source: branches/HeuristicLab.LinqExpressionTreeInterpreter/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisMultiObjectiveTrainingBestSolutionAnalyzer.cs @ 13247

Last change on this file since 13247 was 13247, checked in by mkommend, 6 years ago

#2442: Merged trunk changes into branch for compiled interpreter.

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