Free cookie consent management tool by TermsFeed Policy Generator

source: branches/EfficientGlobalOptimization/HeuristicLab.Algorithms.EGO/EfficientGlobalOptimizationAlgorithm.cs @ 14768

Last change on this file since 14768 was 14768, checked in by bwerth, 7 years ago

#2745 fixed pausing and stopping and namespaces; Added MaximalDatasetSize and rudimentary ISurrogateAlgorithm-interface

File size: 22.9 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2016 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.Collections.Generic;
24using System.Linq;
25using System.Threading;
26using HeuristicLab.Algorithms.DataAnalysis;
27using HeuristicLab.Analysis;
28using HeuristicLab.Common;
29using HeuristicLab.Core;
30using HeuristicLab.Data;
31using HeuristicLab.Encodings.RealVectorEncoding;
32using HeuristicLab.Optimization;
33using HeuristicLab.Parameters;
34using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
35using HeuristicLab.Problems.DataAnalysis;
36using HeuristicLab.Random;
37
38namespace HeuristicLab.Algorithms.EGO {
39  [StorableClass]
40  [Creatable(CreatableAttribute.Categories.Algorithms, Priority = 95)]
41  [Item("EfficientGlobalOptimizationAlgortihm", "Solves a problem by sequentially learning a model, solving a subproblem on the model and evaluating the best found solution for this subproblem.")]
42  public class EfficientGlobalOptimizationAlgorithm : BasicAlgorithm, ISurrogateAlgorithm<RealVector> {
43    #region Basic-Alg-Essentials
44    public override bool SupportsPause => true;
45    public override Type ProblemType => typeof(SingleObjectiveBasicProblem<IEncoding>);
46    public new SingleObjectiveBasicProblem<IEncoding> Problem
47    {
48      get { return (SingleObjectiveBasicProblem<IEncoding>)base.Problem; }
49      set { base.Problem = value; }
50    }
51    #endregion
52
53    #region ParameterNames
54    private const string GenerationSizeParameterName = "GenerationSize";
55    private const string InfillCriterionParameterName = "InfillCriterion";
56    private const string InfillOptimizationAlgorithmParameterName = "InfillOptimizationAlgorithm";
57    private const string InfillOptimizationRestartsParameterName = "InfillOptimizationRestarts";
58    private const string InitialEvaluationsParameterName = "Initial Evaluations";
59    private const string MaximumIterationsParameterName = "Maximum Iterations";
60    private const string MaximumRuntimeParameterName = "Maximum Runtime";
61    private const string RegressionAlgorithmParameterName = "RegressionAlgorithm";
62    private const string SeedParameterName = "Seed";
63    private const string SetSeedRandomlyParameterName = "SetSeedRandomly";
64    private const string MaximalDataSetSizeParameterName = "MaximalDataSetSize";
65    #endregion
66
67    #region ResultNames
68    private const string BestQualityResultName = "Best Quality";
69    private const string BestSolutionResultName = "Best Solution";
70    private const string EvaluatedSoultionsResultName = "EvaluatedSolutions";
71    private const string IterationsResultName = "Iterations";
72    private const string RegressionSolutionResultName = "Model";
73    private const string QualitiesChartResultName = "Qualities";
74    private const string BestQualitiesRowResultName = "Best Quality";
75    private const string CurrentQualitiesRowResultName = "Current Quality";
76    private const string WorstQualitiesRowResultName = "Worst Quality";
77    #endregion
78
79    #region TransmissionResultNames
80    public const string BestInfillSolutionResultName = "BestInfillSolution";
81    public const string BestInfillQualityResultName = "BestInfillQuality";
82    #endregion
83
84    #region ParameterProperties
85    public IFixedValueParameter<IntValue> GenerationSizeParemeter => Parameters[GenerationSizeParameterName] as IFixedValueParameter<IntValue>;
86    public IConstrainedValueParameter<IInfillCriterion> InfillCriterionParameter => Parameters[InfillCriterionParameterName] as IConstrainedValueParameter<IInfillCriterion>;
87    public IValueParameter<Algorithm> InfillOptimizationAlgorithmParameter => Parameters[InfillOptimizationAlgorithmParameterName] as IValueParameter<Algorithm>;
88    public IFixedValueParameter<IntValue> InfillOptimizationRestartsParemeter => Parameters[InfillOptimizationRestartsParameterName] as IFixedValueParameter<IntValue>;
89    public IFixedValueParameter<IntValue> InitialEvaluationsParameter => Parameters[InitialEvaluationsParameterName] as IFixedValueParameter<IntValue>;
90    public IFixedValueParameter<IntValue> MaximumIterationsParameter => Parameters[MaximumIterationsParameterName] as IFixedValueParameter<IntValue>;
91    public IFixedValueParameter<IntValue> MaximumRuntimeParameter => Parameters[MaximumRuntimeParameterName] as IFixedValueParameter<IntValue>;
92    public IValueParameter<IDataAnalysisAlgorithm<IRegressionProblem>> RegressionAlgorithmParameter => Parameters[RegressionAlgorithmParameterName] as IValueParameter<IDataAnalysisAlgorithm<IRegressionProblem>>;
93    public IFixedValueParameter<IntValue> SeedParameter => Parameters[SeedParameterName] as IFixedValueParameter<IntValue>;
94    public IFixedValueParameter<BoolValue> SetSeedRandomlyParameter => Parameters[SetSeedRandomlyParameterName] as IFixedValueParameter<BoolValue>;
95    public IFixedValueParameter<IntValue> MaximalDataSetSizeParameter => Parameters[MaximalDataSetSizeParameterName] as IFixedValueParameter<IntValue>;
96    #endregion
97
98    #region Properties
99
100    public int GenerationSize
101    {
102      get { return GenerationSizeParemeter.Value.Value; }
103    }
104    public IInfillCriterion InfillCriterion
105    {
106      get { return InfillCriterionParameter.Value; }
107    }
108    public Algorithm InfillOptimizationAlgorithm
109    {
110      get { return InfillOptimizationAlgorithmParameter.Value; }
111    }
112    public int InfillOptimizationRestarts
113    {
114      get { return InfillOptimizationRestartsParemeter.Value.Value; }
115    }
116    public int InitialEvaluations
117    {
118      get { return InitialEvaluationsParameter.Value.Value; }
119    }
120    public int MaximumIterations
121    {
122      get { return MaximumIterationsParameter.Value.Value; }
123    }
124    public int MaximumRuntime
125    {
126      get { return MaximumRuntimeParameter.Value.Value; }
127    }
128    public IDataAnalysisAlgorithm<IRegressionProblem> RegressionAlgorithm
129    {
130      get { return RegressionAlgorithmParameter.Value; }
131    }
132    public int Seed
133    {
134      get { return SeedParameter.Value.Value; }
135    }
136    public bool SetSeedRandomly
137    {
138      get { return SetSeedRandomlyParameter.Value.Value; }
139    }
140    public int MaximalDatasetSize
141    {
142      get { return MaximalDataSetSizeParameter.Value.Value; }
143    }
144
145    private IEnumerable<Tuple<RealVector, double>> DataSamples
146    {
147      get
148      {
149        return Samples.Count > MaximalDatasetSize && MaximalDatasetSize > 0
150          ? Samples.Skip(Samples.Count - MaximalDatasetSize)
151          : Samples;
152      }
153    }
154
155    #endregion
156
157    #region StorableProperties
158    [Storable]
159    private IRandom Random = new MersenneTwister();
160    [Storable]
161    private List<Tuple<RealVector, double>> Samples;
162    [Storable]
163    private List<Tuple<RealVector, double>> InitialSamples;
164    #endregion
165
166    #region ResultsProperties
167    private double ResultsBestQuality
168    {
169      get { return ((DoubleValue)Results[BestQualityResultName].Value).Value; }
170      set { ((DoubleValue)Results[BestQualityResultName].Value).Value = value; }
171    }
172    private RealVector ResultsBestSolution
173    {
174      get { return (RealVector)Results[BestSolutionResultName].Value; }
175      set { Results[BestSolutionResultName].Value = value; }
176    }
177    private int ResultsEvaluations
178    {
179      get { return ((IntValue)Results[EvaluatedSoultionsResultName].Value).Value; }
180      set { ((IntValue)Results[EvaluatedSoultionsResultName].Value).Value = value; }
181    }
182    private int ResultsIterations
183    {
184      get { return ((IntValue)Results[IterationsResultName].Value).Value; }
185      set { ((IntValue)Results[IterationsResultName].Value).Value = value; }
186    }
187    private DataTable ResultsQualities
188    {
189      get { return (DataTable)Results[QualitiesChartResultName].Value; }
190    }
191    private DataRow ResultsQualitiesBest
192    {
193      get { return ResultsQualities.Rows[BestQualitiesRowResultName]; }
194    }
195    private DataRow ResultsQualitiesWorst
196    {
197      get { return ResultsQualities.Rows[WorstQualitiesRowResultName]; }
198    }
199    private DataRow ResultsQualitiesIteration
200    {
201      get { return ResultsQualities.Rows[CurrentQualitiesRowResultName]; }
202    }
203    private IRegressionSolution ResultsModel
204    {
205      get { return (IRegressionSolution)Results[RegressionSolutionResultName].Value; }
206      set { Results[RegressionSolutionResultName].Value = value; }
207    }
208    #endregion
209
210    #region HLConstructors
211    [StorableConstructor]
212    protected EfficientGlobalOptimizationAlgorithm(bool deserializing) : base(deserializing) { }
213    [StorableHook(HookType.AfterDeserialization)]
214    private void AfterDeseialization() {
215      RegisterEventhandlers();
216    }
217    protected EfficientGlobalOptimizationAlgorithm(EfficientGlobalOptimizationAlgorithm original, Cloner cloner)
218      : base(original, cloner) {
219      Random = cloner.Clone(Random);
220      if (original.Samples != null) Samples = original.Samples.Select(x => new Tuple<RealVector, double>(cloner.Clone(x.Item1), x.Item2)).ToList();
221      if (original.InitialSamples != null) Samples = original.InitialSamples.Select(x => new Tuple<RealVector, double>(cloner.Clone(x.Item1), x.Item2)).ToList();
222      RegisterEventhandlers();
223    }
224    public override IDeepCloneable Clone(Cloner cloner) { return new EfficientGlobalOptimizationAlgorithm(this, cloner); }
225    public EfficientGlobalOptimizationAlgorithm() {
226      var cmaes = new CMAEvolutionStrategy.CMAEvolutionStrategy {
227        MaximumGenerations = 300,
228        PopulationSize = 50
229      };
230      var model = new GaussianProcessRegression {
231        Problem = new RegressionProblem()
232      };
233      model.CovarianceFunctionParameter.Value = new CovarianceRationalQuadraticIso();
234      Parameters.Add(new FixedValueParameter<IntValue>(MaximumIterationsParameterName, "", new IntValue(int.MaxValue)));
235      Parameters.Add(new FixedValueParameter<IntValue>(InitialEvaluationsParameterName, "", new IntValue(10)));
236      Parameters.Add(new FixedValueParameter<IntValue>(MaximumRuntimeParameterName, "The maximum runtime in seconds after which the algorithm stops. Use -1 to specify no limit for the runtime", new IntValue(3600)));
237      Parameters.Add(new FixedValueParameter<IntValue>(SeedParameterName, "The random seed used to initialize the new pseudo random number generator.", new IntValue(0)));
238      Parameters.Add(new FixedValueParameter<BoolValue>(SetSeedRandomlyParameterName, "True if the random seed should be set to a random value, otherwise false.", new BoolValue(true)));
239      Parameters.Add(new ValueParameter<IDataAnalysisAlgorithm<IRegressionProblem>>(RegressionAlgorithmParameterName, "The model used to approximate the problem", model));
240      Parameters.Add(new ValueParameter<Algorithm>(InfillOptimizationAlgorithmParameterName, "The algorithm used to solve the expected improvement subproblem", cmaes));
241      Parameters.Add(new FixedValueParameter<IntValue>(InfillOptimizationRestartsParameterName, "Number of restarts of the SubAlgortihm to avoid local optima", new IntValue(1)));
242      Parameters.Add(new FixedValueParameter<IntValue>(GenerationSizeParameterName, "Number points that are sampled every iteration (stadard EGO: 1)", new IntValue(1)));
243      Parameters.Add(new ConstrainedValueParameter<IInfillCriterion>(InfillCriterionParameterName, "Decision what value should decide the next sample"));
244      InfillCriterionParameter.ValidValues.Add(new ExpectedImprovement());
245      InfillCriterionParameter.ValidValues.Add(new ExpectedQuality());
246      InfillCriterionParameter.ValidValues.Add(new ConfidenceBound());
247      Parameters.Add(new FixedValueParameter<IntValue>(MaximalDataSetSizeParameterName, "The maximum number of sample points used to generate the model. Set 0 or less to use always all samples ", new IntValue(-1)));
248
249      SetInfillProblem();
250      RegisterEventhandlers();
251    }
252    #endregion
253
254    protected override void Initialize(CancellationToken cancellationToken) {
255      base.Initialize(cancellationToken);
256      //encoding
257      var enc = Problem.Encoding as RealVectorEncoding;
258      if (enc == null) throw new ArgumentException("The EGO algorithm can only be applied to RealVectorEncodings");
259
260      //random
261      if (SetSeedRandomly) SeedParameter.Value.Value = new System.Random().Next();
262      Random.Reset(Seed);
263      Samples = InitialSamples == null ? new List<Tuple<RealVector, double>>() : InitialSamples.ToList();
264
265      //results
266      Results.Add(new Result(IterationsResultName, new IntValue(0)));
267      Results.Add(new Result(EvaluatedSoultionsResultName, new IntValue(Samples.Count)));
268      Results.Add(new Result(BestSolutionResultName, new RealVector(1)));
269      Results.Add(new Result(BestQualityResultName, new DoubleValue(Problem.Maximization ? double.MinValue : double.MaxValue)));
270      Results.Add(new Result(RegressionSolutionResultName, typeof(IRegressionSolution)));
271      var table = new DataTable(QualitiesChartResultName);
272      table.Rows.Add(new DataRow(BestQualitiesRowResultName));
273      table.Rows.Add(new DataRow(WorstQualitiesRowResultName));
274      table.Rows.Add(new DataRow(CurrentQualitiesRowResultName));
275      Results.Add(new Result(QualitiesChartResultName, table));
276
277      //initial samples
278      if (Samples.Count < InitialEvaluations) {
279        var points = EgoUtilities.GetUniformRandomDesign(InitialEvaluations - Samples.Count, enc.Length, enc.Bounds, Random);
280        foreach (var t in points) {
281          Samples.Add(Evaluate(t));
282          cancellationToken.ThrowIfCancellationRequested();
283        }
284      }
285
286      Analyze();
287    }
288
289    protected override void Run(CancellationToken cancellationToken) {
290      for (ResultsIterations = 0; ResultsIterations < MaximumIterations; ResultsIterations++) {
291        try {
292          ResultsModel = BuildModel(cancellationToken);
293          cancellationToken.ThrowIfCancellationRequested();
294          for (var i = 0; i < GenerationSize; i++) {
295            var samplepoint = OptimizeInfillProblem();
296            var sample = Evaluate(samplepoint);
297            Samples.Add(sample);
298            cancellationToken.ThrowIfCancellationRequested();
299          }
300
301        }
302        finally {
303          Analyze();
304        }
305      }
306    }
307
308    public void SetInitialSamples(RealVector[] individuals, double[] qualities) {
309      InitialSamples = individuals.Zip(qualities, (individual, d) => new Tuple<RealVector, double>(individual, d)).ToList();
310    }
311
312    #region Eventhandling
313    private void RegisterEventhandlers() {
314      DeregisterEventhandlers();
315      RegressionAlgorithmParameter.ValueChanged += OnModelAlgorithmChanged;
316      InfillOptimizationAlgorithmParameter.ValueChanged += OnInfillOptimizationAlgorithmChanged;
317      InfillOptimizationAlgorithm.ProblemChanged += InfillOptimizationProblemChanged;
318      InfillCriterionParameter.ValueChanged += InfillCriterionChanged;
319
320    }
321    private void DeregisterEventhandlers() {
322      RegressionAlgorithmParameter.ValueChanged -= OnModelAlgorithmChanged;
323      InfillOptimizationAlgorithmParameter.ValueChanged -= OnInfillOptimizationAlgorithmChanged;
324      InfillOptimizationAlgorithm.ProblemChanged -= InfillOptimizationProblemChanged;
325      InfillCriterionParameter.ValueChanged -= InfillCriterionChanged;
326    }
327    private void OnInfillOptimizationAlgorithmChanged(object sender, EventArgs args) {
328      SetInfillProblem();
329      InfillOptimizationAlgorithm.ProblemChanged -= InfillOptimizationProblemChanged;
330      InfillOptimizationAlgorithm.ProblemChanged += InfillOptimizationProblemChanged;
331    }
332    private void InfillOptimizationProblemChanged(object sender, EventArgs e) {
333      InfillOptimizationAlgorithm.ProblemChanged -= InfillOptimizationProblemChanged;
334      SetInfillProblem();
335      InfillOptimizationAlgorithm.ProblemChanged += InfillOptimizationProblemChanged;
336    }
337    private void InfillCriterionChanged(object sender, EventArgs e) {
338      var infillProblem = InfillOptimizationAlgorithm.Problem as InfillProblem;
339      if (infillProblem == null) throw new ArgumentException("InfillOptimizationAlgorithm has no InfillProblem. Troubles with Eventhandling?");
340      infillProblem.InfillCriterion = InfillCriterion;
341    }
342    private void OnModelAlgorithmChanged(object sender, EventArgs args) {
343      RegressionAlgorithm.Problem = new RegressionProblem();
344    }
345    protected override void OnExecutionTimeChanged() {
346      base.OnExecutionTimeChanged();
347      if (CancellationTokenSource == null) return;
348      if (MaximumRuntime == -1) return;
349      if (ExecutionTime.TotalSeconds > MaximumRuntime) CancellationTokenSource.Cancel();
350    }
351    public override void Pause() {
352      if (InfillOptimizationAlgorithm.ExecutionState == ExecutionState.Started) InfillOptimizationAlgorithm.Pause();
353      if (RegressionAlgorithm.ExecutionState == ExecutionState.Started) RegressionAlgorithm.Pause();
354      base.Pause();
355    }
356    public override void Stop() {
357      if (InfillOptimizationAlgorithm.ExecutionState == ExecutionState.Started || InfillOptimizationAlgorithm.ExecutionState == ExecutionState.Paused) InfillOptimizationAlgorithm.Stop();
358      if (RegressionAlgorithm.ExecutionState == ExecutionState.Started || RegressionAlgorithm.ExecutionState == ExecutionState.Paused) RegressionAlgorithm.Stop();
359      base.Stop();
360    }
361    protected override void OnProblemChanged() {
362      base.OnProblemChanged();
363      var infillProblem = InfillOptimizationAlgorithm.Problem as InfillProblem;
364      if (infillProblem == null) throw new ArgumentException("InfillOptimizationAlgorithm has no InfillProblem. Troubles with Eventhandling?");
365      infillProblem.Problem = Problem;
366    }
367    #endregion
368
369    #region helpers
370    private void SetInfillProblem() {
371      var infillProblem = new InfillProblem {
372        InfillCriterion = InfillCriterion,
373        Problem = Problem
374      };
375      InfillOptimizationAlgorithm.Problem = infillProblem;
376    }
377    private IRegressionSolution BuildModel(CancellationToken cancellationToken) {
378      var dataset = EgoUtilities.GetDataSet(DataSamples.ToList());
379      var problemdata = new RegressionProblemData(dataset, dataset.VariableNames.Where(x => !x.Equals("output")), "output");
380      problemdata.TrainingPartition.Start = 0;
381      problemdata.TrainingPartition.End = dataset.Rows;
382      problemdata.TestPartition.Start = dataset.Rows;
383      problemdata.TestPartition.End = dataset.Rows;
384
385      //train
386      var problem = (RegressionProblem)RegressionAlgorithm.Problem;
387      problem.ProblemDataParameter.Value = problemdata;
388      var i = 0;
389      IRegressionSolution solution = null;
390      double r2 = 0;
391      while ((solution == null || RegressionAlgorithm is GaussianProcessRegression && r2 < 0.95) && i++ < 100) {  //TODO: ask why GP degenerates to NaN so often
392        var results = EgoUtilities.SyncRunSubAlgorithm(RegressionAlgorithm, Random.Next(int.MaxValue));
393        solution = results.Select(x => x.Value).OfType<IRegressionSolution>().SingleOrDefault();
394        r2 = solution?.TrainingRSquared ?? 0;
395        cancellationToken.ThrowIfCancellationRequested();
396      }
397
398      if (solution == null) throw new ArgumentException("The Algorithm did not return a Model");
399      RegressionAlgorithm.Runs.Clear();
400      return solution;
401    }
402    private RealVector OptimizeInfillProblem() {
403      //parameterize and check InfillProblem
404      var infillProblem = InfillOptimizationAlgorithm.Problem as InfillProblem;
405      if (infillProblem == null) throw new ArgumentException("InfillOptimizationAlgorithm does not have InfillProblem. Problem with Eventhandling?");
406      if (infillProblem.InfillCriterion != InfillCriterion) throw new ArgumentException("InfillCiriterion for Problem is not correct. Problem with Eventhandling?");
407      if (infillProblem.Problem != Problem) throw new ArgumentException("Expensive real problem is not correctly set in InfillProblem. Problem with Eventhandling?");
408      infillProblem.RegressionSolution = ResultsModel;
409      if (MaximalDatasetSize > 0 && MaximalDatasetSize < Samples.Count) { infillProblem.Encoding.Bounds = EgoUtilities.GetBoundingBox(DataSamples.Select(x => x.Item1)); }
410
411      RealVector bestVector = null;
412      var bestValue = infillProblem.Maximization ? double.NegativeInfinity : double.PositiveInfinity;
413
414      for (var i = 0; i < InfillOptimizationRestarts; i++) {
415        //optimize
416        var res = EgoUtilities.SyncRunSubAlgorithm(InfillOptimizationAlgorithm, Random.Next(int.MaxValue));
417
418        //extract results
419        if (!res.ContainsKey(BestInfillSolutionResultName)) throw new ArgumentException("The InfillOptimizationAlgorithm did not return a best solution");
420        var v = res[BestInfillSolutionResultName].Value as RealVector;
421        if (!res.ContainsKey(BestInfillQualityResultName)) throw new ArgumentException("The InfillOptimizationAlgorithm did not return a best quality");
422        var d = res[BestInfillQualityResultName].Value as DoubleValue;
423        if (d == null || v == null) throw new ArgumentException("The InfillOptimizationAlgorithm did not return the expected result types");
424
425        //check for improvement
426        if (infillProblem.Maximization != d.Value > bestValue) continue;
427        bestValue = d.Value;
428        bestVector = v;
429      }
430
431      InfillOptimizationAlgorithm.Runs.Clear();
432      return bestVector;
433    }
434    private Tuple<RealVector, double> Evaluate(RealVector point) {
435      return new Tuple<RealVector, double>(point, Problem.Evaluate(GetIndividual(point), Random));
436    }
437    private void Analyze() {
438      ResultsEvaluations = Samples.Count;
439      var max = Samples.ArgMax(x => x.Item2);
440      var min = Samples.ArgMin(x => x.Item2);
441      var best = Samples[Problem.Maximization ? max : min];
442      ResultsBestQuality = best.Item2;
443      ResultsBestSolution = best.Item1;
444      ResultsQualitiesBest.Values.Add(ResultsBestQuality);
445      ResultsQualitiesIteration.Values.Add(Samples[Samples.Count - 1].Item2);
446      ResultsQualitiesWorst.Values.Add(Samples[Problem.Maximization ? min : max].Item2);
447      Problem.Analyze(Samples.Select(x => GetIndividual(x.Item1)).ToArray(), Samples.Select(x => x.Item2).ToArray(), Results, Random);
448    }
449    private Individual GetIndividual(RealVector r) {
450      var scope = new Scope();
451      scope.Variables.Add(new Variable(Problem.Encoding.Name, r));
452      return new SingleEncodingIndividual(Problem.Encoding, scope);
453    }
454    #endregion
455  }
456}
Note: See TracBrowser for help on using the repository browser.