source: trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisMultiObjectiveTrainingBestSolutionAnalyzer.cs @ 12012

Last change on this file since 12012 was 12012, checked in by ascheibe, 7 years ago

#2212 merged r12008, r12009, r12010 back into trunk

File size: 9.0 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.Collections.Generic;
24using System.Linq;
25using HeuristicLab.Common;
26using HeuristicLab.Core;
27using HeuristicLab.Data;
28using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
29using HeuristicLab.Optimization;
30using HeuristicLab.Parameters;
31using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
32
33namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
34  /// <summary>
35  /// An operator that analyzes the training best symbolic data analysis solution for multi objective symbolic data analysis problems.
36  /// </summary>
37  [Item("SymbolicDataAnalysisMultiObjectiveTrainingBestSolutionAnalyzer", "An operator that analyzes the training best symbolic data analysis solution for multi objective symbolic data analysis problems.")]
38  [StorableClass]
39  public abstract class SymbolicDataAnalysisMultiObjectiveTrainingBestSolutionAnalyzer<T> : SymbolicDataAnalysisMultiObjectiveAnalyzer
40    where T : class, ISymbolicDataAnalysisSolution {
41    private const string TrainingBestSolutionsParameterName = "Best training solutions";
42    private const string TrainingBestSolutionQualitiesParameterName = "Best training solution qualities";
43    private const string UpdateAlwaysParameterName = "Always update best solutions";
44
45    #region parameter properties
46    public ILookupParameter<ItemList<T>> TrainingBestSolutionsParameter {
47      get { return (ILookupParameter<ItemList<T>>)Parameters[TrainingBestSolutionsParameterName]; }
48    }
49    public ILookupParameter<ItemList<DoubleArray>> TrainingBestSolutionQualitiesParameter {
50      get { return (ILookupParameter<ItemList<DoubleArray>>)Parameters[TrainingBestSolutionQualitiesParameterName]; }
51    }
52    public IFixedValueParameter<BoolValue> UpdateAlwaysParameter {
53      get { return (IFixedValueParameter<BoolValue>)Parameters[UpdateAlwaysParameterName]; }
54    }
55    #endregion
56    #region properties
57    public ItemList<T> TrainingBestSolutions {
58      get { return TrainingBestSolutionsParameter.ActualValue; }
59      set { TrainingBestSolutionsParameter.ActualValue = value; }
60    }
61    public ItemList<DoubleArray> TrainingBestSolutionQualities {
62      get { return TrainingBestSolutionQualitiesParameter.ActualValue; }
63      set { TrainingBestSolutionQualitiesParameter.ActualValue = value; }
64    }
65    public BoolValue UpdateAlways {
66      get { return UpdateAlwaysParameter.Value; }
67    }
68    #endregion
69
70    [StorableConstructor]
71    protected SymbolicDataAnalysisMultiObjectiveTrainingBestSolutionAnalyzer(bool deserializing) : base(deserializing) { }
72    protected SymbolicDataAnalysisMultiObjectiveTrainingBestSolutionAnalyzer(SymbolicDataAnalysisMultiObjectiveTrainingBestSolutionAnalyzer<T> original, Cloner cloner) : base(original, cloner) { }
73    public SymbolicDataAnalysisMultiObjectiveTrainingBestSolutionAnalyzer()
74      : base() {
75      Parameters.Add(new LookupParameter<ItemList<T>>(TrainingBestSolutionsParameterName, "The training best (Pareto-optimal) symbolic data analysis solutions."));
76      Parameters.Add(new LookupParameter<ItemList<DoubleArray>>(TrainingBestSolutionQualitiesParameterName, "The qualities of the training best (Pareto-optimal) solutions."));
77      Parameters.Add(new FixedValueParameter<BoolValue>(UpdateAlwaysParameterName, "Determines if the best training solutions should always be updated regardless of its quality.", new BoolValue(false)));
78      UpdateAlwaysParameter.Hidden = true;
79    }
80
81    [StorableHook(HookType.AfterDeserialization)]
82    private void AfterDeserialization() {
83      if (!Parameters.ContainsKey(UpdateAlwaysParameterName)) {
84        Parameters.Add(new FixedValueParameter<BoolValue>(UpdateAlwaysParameterName, "Determines if the best training solutions should always be updated regardless of its quality.", new BoolValue(false)));
85        UpdateAlwaysParameter.Hidden = true;
86      }
87    }
88
89    public override IOperation Apply() {
90      var results = ResultCollection;
91      // create empty parameter and result values
92      if (TrainingBestSolutions == null) {
93        TrainingBestSolutions = new ItemList<T>();
94        TrainingBestSolutionQualities = new ItemList<DoubleArray>();
95        results.Add(new Result(TrainingBestSolutionQualitiesParameter.Name, TrainingBestSolutionQualitiesParameter.Description, TrainingBestSolutionQualities));
96        results.Add(new Result(TrainingBestSolutionsParameter.Name, TrainingBestSolutionsParameter.Description, TrainingBestSolutions));
97      }
98
99      //if the pareto front of best solutions shall be updated regardless of the quality, the list initialized empty to discard old solutions
100      IList<double[]> trainingBestQualities;
101      if (UpdateAlways.Value) {
102        trainingBestQualities = new List<double[]>();
103      } else {
104        trainingBestQualities = TrainingBestSolutionQualities.Select(x => x.ToArray()).ToList();
105      }
106
107      #region find best trees
108      IList<int> nonDominatedIndexes = new List<int>();
109      ISymbolicExpressionTree[] tree = SymbolicExpressionTree.ToArray();
110      List<double[]> qualities = Qualities.Select(x => x.ToArray()).ToList();
111      bool[] maximization = Maximization.ToArray();
112      List<double[]> newNonDominatedQualities = new List<double[]>();
113      for (int i = 0; i < tree.Length; i++) {
114        if (IsNonDominated(qualities[i], trainingBestQualities, maximization) &&
115          IsNonDominated(qualities[i], qualities, maximization)) {
116          if (!newNonDominatedQualities.Contains(qualities[i], new DoubleArrayComparer())) {
117            newNonDominatedQualities.Add(qualities[i]);
118            nonDominatedIndexes.Add(i);
119          }
120        }
121      }
122      #endregion
123      #region update Pareto-optimal solution archive
124      if (nonDominatedIndexes.Count > 0) {
125        ItemList<DoubleArray> nonDominatedQualities = new ItemList<DoubleArray>();
126        ItemList<T> nonDominatedSolutions = new ItemList<T>();
127        // add all new non-dominated solutions to the archive
128        foreach (var index in nonDominatedIndexes) {
129          T solution = CreateSolution(tree[index], qualities[index]);
130          nonDominatedSolutions.Add(solution);
131          nonDominatedQualities.Add(new DoubleArray(qualities[index]));
132        }
133        // add old non-dominated solutions only if they are not dominated by one of the new solutions
134        for (int i = 0; i < trainingBestQualities.Count; i++) {
135          if (IsNonDominated(trainingBestQualities[i], newNonDominatedQualities, maximization)) {
136            if (!newNonDominatedQualities.Contains(trainingBestQualities[i], new DoubleArrayComparer())) {
137              nonDominatedSolutions.Add(TrainingBestSolutions[i]);
138              nonDominatedQualities.Add(TrainingBestSolutionQualities[i]);
139            }
140          }
141        }
142
143        results[TrainingBestSolutionsParameter.Name].Value = nonDominatedSolutions;
144        results[TrainingBestSolutionQualitiesParameter.Name].Value = nonDominatedQualities;
145      }
146      #endregion
147      return base.Apply();
148    }
149
150    private class DoubleArrayComparer : IEqualityComparer<double[]> {
151      public bool Equals(double[] x, double[] y) {
152        if (y.Length != x.Length) throw new ArgumentException();
153        for (int i = 0; i < x.Length; i++) {
154          if (!x[i].IsAlmost(y[i])) return false;
155        }
156        return true;
157      }
158
159      public int GetHashCode(double[] obj) {
160        int c = obj.Length;
161        for (int i = 0; i < obj.Length; i++)
162          c ^= obj[i].GetHashCode();
163        return c;
164      }
165    }
166
167    protected abstract T CreateSolution(ISymbolicExpressionTree bestTree, double[] bestQuality);
168
169    private bool IsNonDominated(double[] point, IList<double[]> points, bool[] maximization) {
170      foreach (var refPoint in points) {
171        bool refPointDominatesPoint = true;
172        for (int i = 0; i < point.Length; i++) {
173          refPointDominatesPoint &= IsBetterOrEqual(refPoint[i], point[i], maximization[i]);
174        }
175        if (refPointDominatesPoint) return false;
176      }
177      return true;
178    }
179    private bool IsBetterOrEqual(double lhs, double rhs, bool maximization) {
180      if (maximization) return lhs > rhs;
181      else return lhs < rhs;
182    }
183  }
184}
Note: See TracBrowser for help on using the repository browser.