Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.Problems.NK/3.3/NKLandscape.cs @ 17398

Last change on this file since 17398 was 17180, checked in by swagner, 5 years ago

#2875: Removed years in copyrights

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