Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 12576 was 12576, checked in by epitzer, 9 years ago

#2306 Implement NKq and NKp landscape (and fix Seed parameter clash with Algorithm's seed)

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