Free cookie consent management tool by TermsFeed Policy Generator

source: branches/FitnessLandscapeAnalysis/HeuristicLab.Problems.NK/NKLandscape.cs @ 12582

Last change on this file since 12582 was 12582, checked in by ascheibe, 9 years ago

#2306 made comparers and initializers consistent

File size: 12.6 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Linq;
24using System.Security.Cryptography;
25using HeuristicLab.Common;
26using HeuristicLab.Core;
27using HeuristicLab.Data;
28using HeuristicLab.Encodings.BinaryVectorEncoding;
29using HeuristicLab.Parameters;
30using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
31using HeuristicLab.PluginInfrastructure;
32using HeuristicLab.Problems.Binary;
33using HeuristicLab.Random;
34
35namespace HeuristicLab.Problems.NK {
36
37  [Item("NK Landscape", "Represents an NK landscape optimization problem.")]
38  [Creatable("Problems")]
39  [StorableClass]
40  public sealed class NKLandscape : BinaryProblem {
41    public override bool Maximization {
42      get { return false; }
43    }
44
45    #region Parameters
46    public IValueParameter<BoolMatrix> GeneInteractionsParameter {
47      get { return (IValueParameter<BoolMatrix>)Parameters["GeneInteractions"]; }
48    }
49    public IValueParameter<IntValue> SeedParameter {
50      get { return (IValueParameter<IntValue>)Parameters["ProblemSeed"]; }
51    }
52    public IValueParameter<IntValue> InteractionSeedParameter {
53      get { return (IValueParameter<IntValue>)Parameters["InteractionSeed"]; }
54    }
55    public IValueParameter<IntValue> NrOfInteractionsParameter {
56      get { return (IValueParameter<IntValue>)Parameters["NrOfInteractions"]; }
57    }
58    public IValueParameter<IntValue> NrOfFitnessComponentsParameter {
59      get { return (IValueParameter<IntValue>)Parameters["NrOfFitnessComponents"]; }
60    }
61    public IValueParameter<IntValue> QParameter {
62      get { return (IValueParameter<IntValue>)Parameters["Q"]; }
63    }
64    public IValueParameter<DoubleValue> PParameter {
65      get { return (IValueParameter<DoubleValue>)Parameters["P"]; }
66    }
67    public IValueParameter<DoubleArray> WeightsParameter {
68      get { return (IValueParameter<DoubleArray>)Parameters["Weights"]; }
69    }
70    public IConstrainedValueParameter<IInteractionInitializer> InteractionInitializerParameter {
71      get { return (IConstrainedValueParameter<IInteractionInitializer>)Parameters["InteractionInitializer"]; }
72    }
73    public IConstrainedValueParameter<IWeightsInitializer> WeightsInitializerParameter {
74      get { return (IConstrainedValueParameter<IWeightsInitializer>)Parameters["WeightsInitializer"]; }
75    }
76    #endregion
77
78    #region Properties
79    public IInteractionInitializer InteractionInitializer {
80      get { return InteractionInitializerParameter.Value; }
81    }
82    public BoolMatrix GeneInteractions {
83      get { return GeneInteractionsParameter.Value; }
84    }
85    public DoubleArray Weights {
86      get { return WeightsParameter.Value; }
87    }
88    public IntValue InteractionSeed {
89      get { return InteractionSeedParameter.Value; }
90    }
91    public IntValue NrOfFitnessComponents {
92      get { return NrOfFitnessComponentsParameter.Value; }
93    }
94    public IntValue NrOfInteractions {
95      get { return NrOfInteractionsParameter.Value; }
96    }
97    public IWeightsInitializer WeightsInitializer {
98      get { return WeightsInitializerParameter.Value; }
99    }
100    public int Q { get { return QParameter.Value.Value; } }
101    public double P { get { return PParameter.Value.Value; } }
102    public IntValue Seed {
103      get { return SeedParameter.Value; }
104    }
105    #endregion
106
107    [Storable]
108    private MersenneTwister random;
109
110    [ThreadStatic]
111    private static HashAlgorithm hashAlgorithm;
112
113    [ThreadStatic]
114    private static HashAlgorithm hashAlgorithmP;
115
116    public static HashAlgorithm HashAlgorithm {
117      get {
118        if (hashAlgorithm == null) {
119          hashAlgorithm = HashAlgorithm.Create("MD5");
120        }
121        return hashAlgorithm;
122      }
123    }
124
125    public static HashAlgorithm HashAlgorithmP {
126      get {
127        if (hashAlgorithmP == null) {
128          hashAlgorithmP = HashAlgorithm.Create("SHA1");
129        }
130        return hashAlgorithmP;
131      }
132    }
133
134    [StorableConstructor]
135    private NKLandscape(bool deserializing) : base(deserializing) { }
136    private NKLandscape(NKLandscape original, Cloner cloner)
137      : base(original, cloner) {
138      random = (MersenneTwister)original.random.Clone(cloner);
139      RegisterEventHandlers();
140    }
141    public NKLandscape()
142      : base() {
143      random = new MersenneTwister();
144
145      Parameters.Add(new ValueParameter<BoolMatrix>("GeneInteractions", "Every column gives the participating genes for each fitness component"));
146      Parameters.Add(new ValueParameter<IntValue>("ProblemSeed", "The seed used for the random number generator.", new IntValue(0)));
147      random.Reset(Seed.Value);
148
149      Parameters.Add(new ValueParameter<IntValue>("InteractionSeed", "The seed used for the hash function to generate interaction tables.", new IntValue(random.Next())));
150      Parameters.Add(new ValueParameter<IntValue>("NrOfFitnessComponents", "Number of fitness component functions. (nr of columns in the interaction column)", new IntValue(10)));
151      Parameters.Add(new ValueParameter<IntValue>("NrOfInteractions", "Number of genes interacting with each other. (nr of True values per column in the interaction matrix)", new IntValue(3)));
152      Parameters.Add(new ValueParameter<IntValue>("Q", "Number of allowed fitness values in the (virutal) random table, or zero", new IntValue(0)));
153      Parameters.Add(new ValueParameter<DoubleValue>("P", "Probability of any entry in the (virtual) random table being zero", new DoubleValue(0)));
154      Parameters.Add(new ValueParameter<DoubleArray>("Weights", "The weights for the component functions. If shorted, will be repeated.", new DoubleArray(new[] { 1.0 })));
155      Parameters.Add(new OptionalConstrainedValueParameter<IInteractionInitializer>("InteractionInitializer", "Initialize interactions within the component functions."));
156      Parameters.Add(new OptionalConstrainedValueParameter<IWeightsInitializer>("WeightsInitializer", "Operator to initialize weights distribution"));
157
158      InitializeInteractionInitializerParameter();
159      InitializeWeightsInitializerParameter();
160
161      InitializeOperators();
162      RegisterEventHandlers();
163      InitializeInteractions();
164    }
165
166    private void InitializeInteractionInitializerParameter() {
167      foreach (var initializer in ApplicationManager.Manager.GetInstances<IInteractionInitializer>())
168        InteractionInitializerParameter.ValidValues.Add(initializer);
169      InteractionInitializerParameter.Value = InteractionInitializerParameter.ValidValues.First(v => v is RandomInteractionsInitializer);
170    }
171
172    private void InitializeWeightsInitializerParameter() {
173      foreach (var initializer in ApplicationManager.Manager.GetInstances<IWeightsInitializer>())
174        WeightsInitializerParameter.ValidValues.Add(initializer);
175      WeightsInitializerParameter.Value = WeightsInitializerParameter.ValidValues.First(v => v is EqualWeightsInitializer);
176    }
177
178    public override IDeepCloneable Clone(Cloner cloner) {
179      return new NKLandscape(this, cloner);
180    }
181
182    #region Events
183    protected override void LengthParameter_ValueChanged(object sender, EventArgs e) {
184      BestKnownQualityParameter.Value = new DoubleValue(Length);
185      NrOfFitnessComponentsParameter.Value = new IntValue(Length);
186    }
187    #endregion
188
189    #region Helpers
190    [StorableHook(HookType.AfterDeserialization)]
191    private void AfterDeserialization() {
192      RegisterEventHandlers();
193    }
194
195    private void RegisterEventHandlers() {
196      NrOfInteractionsParameter.ValueChanged += InteractionParameterChanged;
197      NrOfInteractionsParameter.Value.ValueChanged += InteractionParameterChanged;
198      NrOfFitnessComponentsParameter.ValueChanged += InteractionParameterChanged;
199      NrOfFitnessComponentsParameter.Value.ValueChanged += InteractionParameterChanged;
200      InteractionInitializerParameter.ValueChanged += InteractionInitializerParameter_ValueChanged;
201      WeightsInitializerParameter.ValueChanged += WeightsInitializerParameter_ValueChanged;
202      SeedParameter.ValueChanged += SeedParameter_ValueChanged;
203      SeedParameter.Value.ValueChanged += SeedParameter_ValueChanged;
204    }
205
206    private void SeedParameter_ValueChanged(object sender, EventArgs e) {
207      random.Reset(Seed.Value);
208      InteractionSeed.Value = random.Next();
209      InitializeInteractions();
210    }
211
212    private void WeightsInitializerParameter_ValueChanged(object sender, EventArgs e) {
213      InitializeWeights();
214    }
215
216    private void InteractionInitializerParameter_ValueChanged(object sender, EventArgs e) {
217      InitializeInteractions();
218    }
219
220    private void InteractionParameterChanged(object sender, EventArgs e) {
221      InitializeInteractions();
222    }
223
224    private void InitializeOperators() {
225      NKBitFlipMoveEvaluator nkEvaluator = new NKBitFlipMoveEvaluator();
226      Encoding.ConfigureOperator(nkEvaluator);
227      Operators.Add(nkEvaluator);
228    }
229
230    private void InitializeInteractions() {
231      if (InteractionInitializer != null)
232        GeneInteractionsParameter.Value = InteractionInitializer.InitializeInterations(
233          Length,
234          NrOfFitnessComponents.Value,
235          NrOfInteractions.Value, random);
236    }
237
238    private void InitializeWeights() {
239      if (WeightsInitializerParameter.Value != null)
240        WeightsParameter.Value = new DoubleArray(
241          WeightsInitializer.GetWeights(NrOfFitnessComponents.Value)
242          .ToArray());
243    }
244    #endregion
245
246    #region Evaluation function
247    private static long Hash(long x, HashAlgorithm hashAlg) {
248      return BitConverter.ToInt64(hashAlg.ComputeHash(BitConverter.GetBytes(x), 0, 8), 0);
249    }
250
251    public static double F_i(long x, long i, long g_i, long seed, int q, double p) {
252      var hash = new Func<long, long>(y => Hash(y, HashAlgorithm));
253      var fi = Math.Abs((double)hash((x & g_i) ^ hash(g_i ^ hash(i ^ seed)))) / long.MaxValue;
254      if (q > 0) { fi = Math.Round(fi * q) / q; }
255      if (p > 0) {
256        hash = y => Hash(y, HashAlgorithmP);
257        var r = Math.Abs((double)hash((x & g_i) ^ hash(g_i ^ hash(i ^ seed)))) / long.MaxValue;
258        fi = (r <= p) ? 0 : fi;
259      }
260      return fi;
261    }
262
263    private static double F(long x, long[] g, double[] w, long seed, ref double[] f_i, int q, double p) {
264      double value = 0;
265      for (int i = 0; i < g.Length; i++) {
266        f_i[i] = F_i(x, i, g[i], seed, q, p);
267        value += w[i % w.Length] * f_i[i];
268      }
269      return value;
270    }
271
272    public static long Encode(BinaryVector v) {
273      long x = 0;
274      for (int i = 0; i < 64 && i < v.Length; i++) {
275        x |= (v[i] ? (long)1 : (long)0) << i;
276      }
277      return x;
278    }
279
280    public static long[] Encode(BoolMatrix m) {
281      long[] x = new long[m.Columns];
282      for (int c = 0; c < m.Columns; c++) {
283        x[c] = 0;
284        for (int r = 0; r < 64 && r < m.Rows; r++) {
285          x[c] |= (m[r, c] ? (long)1 : (long)0) << r;
286        }
287      }
288      return x;
289    }
290
291    public static double[] Normalize(DoubleArray weights) {
292      double sum = 0;
293      double[] w = new double[weights.Length];
294      foreach (var v in weights) {
295        sum += Math.Abs(v);
296      }
297      for (int i = 0; i < weights.Length; i++) {
298        w[i] = Math.Abs(weights[i]) / sum;
299      }
300      return w;
301    }
302
303    public static double Evaluate(BinaryVector vector, BoolMatrix interactions, DoubleArray weights, int seed, out double[] f_i, int q, double p) {
304      long x = Encode(vector);
305      long[] g = Encode(interactions);
306      double[] w = Normalize(weights);
307      f_i = new double[interactions.Columns];
308      return F(x, g, w, (long)seed, ref f_i, q, p);
309    }
310
311    public override double Evaluate(BinaryVector vector, IRandom random) {
312      double[] f_i; //useful for debugging
313      double quality = Evaluate(vector, GeneInteractions, Weights, InteractionSeed.Value, out f_i, Q, P);
314      return quality;
315    }
316    #endregion
317  }
318}
Note: See TracBrowser for help on using the repository browser.