source: branches/2521_ProblemRefactoring/HeuristicLab.Problems.TestFunctions/3.3/SingleObjectiveTestFunctionProblem.cs @ 17382

Last change on this file since 17382 was 17382, checked in by mkommend, 7 months ago

#2521: Refactored single-objective problems to use EvaluationResult instead of double as return type from Evaluate.

File size: 11.7 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 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 HEAL.Attic;
27using HeuristicLab.Analysis;
28using HeuristicLab.Common;
29using HeuristicLab.Core;
30using HeuristicLab.Data;
31using HeuristicLab.Encodings.RealVectorEncoding;
32using HeuristicLab.Optimization;
33using HeuristicLab.Parameters;
34using HeuristicLab.Problems.Instances;
35
36namespace HeuristicLab.Problems.TestFunctions {
37  [Item("Test Function (single-objective)", "Test function with real valued inputs and a single objective.")]
38  [StorableType("F0AB7236-2C9B-49DC-9D4F-A3558FD9E992")]
39  [Creatable(CreatableAttribute.Categories.Problems, Priority = 90)]
40  public sealed class SingleObjectiveTestFunctionProblem : RealVectorProblem,
41    IProblemInstanceConsumer<SOTFData> {
42
43    #region Parameter Properties
44    private IFixedValueParameter<IntValue> ProblemSizeParameter {
45      get { return (IFixedValueParameter<IntValue>)Parameters["ProblemSize"]; }
46    }
47    private IValueParameter<DoubleMatrix> BoundsParameter {
48      get { return (IValueParameter<DoubleMatrix>)Parameters["Bounds"]; }
49    }
50    public OptionalValueParameter<RealVector> BestKnownSolutionParameter {
51      get { return (OptionalValueParameter<RealVector>)Parameters["BestKnownSolution"]; }
52    }
53    public IValueParameter<ISingleObjectiveTestFunction> TestFunctionParameter {
54      get { return (IValueParameter<ISingleObjectiveTestFunction>)Parameters["TestFunction"]; }
55    }
56    #endregion
57
58    #region Properties
59    public int ProblemSize {
60      get { return ProblemSizeParameter.Value.Value; }
61      set { ProblemSizeParameter.Value.Value = value; }
62    }
63    public DoubleMatrix Bounds {
64      get { return BoundsParameter.Value; }
65      set { BoundsParameter.Value = value; }
66    }
67    public ISingleObjectiveTestFunction TestFunction {
68      get { return TestFunctionParameter.Value; }
69      set { TestFunctionParameter.Value = value; }
70    }
71    #endregion
72
73    [StorableConstructor]
74    private SingleObjectiveTestFunctionProblem(StorableConstructorFlag _) : base(_) { }
75    private SingleObjectiveTestFunctionProblem(SingleObjectiveTestFunctionProblem original, Cloner cloner)
76      : base(original, cloner) {
77      RegisterEventHandlers();
78    }
79    public SingleObjectiveTestFunctionProblem()
80      : base(new RealVectorEncoding("Point")) {
81      Parameters.Add(new FixedValueParameter<IntValue>("ProblemSize", "The dimensionality of the problem instance (number of variables in the function).", new IntValue(2)));
82      Parameters.Add(new ValueParameter<DoubleMatrix>("Bounds", "The bounds of the solution given as either one line for all variables or a line for each variable. The first column specifies lower bound, the second upper bound.", new DoubleMatrix(new double[,] { { -100, 100 } })));
83      Parameters.Add(new OptionalValueParameter<RealVector>("BestKnownSolution", "The best known solution for this test function instance."));
84      Parameters.Add(new ValueParameter<ISingleObjectiveTestFunction>("TestFunction", "The function that is to be optimized.", new Ackley()));
85      Maximization = TestFunction.Maximization;
86
87      Encoding.LengthParameter = ProblemSizeParameter;
88      Encoding.BoundsParameter = BoundsParameter;
89      BestKnownQuality = TestFunction.BestKnownQuality;
90
91      InitializeOperators();
92      RegisterEventHandlers();
93    }
94
95    public override IDeepCloneable Clone(Cloner cloner) {
96      return new SingleObjectiveTestFunctionProblem(this, cloner);
97    }
98
99    [StorableHook(HookType.AfterDeserialization)]
100    private void AfterDeserialization() {
101      RegisterEventHandlers();
102    }
103
104    private void RegisterEventHandlers() {
105      Evaluator.QualityParameter.ActualNameChanged += Evaluator_QualityParameter_ActualNameChanged;
106      TestFunctionParameter.ValueChanged += TestFunctionParameterOnValueChanged;
107      ProblemSizeParameter.Value.ValueChanged += ProblemSizeOnValueChanged;
108      BoundsParameter.ValueChanged += BoundsParameterOnValueChanged;
109    }
110
111    public override ISingleObjectiveEvaluationResult Evaluate(RealVector individual, IRandom random, CancellationToken cancellationToken) {
112      var quality = TestFunction.Evaluate(individual);
113      return new SingleObjectiveEvaluationResult(quality);
114    }
115
116    public override void Analyze(RealVector[] realVectors, double[] qualities, ResultCollection results, IRandom random) {
117      var best = GetBestSolution(realVectors, qualities);
118
119      DoubleValue bestKnownQuality = BestKnownQualityParameter.Value;
120      RealVector bestKnownSolution = null;
121      var bestKnownUpdate = bestKnownQuality == null || IsBetter(best.Item2, bestKnownQuality.Value);
122      if (bestKnownUpdate) {
123        if (bestKnownQuality != null) bestKnownQuality.Value = best.Item2;
124        else BestKnownQualityParameter.Value = bestKnownQuality = new DoubleValue(best.Item2);
125        BestKnownSolutionParameter.Value = bestKnownSolution = (RealVector)best.Item1.Clone();
126      }
127
128      SingleObjectiveTestFunctionSolution solution = null;
129      if (results.TryGetValue("Best Solution", out var res)) {
130        solution = (SingleObjectiveTestFunctionSolution)res.Value;
131        if (IsBetter(best.Item2, solution.BestQuality.Value)) {
132          solution.BestRealVector = (RealVector)best.Item1.Clone();
133          solution.BestQuality = new DoubleValue(best.Item2);
134        }
135      } else {
136        solution = new SingleObjectiveTestFunctionSolution((RealVector)best.Item1.Clone(),
137                                                           new DoubleValue(best.Item2),
138                                                           TestFunctionParameter.Value) {
139          BestKnownRealVector = bestKnownSolution,
140          Bounds = BoundsParameter.Value
141        };
142        results.Add(new Result("Best Solution", solution));
143      }
144      if (best.Item1.Length == 2) solution.Population = new ItemArray<RealVector>(realVectors.Select(x => (RealVector)x.Clone()));
145      if (bestKnownUpdate) solution.BestKnownRealVector = bestKnownSolution;
146    }
147
148    #region Events
149    protected override void OnEncodingChanged() {
150      base.OnEncodingChanged();
151      Parameterize();
152    }
153    protected override void OnEvaluatorChanged() {
154      base.OnEvaluatorChanged();
155      Evaluator.QualityParameter.ActualNameChanged += Evaluator_QualityParameter_ActualNameChanged;
156      Parameterize();
157    }
158    private void Evaluator_QualityParameter_ActualNameChanged(object sender, EventArgs e) {
159      Parameterize();
160    }
161    private void TestFunctionParameterOnValueChanged(object sender, EventArgs eventArgs) {
162      var problemSizeChange = ProblemSize < TestFunction.MinimumProblemSize
163                              || ProblemSize > TestFunction.MaximumProblemSize;
164      if (problemSizeChange) {
165        ProblemSize = Math.Max(TestFunction.MinimumProblemSize, Math.Min(ProblemSize, TestFunction.MaximumProblemSize));
166      }
167      BestKnownQuality = TestFunction.BestKnownQuality;
168      Bounds = (DoubleMatrix)TestFunction.Bounds.Clone();
169      var bestSolution = TestFunction.GetBestKnownSolution(ProblemSize);
170      BestKnownSolutionParameter.Value = bestSolution;
171      Maximization = TestFunction.Maximization;
172
173      OnReset();
174    }
175    private void ProblemSizeOnValueChanged(object sender, EventArgs eventArgs) {
176      if (ProblemSize < TestFunction.MinimumProblemSize
177        || ProblemSize > TestFunction.MaximumProblemSize)
178        ProblemSize = Math.Min(TestFunction.MaximumProblemSize, Math.Max(TestFunction.MinimumProblemSize, ProblemSize));
179    }
180    private void BoundsParameterOnValueChanged(object sender, EventArgs eventArgs) {
181      Parameterize();
182    }
183    #endregion
184
185    #region Helpers
186    private void InitializeOperators() {
187      Operators.Add(new SingleObjectiveTestFunctionImprovementOperator());
188      Operators.Add(new SingleObjectiveTestFunctionPathRelinker());
189      Operators.Add(new SingleObjectiveTestFunctionSimilarityCalculator());
190      Operators.Add(new EuclideanSimilarityCalculator());
191      Operators.Add(new AdditiveMoveEvaluator());
192
193      Parameterize();
194    }
195
196    private void Parameterize() {
197      var operators = new List<IItem>();
198      foreach (var op in Operators.OfType<PopulationSimilarityAnalyzer>()) {
199        var calcs = Operators.OfType<ISolutionSimilarityCalculator>().ToArray();
200        op.SimilarityCalculatorParameter.ValidValues.Clear();
201        foreach (var c in calcs) {
202          // TODO: unified encoding parameters
203          c.SolutionVariableName = ((IRealVectorSolutionOperator)Encoding.SolutionCreator).RealVectorParameter.ActualName;
204          c.QualityVariableName = Evaluator.QualityParameter.ActualName;
205          op.SimilarityCalculatorParameter.ValidValues.Add(c);
206        }
207      }
208      foreach (var op in Operators.OfType<ISingleObjectiveTestFunctionAdditiveMoveEvaluator>()) {
209        operators.Add(op);
210        op.QualityParameter.ActualName = Evaluator.QualityParameter.ActualName;
211        op.QualityParameter.Hidden = true;
212        foreach (var movOp in Encoding.Operators.OfType<IRealVectorAdditiveMoveQualityOperator>())
213          movOp.MoveQualityParameter.ActualName = op.MoveQualityParameter.ActualName;
214      }
215      foreach (var op in Operators.OfType<IRealVectorParticleCreator>()) {
216        // TODO: unified encoding parameters
217        op.RealVectorParameter.ActualName = ((IRealVectorSolutionOperator)Encoding.SolutionCreator).RealVectorParameter.ActualName;
218        op.RealVectorParameter.Hidden = true;
219        op.BoundsParameter.ActualName = BoundsParameter.Name;
220        op.BoundsParameter.Hidden = true;
221      }
222      foreach (var op in Operators.OfType<IRealVectorParticleUpdater>()) {
223        // TODO: unified encoding parameters
224        op.RealVectorParameter.ActualName = ((IRealVectorSolutionOperator)Encoding.SolutionCreator).RealVectorParameter.ActualName;
225        op.RealVectorParameter.Hidden = true;
226        op.BoundsParameter.ActualName = BoundsParameter.Name;
227        op.BoundsParameter.Hidden = true;
228      }
229      foreach (var op in Operators.OfType<IRealVectorSwarmUpdater>()) {
230        op.MaximizationParameter.ActualName = MaximizationParameter.Name;
231        op.MaximizationParameter.Hidden = true;
232      }
233      foreach (var op in Operators.OfType<ISingleObjectiveImprovementOperator>()) {
234        operators.Add(op);
235        op.SolutionParameter.ActualName = Encoding.Name;
236        op.SolutionParameter.Hidden = true;
237      }
238      foreach (var op in Operators.OfType<ITestFunctionSolutionSimilarityCalculator>()) {
239        operators.Add(op);
240        op.SolutionVariableName = Encoding.Name;
241        op.QualityVariableName = Evaluator.QualityParameter.ActualName;
242        op.Bounds = Bounds;
243      }
244
245      if (operators.Count > 0) Encoding.ConfigureOperators(operators);
246    }
247    #endregion
248
249    public void Load(SOTFData data) {
250      Name = data.Name;
251      Description = data.Description;
252      TestFunction = data.TestFunction;
253    }
254  }
255}
Note: See TracBrowser for help on using the repository browser.