source: branches/2974_Constants_Optimization/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/MultiSymbolicDataAnalysisExpressionCrossover.cs @ 17193

Last change on this file since 17193 was 17193, checked in by mkommend, 6 weeks ago

#2974: Merged trunk changes into branch.

File size: 11.3 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.Linq;
24using HeuristicLab.Collections;
25using HeuristicLab.Common;
26using HeuristicLab.Core;
27using HeuristicLab.Data;
28using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
29using HeuristicLab.Operators;
30using HeuristicLab.Optimization;
31using HeuristicLab.Parameters;
32using HEAL.Attic;
33using HeuristicLab.PluginInfrastructure;
34
35namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
36  [Item("MultiSymbolicDataAnalysisExpressionCrossover", "Randomly selects and applies one of its crossovers every time it is called.")]
37  [StorableType("AD80D64F-64E6-42F7-B1D3-AFDE6AF96EC4")]
38  public class MultiSymbolicDataAnalysisExpressionCrossover<T> : StochasticMultiBranch<ISymbolicExpressionTreeCrossover>,
39    ISymbolicDataAnalysisExpressionCrossover<T> where T : class, IDataAnalysisProblemData {
40    private const string ParentsParameterName = "Parents";
41    private const string SymbolicExpressionTreeParameterName = "SymbolicExpressionTree";
42    private const string MaximumSymbolicExpressionTreeLengthParameterName = "MaximumSymbolicExpressionTreeLength";
43    private const string MaximumSymbolicExpressionTreeDepthParameterName = "MaximumSymbolicExpressionTreeDepth";
44    private const string SymbolicDataAnalysisTreeInterpreterParameterName = "SymbolicExpressionTreeInterpreter";
45    private const string EvaluatorParameterName = "Evaluator";
46    private const string SymbolicDataAnalysisEvaluationPartitionParameterName = "EvaluationPartition";
47    private const string RelativeNumberOfEvaluatedSamplesParameterName = "RelativeNumberOfEvaluatedSamples";
48    private const string ProblemDataParameterName = "ProblemData";
49
50    protected override bool CreateChildOperation {
51      get { return true; }
52    }
53
54    public override bool CanChangeName {
55      get { return false; }
56    }
57
58    #region parameter properties
59    public ILookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter> SymbolicDataAnalysisTreeInterpreterParameter {
60      get { return (ILookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter>)Parameters[SymbolicDataAnalysisTreeInterpreterParameterName]; }
61    }
62    public ILookupParameter<ItemArray<ISymbolicExpressionTree>> ParentsParameter {
63      get { return (ScopeTreeLookupParameter<ISymbolicExpressionTree>)Parameters[ParentsParameterName]; }
64    }
65    public ILookupParameter<ISymbolicExpressionTree> SymbolicExpressionTreeParameter {
66      get { return (ILookupParameter<ISymbolicExpressionTree>)Parameters[SymbolicExpressionTreeParameterName]; }
67    }
68    public IValueLookupParameter<IntValue> MaximumSymbolicExpressionTreeLengthParameter {
69      get { return (IValueLookupParameter<IntValue>)Parameters[MaximumSymbolicExpressionTreeLengthParameterName]; }
70    }
71    public IValueLookupParameter<IntValue> MaximumSymbolicExpressionTreeDepthParameter {
72      get { return (IValueLookupParameter<IntValue>)Parameters[MaximumSymbolicExpressionTreeDepthParameterName]; }
73    }
74    public ILookupParameter<ISymbolicDataAnalysisSingleObjectiveEvaluator<T>> EvaluatorParameter {
75      get { return (ILookupParameter<ISymbolicDataAnalysisSingleObjectiveEvaluator<T>>)Parameters[EvaluatorParameterName]; }
76    }
77    public IValueLookupParameter<IntRange> EvaluationPartitionParameter {
78      get { return (IValueLookupParameter<IntRange>)Parameters[SymbolicDataAnalysisEvaluationPartitionParameterName]; }
79    }
80    public IValueLookupParameter<PercentValue> RelativeNumberOfEvaluatedSamplesParameter {
81      get { return (IValueLookupParameter<PercentValue>)Parameters[RelativeNumberOfEvaluatedSamplesParameterName]; }
82    }
83    public IValueLookupParameter<T> ProblemDataParameter {
84      get { return (IValueLookupParameter<T>)Parameters[ProblemDataParameterName]; }
85    }
86    #endregion
87
88    [StorableConstructor]
89    protected MultiSymbolicDataAnalysisExpressionCrossover(StorableConstructorFlag _) : base(_) { }
90    protected MultiSymbolicDataAnalysisExpressionCrossover(MultiSymbolicDataAnalysisExpressionCrossover<T> original, Cloner cloner) : base(original, cloner) { }
91    public override IDeepCloneable Clone(Cloner cloner) { return new MultiSymbolicDataAnalysisExpressionCrossover<T>(this, cloner); }
92    public MultiSymbolicDataAnalysisExpressionCrossover()
93      : base() {
94      Parameters.Add(new ValueLookupParameter<PercentValue>(RelativeNumberOfEvaluatedSamplesParameterName, "The relative number of samples of the dataset partition, which should be randomly chosen for evaluation between the start and end index."));
95      Parameters.Add(new ValueLookupParameter<T>(ProblemDataParameterName, "The problem data on which the symbolic data analysis solution should be evaluated."));
96      Parameters.Add(new LookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter>(SymbolicDataAnalysisTreeInterpreterParameterName, "The interpreter that should be used to calculate the output values of the symbolic data analysis tree."));
97      Parameters.Add(new ValueLookupParameter<IntValue>(MaximumSymbolicExpressionTreeLengthParameterName, "The maximal length (number of nodes) of the symbolic expression tree."));
98      Parameters.Add(new ValueLookupParameter<IntValue>(MaximumSymbolicExpressionTreeDepthParameterName, "The maximal depth of the symbolic expression tree (a tree with one node has depth = 0)."));
99      Parameters.Add(new LookupParameter<ISymbolicDataAnalysisSingleObjectiveEvaluator<T>>(EvaluatorParameterName, "The single objective solution evaluator"));
100      Parameters.Add(new ValueLookupParameter<IntRange>(SymbolicDataAnalysisEvaluationPartitionParameterName, "The start index of the dataset partition on which the symbolic data analysis solution should be evaluated."));
101      Parameters.Add(new ScopeTreeLookupParameter<ISymbolicExpressionTree>(ParentsParameterName, "The parent symbolic expression trees which should be crossed."));
102      Parameters.Add(new LookupParameter<ISymbolicExpressionTree>(SymbolicExpressionTreeParameterName, "The child symbolic expression tree resulting from the crossover."));
103
104      EvaluatorParameter.Hidden = true;
105      EvaluationPartitionParameter.Hidden = true;
106      SymbolicDataAnalysisTreeInterpreterParameter.Hidden = true;
107      ProblemDataParameter.Hidden = true;
108      RelativeNumberOfEvaluatedSamplesParameter.Hidden = true;
109
110      InitializeOperators();
111      name = "MultiSymbolicDataAnalysisExpressionCrossover";
112
113      SelectedOperatorParameter.ActualName = "SelectedCrossoverOperator";
114    }
115
116    [StorableHook(HookType.AfterDeserialization)]
117    private void AfterDeserialization() {
118      // BackwardsCompatibility3.3
119      #region Backwards compatible code, remove with 3.4
120      if (!Parameters.ContainsKey(SymbolicExpressionTreeParameterName))
121        Parameters.Add(new LookupParameter<ISymbolicExpressionTree>(SymbolicExpressionTreeParameterName, "The symbolic expression tree on which the operator should be applied."));
122      #endregion
123    }
124
125    private void InitializeOperators() {
126      var list = ApplicationManager.Manager.GetInstances<ISymbolicExpressionTreeCrossover>().ToList();
127      var dataAnalysisCrossovers = from type in ApplicationManager.Manager.GetTypes(typeof(ISymbolicDataAnalysisExpressionCrossover<T>))
128                                   where this.GetType().Assembly == type.Assembly
129                                   where !typeof(IMultiOperator<ISymbolicExpressionTreeCrossover>).IsAssignableFrom(type)
130                                   select (ISymbolicDataAnalysisExpressionCrossover<T>)Activator.CreateInstance(type);
131      list.AddRange(dataAnalysisCrossovers);
132
133      var checkedItemList = new CheckedItemList<ISymbolicExpressionTreeCrossover>();
134      checkedItemList.AddRange(list.OrderBy(op => op.Name));
135      Operators = checkedItemList;
136      Operators_ItemsAdded(this, new CollectionItemsChangedEventArgs<IndexedItem<ISymbolicExpressionTreeCrossover>>(Operators.CheckedItems));
137    }
138
139    public ISymbolicExpressionTree Crossover(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1) {
140      double sum = Operators.CheckedItems.Sum(o => Probabilities[o.Index]);
141      if (sum.IsAlmost(0)) throw new InvalidOperationException(Name + ": All selected operators have zero probability.");
142      double r = random.NextDouble() * sum;
143      sum = 0;
144      int index = -1;
145      foreach (var indexedItem in Operators.CheckedItems) {
146        sum += Probabilities[indexedItem.Index];
147        if (sum > r) {
148          index = indexedItem.Index;
149          break;
150        }
151      }
152      return Operators[index].Crossover(random, parent0, parent1);
153    }
154
155    protected override void Operators_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<ISymbolicExpressionTreeCrossover>> e) {
156      base.Operators_ItemsReplaced(sender, e);
157      ParameterizeCrossovers();
158    }
159
160    protected override void Operators_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<ISymbolicExpressionTreeCrossover>> e) {
161      base.Operators_ItemsAdded(sender, e);
162      ParameterizeCrossovers();
163    }
164
165    private void ParameterizeCrossovers() {
166      foreach (ISymbolicExpressionTreeCrossover op in Operators) {
167        op.SymbolicExpressionTreeParameter.ActualName = SymbolicExpressionTreeParameter.Name;
168        op.ParentsParameter.ActualName = ParentsParameter.Name;
169      }
170      foreach (IStochasticOperator op in Operators.OfType<IStochasticOperator>()) {
171        op.RandomParameter.ActualName = RandomParameter.Name;
172      }
173      foreach (ISymbolicExpressionTreeSizeConstraintOperator op in Operators.OfType<ISymbolicExpressionTreeSizeConstraintOperator>()) {
174        op.MaximumSymbolicExpressionTreeDepthParameter.ActualName = MaximumSymbolicExpressionTreeDepthParameter.Name;
175        op.MaximumSymbolicExpressionTreeLengthParameter.ActualName = MaximumSymbolicExpressionTreeLengthParameter.Name;
176      }
177
178      foreach (ISymbolicDataAnalysisInterpreterOperator op in Operators.OfType<ISymbolicDataAnalysisInterpreterOperator>()) {
179        op.SymbolicDataAnalysisTreeInterpreterParameter.ActualName = SymbolicDataAnalysisTreeInterpreterParameter.Name;
180      }
181      foreach (var op in Operators.OfType<ISymbolicDataAnalysisExpressionCrossover<T>>()) {
182        op.ProblemDataParameter.ActualName = ProblemDataParameter.Name;
183        op.EvaluationPartitionParameter.ActualName = EvaluationPartitionParameter.Name;
184        op.RelativeNumberOfEvaluatedSamplesParameter.ActualName = RelativeNumberOfEvaluatedSamplesParameter.Name;
185        op.EvaluatorParameter.ActualName = EvaluatorParameter.Name;
186      }
187    }
188  }
189}
Note: See TracBrowser for help on using the repository browser.