1  #region License Information


2  /* HeuristicLab


3  * Copyright (C) 20022019 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 


22  using System;


23  using System.Linq;


24  using HeuristicLab.Analysis;


25  using HeuristicLab.Common;


26  using HeuristicLab.Core;


27  using HeuristicLab.Data;


28  using HeuristicLab.Optimization;


29  using HeuristicLab.Parameters;


30  using HEAL.Fossil;


31 


32  namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Regression {


33  /// <summary>


34  /// An operator that optimizes the constants for the best symbolic expression tress in the current generation.


35  /// </summary>


36  [Item("ConstantOptimizationAnalyzer", "An operator that performs a constant optimization on the best symbolic expression trees.")]


37  [StorableType("9FB87E7BA9E249DDA92A78BD9FC17916")]


38  public sealed class ConstantOptimizationAnalyzer : SymbolicDataAnalysisSingleObjectiveAnalyzer, IStatefulItem {


39  private const string PercentageOfBestSolutionsParameterName = "PercentageOfBestSolutions";


40  private const string ConstantOptimizationEvaluatorParameterName = "ConstantOptimizationOperator";


41 


42  private const string DataTableNameConstantOptimizationImprovement = "Constant Optimization Improvement";


43  private const string DataRowNameMinimumImprovement = "Minimum improvement";


44  private const string DataRowNameMedianImprovement = "Median improvement";


45  private const string DataRowNameAverageImprovement = "Average improvement";


46  private const string DataRowNameMaximumImprovement = "Maximum improvement";


47 


48  #region parameter properties


49  public IFixedValueParameter<PercentValue> PercentageOfBestSolutionsParameter {


50  get { return (IFixedValueParameter<PercentValue>)Parameters[PercentageOfBestSolutionsParameterName]; }


51  }


52 


53  public IFixedValueParameter<SymbolicRegressionConstantOptimizationEvaluator> ConstantOptimizationEvaluatorParameter {


54  get { return (IFixedValueParameter<SymbolicRegressionConstantOptimizationEvaluator>)Parameters[ConstantOptimizationEvaluatorParameterName]; }


55  }


56  #endregion


57 


58  #region properties


59  public SymbolicRegressionConstantOptimizationEvaluator ConstantOptimizationEvaluator {


60  get { return ConstantOptimizationEvaluatorParameter.Value; }


61  }


62  public double PercentageOfBestSolutions {


63  get { return PercentageOfBestSolutionsParameter.Value.Value; }


64  }


65 


66  private DataTable ConstantOptimizationImprovementDataTable {


67  get {


68  IResult result;


69  ResultCollection.TryGetValue(DataTableNameConstantOptimizationImprovement, out result);


70  if (result == null) return null;


71  return (DataTable)result.Value;


72  }


73  }


74  private DataRow MinimumImprovement {


75  get { return ConstantOptimizationImprovementDataTable.Rows[DataRowNameMinimumImprovement]; }


76  }


77  private DataRow MedianImprovement {


78  get { return ConstantOptimizationImprovementDataTable.Rows[DataRowNameMedianImprovement]; }


79  }


80  private DataRow AverageImprovement {


81  get { return ConstantOptimizationImprovementDataTable.Rows[DataRowNameAverageImprovement]; }


82  }


83  private DataRow MaximumImprovement {


84  get { return ConstantOptimizationImprovementDataTable.Rows[DataRowNameMaximumImprovement]; }


85  }


86  #endregion


87 


88  [StorableConstructor]


89  private ConstantOptimizationAnalyzer(StorableConstructorFlag _) : base(_) { }


90  private ConstantOptimizationAnalyzer(ConstantOptimizationAnalyzer original, Cloner cloner) : base(original, cloner) { }


91  public override IDeepCloneable Clone(Cloner cloner) { return new ConstantOptimizationAnalyzer(this, cloner); }


92  public ConstantOptimizationAnalyzer()


93  : base() {


94  Parameters.Add(new FixedValueParameter<PercentValue>(PercentageOfBestSolutionsParameterName, "The percentage of the top solutions which should be analyzed.", new PercentValue(0.1)));


95  Parameters.Add(new FixedValueParameter<SymbolicRegressionConstantOptimizationEvaluator>(ConstantOptimizationEvaluatorParameterName, "The operator used to perform the constant optimization"));


96 


97  //Changed the ActualName of the EvaluationPartitionParameter so that it matches the parameter name of symbolic regression problems.


98  ConstantOptimizationEvaluator.EvaluationPartitionParameter.ActualName = "FitnessCalculationPartition";


99  }


100 


101 


102  private double[] qualitiesBeforeCoOp = null;


103  private int[] scopeIndexes = null;


104  void IStatefulItem.InitializeState() {


105  qualitiesBeforeCoOp = null;


106  scopeIndexes = null;


107  }


108  void IStatefulItem.ClearState() {


109  qualitiesBeforeCoOp = null;


110  scopeIndexes = null;


111  }


112 


113  public override IOperation Apply() {


114  //code executed in the first call of analyzer


115  if (qualitiesBeforeCoOp == null) {


116  double[] trainingQuality;


117  // sort is ascending and we take the first n% => order so that best solutions are smallest


118  // sort order is determined by maximization parameter


119  if (Maximization.Value) {


120  // largest values must be sorted first


121  trainingQuality = Quality.Select(x => x.Value).ToArray();


122  } else {


123  // smallest values must be sorted first


124  trainingQuality = Quality.Select(x => x.Value).ToArray();


125  }


126  // sort trees by training qualities


127  int topN = (int)Math.Max(trainingQuality.Length * PercentageOfBestSolutions, 1);


128  scopeIndexes = Enumerable.Range(0, trainingQuality.Length).ToArray();


129  Array.Sort(trainingQuality, scopeIndexes);


130  scopeIndexes = scopeIndexes.Take(topN).ToArray();


131  qualitiesBeforeCoOp = scopeIndexes.Select(x => Quality[x].Value).ToArray();


132 


133  OperationCollection operationCollection = new OperationCollection();


134  operationCollection.Parallel = true;


135  foreach (var scopeIndex in scopeIndexes) {


136  var childOperation = ExecutionContext.CreateChildOperation(ConstantOptimizationEvaluator, ExecutionContext.Scope.SubScopes[scopeIndex]);


137  operationCollection.Add(childOperation);


138  }


139 


140  return new OperationCollection { operationCollection, ExecutionContext.CreateOperation(this) };


141  }


142 


143  //code executed to analyze results of constant optimization


144  double[] qualitiesAfterCoOp = scopeIndexes.Select(x => Quality[x].Value).ToArray();


145  var qualityImprovement = qualitiesBeforeCoOp.Zip(qualitiesAfterCoOp, (b, a) => a  b).ToArray();


146 


147  if (!ResultCollection.ContainsKey(DataTableNameConstantOptimizationImprovement)) {


148  var dataTable = new DataTable(DataTableNameConstantOptimizationImprovement);


149  ResultCollection.Add(new Result(DataTableNameConstantOptimizationImprovement, dataTable));


150  dataTable.VisualProperties.YAxisTitle = "R²";


151 


152  dataTable.Rows.Add(new DataRow(DataRowNameMinimumImprovement));


153  MinimumImprovement.VisualProperties.StartIndexZero = true;


154 


155  dataTable.Rows.Add(new DataRow(DataRowNameMedianImprovement));


156  MedianImprovement.VisualProperties.StartIndexZero = true;


157 


158  dataTable.Rows.Add(new DataRow(DataRowNameAverageImprovement));


159  AverageImprovement.VisualProperties.StartIndexZero = true;


160 


161  dataTable.Rows.Add(new DataRow(DataRowNameMaximumImprovement));


162  MaximumImprovement.VisualProperties.StartIndexZero = true;


163  }


164 


165  MinimumImprovement.Values.Add(qualityImprovement.Min());


166  MedianImprovement.Values.Add(qualityImprovement.Median());


167  AverageImprovement.Values.Add(qualityImprovement.Average());


168  MaximumImprovement.Values.Add(qualityImprovement.Max());


169 


170  qualitiesBeforeCoOp = null;


171  scopeIndexes = null;


172  return base.Apply();


173  }


174  }


175  }

