Free cookie consent management tool by TermsFeed Policy Generator

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

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

#2306

  • hide weight and interaction initializer parameters
  • hide encoding parameter
  • removed setting of BestKnownQuality
  • added wiring code for interaction and weight initializers that have parameters
  • made all interaction/weight initializers ParameterizedNamedItem
File size: 13.8 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  [Item("NK Landscape", "Represents an NK landscape optimization problem.")]
37  [Creatable("Problems")]
38  [StorableClass]
39  public sealed class NKLandscape : BinaryProblem {
40    public override bool Maximization {
41      get { return false; }
42    }
43
44    #region Parameters
45    public IValueParameter<BoolMatrix> GeneInteractionsParameter {
46      get { return (IValueParameter<BoolMatrix>)Parameters["GeneInteractions"]; }
47    }
48    public IValueParameter<IntValue> SeedParameter {
49      get { return (IValueParameter<IntValue>)Parameters["ProblemSeed"]; }
50    }
51    public IValueParameter<IntValue> InteractionSeedParameter {
52      get { return (IValueParameter<IntValue>)Parameters["InteractionSeed"]; }
53    }
54    public IValueParameter<IntValue> NrOfInteractionsParameter {
55      get { return (IValueParameter<IntValue>)Parameters["NrOfInteractions"]; }
56    }
57    public IValueParameter<IntValue> NrOfFitnessComponentsParameter {
58      get { return (IValueParameter<IntValue>)Parameters["NrOfFitnessComponents"]; }
59    }
60    public IValueParameter<IntValue> QParameter {
61      get { return (IValueParameter<IntValue>)Parameters["Q"]; }
62    }
63    public IValueParameter<DoubleValue> PParameter {
64      get { return (IValueParameter<DoubleValue>)Parameters["P"]; }
65    }
66    public IValueParameter<DoubleArray> WeightsParameter {
67      get { return (IValueParameter<DoubleArray>)Parameters["Weights"]; }
68    }
69    public IConstrainedValueParameter<IInteractionInitializer> InteractionInitializerParameter {
70      get { return (IConstrainedValueParameter<IInteractionInitializer>)Parameters["InteractionInitializer"]; }
71    }
72    public IConstrainedValueParameter<IWeightsInitializer> WeightsInitializerParameter {
73      get { return (IConstrainedValueParameter<IWeightsInitializer>)Parameters["WeightsInitializer"]; }
74    }
75    #endregion
76
77    #region Properties
78    public IInteractionInitializer InteractionInitializer {
79      get { return InteractionInitializerParameter.Value; }
80    }
81    public BoolMatrix GeneInteractions {
82      get { return GeneInteractionsParameter.Value; }
83    }
84    public DoubleArray Weights {
85      get { return WeightsParameter.Value; }
86    }
87    public IntValue InteractionSeed {
88      get { return InteractionSeedParameter.Value; }
89    }
90    public IntValue NrOfFitnessComponents {
91      get { return NrOfFitnessComponentsParameter.Value; }
92    }
93    public IntValue NrOfInteractions {
94      get { return NrOfInteractionsParameter.Value; }
95    }
96    public IWeightsInitializer WeightsInitializer {
97      get { return WeightsInitializerParameter.Value; }
98    }
99    public int Q { get { return QParameter.Value.Value; } }
100    public double P { get { return PParameter.Value.Value; } }
101    public IntValue Seed {
102      get { return SeedParameter.Value; }
103    }
104    #endregion
105
106    [Storable]
107    private MersenneTwister random;
108
109    [ThreadStatic]
110    private static HashAlgorithm hashAlgorithm;
111
112    [ThreadStatic]
113    private static HashAlgorithm hashAlgorithmP;
114
115    public static HashAlgorithm HashAlgorithm {
116      get {
117        if (hashAlgorithm == null) {
118          hashAlgorithm = HashAlgorithm.Create("MD5");
119        }
120        return hashAlgorithm;
121      }
122    }
123
124    public static HashAlgorithm HashAlgorithmP {
125      get {
126        if (hashAlgorithmP == null) {
127          hashAlgorithmP = HashAlgorithm.Create("SHA1");
128        }
129        return hashAlgorithmP;
130      }
131    }
132
133    [StorableConstructor]
134    private NKLandscape(bool deserializing) : base(deserializing) { }
135    private NKLandscape(NKLandscape original, Cloner cloner)
136      : base(original, cloner) {
137      random = (MersenneTwister)original.random.Clone(cloner);
138      RegisterEventHandlers();
139    }
140    public NKLandscape()
141      : base() {
142      random = new MersenneTwister();
143
144      Parameters.Add(new ValueParameter<BoolMatrix>("GeneInteractions", "Every column gives the participating genes for each fitness component"));
145      Parameters.Add(new ValueParameter<IntValue>("ProblemSeed", "The seed used for the random number generator.", new IntValue(0)));
146      random.Reset(Seed.Value);
147
148      Parameters.Add(new ValueParameter<IntValue>("InteractionSeed", "The seed used for the hash function to generate interaction tables.", new IntValue(random.Next())));
149      Parameters.Add(new ValueParameter<IntValue>("NrOfFitnessComponents", "Number of fitness component functions. (nr of columns in the interaction column)", new IntValue(10)));
150      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)));
151      Parameters.Add(new ValueParameter<IntValue>("Q", "Number of allowed fitness values in the (virutal) random table, or zero", new IntValue(0)));
152      Parameters.Add(new ValueParameter<DoubleValue>("P", "Probability of any entry in the (virtual) random table being zero", new DoubleValue(0)));
153      Parameters.Add(new ValueParameter<DoubleArray>("Weights", "The weights for the component functions. If shorted, will be repeated.", new DoubleArray(new[] { 1.0 })));
154      Parameters.Add(new OptionalConstrainedValueParameter<IInteractionInitializer>("InteractionInitializer", "Initialize interactions within the component functions."));
155      Parameters.Add(new OptionalConstrainedValueParameter<IWeightsInitializer>("WeightsInitializer", "Operator to initialize weights distribution"));
156
157      //allow just the standard NK[P,Q] formulations at the moment
158      WeightsParameter.Hidden = true;
159      InteractionInitializerParameter.Hidden = true;
160      WeightsInitializerParameter.Hidden = true;
161      EncodingParameter.Hidden = true;
162
163      InitializeInteractionInitializerParameter();
164      InitializeWeightsInitializerParameter();
165
166      InitializeOperators();
167      InitializeInteractions();
168      RegisterEventHandlers();
169    }
170
171    private void InitializeInteractionInitializerParameter() {
172      foreach (var initializer in ApplicationManager.Manager.GetInstances<IInteractionInitializer>())
173        InteractionInitializerParameter.ValidValues.Add(initializer);
174      InteractionInitializerParameter.Value = InteractionInitializerParameter.ValidValues.First(v => v is RandomInteractionsInitializer);
175    }
176
177    private void InitializeWeightsInitializerParameter() {
178      foreach (var initializer in ApplicationManager.Manager.GetInstances<IWeightsInitializer>())
179        WeightsInitializerParameter.ValidValues.Add(initializer);
180      WeightsInitializerParameter.Value = WeightsInitializerParameter.ValidValues.First(v => v is EqualWeightsInitializer);
181    }
182
183    public override IDeepCloneable Clone(Cloner cloner) {
184      return new NKLandscape(this, cloner);
185    }
186
187    [StorableHook(HookType.AfterDeserialization)]
188    private void AfterDeserialization() {
189      RegisterEventHandlers();
190    }
191
192    private void RegisterEventHandlers() {
193      NrOfInteractionsParameter.ValueChanged += InteractionParameter_ValueChanged;
194      NrOfInteractionsParameter.Value.ValueChanged += InteractionParameter_ValueChanged;
195      NrOfFitnessComponentsParameter.ValueChanged += InteractionParameter_ValueChanged;
196      NrOfFitnessComponentsParameter.Value.ValueChanged += InteractionParameter_ValueChanged;
197      InteractionInitializerParameter.ValueChanged += InteractionParameter_ValueChanged;
198      WeightsInitializerParameter.ValueChanged += WeightsInitializerParameter_ValueChanged;
199      SeedParameter.ValueChanged += SeedParameter_ValueChanged;
200      SeedParameter.Value.ValueChanged += SeedParameter_ValueChanged;
201
202      RegisterInteractionInitializerParameterEvents();
203      RegisterWeightsParameterEvents();
204    }
205
206    private void RegisterWeightsParameterEvents() {
207      foreach (var vv in WeightsInitializerParameter.ValidValues) {
208        foreach (var p in vv.Parameters) {
209          if (p.ActualValue != null && p.ActualValue is IStringConvertibleValue) {
210            var v = (IStringConvertibleValue)p.ActualValue;
211            v.ValueChanged += WeightsInitializerParameter_ValueChanged;
212          }
213        }
214      }
215    }
216
217    private void RegisterInteractionInitializerParameterEvents() {
218      foreach (var vv in InteractionInitializerParameter.ValidValues) {
219        foreach (var p in vv.Parameters) {
220          if (p.ActualValue != null && p.ActualValue is IStringConvertibleValue) {
221            var v = (IStringConvertibleValue)p.ActualValue;
222            v.ValueChanged += InteractionParameter_ValueChanged;
223          } else if (p.ActualValue != null && p is IConstrainedValueParameter<IBinaryVectorComparer>) {
224            ((IConstrainedValueParameter<IBinaryVectorComparer>)p).ValueChanged +=
225              InteractionParameter_ValueChanged;
226          }
227        }
228      }
229    }
230
231    protected override void LengthParameter_ValueChanged(object sender, EventArgs e) {
232      NrOfFitnessComponentsParameter.Value = new IntValue(Length);
233    }
234
235    private void SeedParameter_ValueChanged(object sender, EventArgs e) {
236      random.Reset(Seed.Value);
237      InteractionSeed.Value = random.Next();
238      InitializeInteractions();
239    }
240
241    private void WeightsInitializerParameter_ValueChanged(object sender, EventArgs e) {
242      InitializeWeights();
243    }
244
245    private void InteractionParameter_ValueChanged(object sender, EventArgs e) {
246      InitializeInteractions();
247    }
248
249    private void InitializeOperators() {
250      NKBitFlipMoveEvaluator nkEvaluator = new NKBitFlipMoveEvaluator();
251      Encoding.ConfigureOperator(nkEvaluator);
252      Operators.Add(nkEvaluator);
253    }
254
255    private void InitializeInteractions() {
256      if (InteractionInitializer != null)
257        GeneInteractionsParameter.Value = InteractionInitializer.InitializeInterations(
258          Length,
259          NrOfFitnessComponents.Value,
260          NrOfInteractions.Value, random);
261    }
262
263    private void InitializeWeights() {
264      if (WeightsInitializerParameter.Value != null)
265        WeightsParameter.Value = new DoubleArray(
266          WeightsInitializer.GetWeights(NrOfFitnessComponents.Value)
267          .ToArray());
268    }
269
270    #region Evaluation function
271    private static long Hash(long x, HashAlgorithm hashAlg) {
272      return BitConverter.ToInt64(hashAlg.ComputeHash(BitConverter.GetBytes(x), 0, 8), 0);
273    }
274
275    public static double F_i(long x, long i, long g_i, long seed, int q, double p) {
276      var hash = new Func<long, long>(y => Hash(y, HashAlgorithm));
277      var fi = Math.Abs((double)hash((x & g_i) ^ hash(g_i ^ hash(i ^ seed)))) / long.MaxValue;
278      if (q > 0) { fi = Math.Round(fi * q) / q; }
279      if (p > 0) {
280        hash = y => Hash(y, HashAlgorithmP);
281        var r = Math.Abs((double)hash((x & g_i) ^ hash(g_i ^ hash(i ^ seed)))) / long.MaxValue;
282        fi = (r <= p) ? 0 : fi;
283      }
284      return fi;
285    }
286
287    private static double F(long x, long[] g, double[] w, long seed, ref double[] f_i, int q, double p) {
288      double value = 0;
289      for (int i = 0; i < g.Length; i++) {
290        f_i[i] = F_i(x, i, g[i], seed, q, p);
291        value += w[i % w.Length] * f_i[i];
292      }
293      return value;
294    }
295
296    public static long Encode(BinaryVector v) {
297      long x = 0;
298      for (int i = 0; i < 64 && i < v.Length; i++) {
299        x |= (v[i] ? (long)1 : (long)0) << i;
300      }
301      return x;
302    }
303
304    public static long[] Encode(BoolMatrix m) {
305      long[] x = new long[m.Columns];
306      for (int c = 0; c < m.Columns; c++) {
307        x[c] = 0;
308        for (int r = 0; r < 64 && r < m.Rows; r++) {
309          x[c] |= (m[r, c] ? (long)1 : (long)0) << r;
310        }
311      }
312      return x;
313    }
314
315    public static double[] Normalize(DoubleArray weights) {
316      double sum = 0;
317      double[] w = new double[weights.Length];
318      foreach (var v in weights) {
319        sum += Math.Abs(v);
320      }
321      for (int i = 0; i < weights.Length; i++) {
322        w[i] = Math.Abs(weights[i]) / sum;
323      }
324      return w;
325    }
326
327    public static double Evaluate(BinaryVector vector, BoolMatrix interactions, DoubleArray weights, int seed, out double[] f_i, int q, double p) {
328      long x = Encode(vector);
329      long[] g = Encode(interactions);
330      double[] w = Normalize(weights);
331      f_i = new double[interactions.Columns];
332      return F(x, g, w, (long)seed, ref f_i, q, p);
333    }
334
335    public override double Evaluate(BinaryVector vector, IRandom random) {
336      double[] f_i; //useful for debugging
337      double quality = Evaluate(vector, GeneInteractions, Weights, InteractionSeed.Value, out f_i, Q, P);
338      return quality;
339    }
340    #endregion
341  }
342}
Note: See TracBrowser for help on using the repository browser.