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

Last change on this file since 17226 was 17226, checked in by mkommend, 3 years ago

#2521: Merged trunk changes into problem refactoring branch.

File size: 11.6 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 HEAL.Attic;
26using HeuristicLab.Analysis;
27using HeuristicLab.Common;
28using HeuristicLab.Core;
29using HeuristicLab.Data;
30using HeuristicLab.Encodings.RealVectorEncoding;
31using HeuristicLab.Optimization;
32using HeuristicLab.Parameters;
33using HeuristicLab.Problems.Instances;
34
35namespace HeuristicLab.Problems.TestFunctions {
36  [Item("Test Function (single-objective)", "Test function with real valued inputs and a single objective.")]
37  [StorableType("F0AB7236-2C9B-49DC-9D4F-A3558FD9E992")]
38  [Creatable(CreatableAttribute.Categories.Problems, Priority = 90)]
39  public sealed class SingleObjectiveTestFunctionProblem : RealVectorProblem,
40    IProblemInstanceConsumer<SOTFData> {
41
42    public override bool Maximization {
43      get { return Parameters.ContainsKey("TestFunction") && TestFunction.Maximization; }
44    }
45
46    #region Parameter Properties
47    private IFixedValueParameter<IntValue> ProblemSizeParameter {
48      get { return (IFixedValueParameter<IntValue>)Parameters["ProblemSize"]; }
49    }
50    private IValueParameter<DoubleMatrix> BoundsParameter {
51      get { return (IValueParameter<DoubleMatrix>)Parameters["Bounds"]; }
52    }
53    public OptionalValueParameter<RealVector> BestKnownSolutionParameter {
54      get { return (OptionalValueParameter<RealVector>)Parameters["BestKnownSolution"]; }
55    }
56    public IValueParameter<ISingleObjectiveTestFunction> TestFunctionParameter {
57      get { return (IValueParameter<ISingleObjectiveTestFunction>)Parameters["TestFunction"]; }
58    }
59    #endregion
60
61    #region Properties
62    public int ProblemSize {
63      get { return ProblemSizeParameter.Value.Value; }
64      set { ProblemSizeParameter.Value.Value = value; }
65    }
66    public DoubleMatrix Bounds {
67      get { return BoundsParameter.Value; }
68      set { BoundsParameter.Value = value; }
69    }
70    public ISingleObjectiveTestFunction TestFunction {
71      get { return TestFunctionParameter.Value; }
72      set { TestFunctionParameter.Value = value; }
73    }
74    #endregion
75
76    [StorableConstructor]
77    private SingleObjectiveTestFunctionProblem(StorableConstructorFlag _) : base(_) { }
78    private SingleObjectiveTestFunctionProblem(SingleObjectiveTestFunctionProblem original, Cloner cloner)
79      : base(original, cloner) {
80      RegisterEventHandlers();
81    }
82    public SingleObjectiveTestFunctionProblem()
83      : base(new RealVectorEncoding("Point")) {
84      Parameters.Add(new FixedValueParameter<IntValue>("ProblemSize", "The dimensionality of the problem instance (number of variables in the function).", new IntValue(2)));
85      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 } })));
86      Parameters.Add(new OptionalValueParameter<RealVector>("BestKnownSolution", "The best known solution for this test function instance."));
87      Parameters.Add(new ValueParameter<ISingleObjectiveTestFunction>("TestFunction", "The function that is to be optimized.", new Ackley()));
88
89      Encoding.LengthParameter = ProblemSizeParameter;
90      Encoding.BoundsParameter = BoundsParameter;
91      BestKnownQuality = TestFunction.BestKnownQuality;
92
93      InitializeOperators();
94      RegisterEventHandlers();
95    }
96
97    public override IDeepCloneable Clone(Cloner cloner) {
98      return new SingleObjectiveTestFunctionProblem(this, cloner);
99    }
100
101    [StorableHook(HookType.AfterDeserialization)]
102    private void AfterDeserialization() {
103      RegisterEventHandlers();
104    }
105
106    private void RegisterEventHandlers() {
107      Evaluator.QualityParameter.ActualNameChanged += Evaluator_QualityParameter_ActualNameChanged;
108      TestFunctionParameter.ValueChanged += TestFunctionParameterOnValueChanged;
109      ProblemSizeParameter.Value.ValueChanged += ProblemSizeOnValueChanged;
110      BoundsParameter.ValueChanged += BoundsParameterOnValueChanged;
111    }
112
113    public override double Evaluate(RealVector individual, IRandom random) {
114      return TestFunction.Evaluate(individual);
115    }
116
117    public override void Analyze(RealVector[] realVectors, double[] qualities, ResultCollection results, IRandom random) {
118      var best = GetBestSolution(realVectors, qualities);
119
120      DoubleValue bestKnownQuality = BestKnownQualityParameter.Value;
121      RealVector bestKnownSolution = null;
122      var bestKnownUpdate = bestKnownQuality == null || IsBetter(best.Item2, bestKnownQuality.Value);
123      if (bestKnownUpdate) {
124        if (bestKnownQuality != null) bestKnownQuality.Value = best.Item2;
125        else BestKnownQualityParameter.Value = bestKnownQuality = new DoubleValue(best.Item2);
126        BestKnownSolutionParameter.Value = bestKnownSolution = (RealVector)best.Item1.Clone();
127      }
128
129      SingleObjectiveTestFunctionSolution solution = null;
130      if (results.TryGetValue("Best Solution", out var res)) {
131        solution = (SingleObjectiveTestFunctionSolution)res.Value;
132        if (IsBetter(best.Item2, solution.BestQuality.Value)) {
133          solution.BestRealVector = (RealVector)best.Item1.Clone();
134          solution.BestQuality = new DoubleValue(best.Item2);
135        }
136      } else {
137        solution = new SingleObjectiveTestFunctionSolution((RealVector)best.Item1.Clone(),
138                                                           new DoubleValue(best.Item2),
139                                                           TestFunctionParameter.Value) {
140          BestKnownRealVector = bestKnownSolution,
141          Bounds = BoundsParameter.Value
142        };
143        results.Add(new Result("Best Solution", solution));
144      }
145      if (best.Item1.Length == 2) solution.Population = new ItemArray<RealVector>(realVectors.Select(x => (RealVector)x.Clone()));
146      if (bestKnownUpdate) solution.BestKnownRealVector = bestKnownSolution;
147    }
148
149    #region Events
150    protected override void OnEncodingChanged() {
151      base.OnEncodingChanged();
152      Parameterize();
153    }
154    protected override void OnEvaluatorChanged() {
155      base.OnEvaluatorChanged();
156      Evaluator.QualityParameter.ActualNameChanged += Evaluator_QualityParameter_ActualNameChanged;
157      Parameterize();
158    }
159    private void Evaluator_QualityParameter_ActualNameChanged(object sender, EventArgs e) {
160      Parameterize();
161    }
162    private void TestFunctionParameterOnValueChanged(object sender, EventArgs eventArgs) {
163      var problemSizeChange = ProblemSize < TestFunction.MinimumProblemSize
164                              || ProblemSize > TestFunction.MaximumProblemSize;
165      if (problemSizeChange) {
166        ProblemSize = Math.Max(TestFunction.MinimumProblemSize, Math.Min(ProblemSize, TestFunction.MaximumProblemSize));
167      }
168      BestKnownQuality = TestFunction.BestKnownQuality;
169      Bounds = (DoubleMatrix)TestFunction.Bounds.Clone();
170      var bestSolution = TestFunction.GetBestKnownSolution(ProblemSize);
171      BestKnownSolutionParameter.Value = bestSolution;
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.