source: stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Selectors/DiversitySelector.cs @ 17140

Last change on this file since 17140 was 17140, checked in by abeham, 2 months ago

#2991: merged to stable

  • fixed merge conflict (order of items added to csproj, first DiversitySelector.cs, then SymbolicDataAnalysisExpressionTreeAverageSimilarityCalculator.cs
File size: 8.4 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2019 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 HEAL.Attic;
25using HeuristicLab.Common;
26using HeuristicLab.Core;
27using HeuristicLab.Data;
28using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
29using HeuristicLab.Optimization;
30using HeuristicLab.Parameters;
31using HeuristicLab.Selection;
32
33namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
34  [StorableType("3E8EA052-3B86-4609-BD38-E3FE78DAD2FF")]
35  [Item("DiversitySelector", "A selection operator that applies a diversity penalty to the objective function before applying an inner selector.")]
36  public sealed class DiversitySelector : StochasticSingleObjectiveSelector, ISingleObjectiveSelector {
37    private const string StrictSimilarityParameterName = "StrictSimilarity";
38    private const string SimilarityWeightParameterName = "SimilarityWeight";
39    private const string SymbolicExpressionTreeParameterName = "SymbolicExpressionTree";
40    private const string SelectorParameterName = "Selector";
41    private const string DiversityParameterName = "Diversity";
42
43    public IValueParameter<ISingleObjectiveSelector> SelectorParameter {
44      get { return (IValueParameter<ISingleObjectiveSelector>)Parameters[SelectorParameterName]; }
45    }
46
47    public ISingleObjectiveSelector Selector {
48      get { return SelectorParameter.Value; }
49      set { SelectorParameter.Value = value; }
50    }
51
52    public IScopeTreeLookupParameter<ISymbolicExpressionTree> SymbolicExpressionTreeParameter {
53      get { return (IScopeTreeLookupParameter<ISymbolicExpressionTree>)Parameters[SymbolicExpressionTreeParameterName]; }
54    }
55
56    public IScopeTreeLookupParameter<DoubleValue> DiversityParameter {
57      get { return (IScopeTreeLookupParameter<DoubleValue>)Parameters[DiversityParameterName]; }
58    }
59
60    public IFixedValueParameter<BoolValue> StrictSimilarityParameter {
61      get { return (IFixedValueParameter<BoolValue>)Parameters[StrictSimilarityParameterName]; }
62    }
63
64    public IFixedValueParameter<DoubleValue> SimilarityWeightParameter {
65      get { return (IFixedValueParameter<DoubleValue>)Parameters[SimilarityWeightParameterName]; }
66    }
67
68    public bool StrictSimilarity { get { return StrictSimilarityParameter.Value.Value; } }
69
70    public double SimilarityWeight { get { return SimilarityWeightParameter.Value.Value; } }
71
72    public DiversitySelector() : base() {
73      Parameters.Add(new FixedValueParameter<BoolValue>(StrictSimilarityParameterName, "Calculate strict similarity.", new BoolValue(true)));
74      Parameters.Add(new FixedValueParameter<DoubleValue>(SimilarityWeightParameterName, "Weight of the diversity term.", new DoubleValue(1)));
75      Parameters.Add(new ScopeTreeLookupParameter<ISymbolicExpressionTree>(SymbolicExpressionTreeParameterName, "The symbolic expression trees that should be analyzed."));
76      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>(DiversityParameterName));
77      Parameters.Add(new ValueParameter<ISingleObjectiveSelector>(SelectorParameterName, "The inner selection operator to select the parents.", new TournamentSelector()));
78
79      RegisterParameterEventHandlers();
80    }
81
82    [StorableConstructor]
83    private DiversitySelector(StorableConstructorFlag deserializing) : base(deserializing) { }
84
85    private DiversitySelector(DiversitySelector original, Cloner cloner) : base(original, cloner) { }
86
87    public override IDeepCloneable Clone(Cloner cloner) {
88      return new DiversitySelector(this, cloner);
89    }
90
91    [StorableHook(HookType.AfterDeserialization)]
92    private void AfterDeserialization() {
93      RegisterParameterEventHandlers();
94
95      if (!Parameters.ContainsKey(DiversityParameterName)) {
96        Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>(DiversityParameterName));
97      }
98    }
99
100    #region Events
101    private void RegisterParameterEventHandlers() {
102      SelectorParameter.ValueChanged += SelectorParameter_ValueChanged;
103      CopySelectedParameter.ValueChanged += CopySelectedParameter_ValueChanged;
104      CopySelected.ValueChanged += CopySelected_ValueChanged;
105    }
106
107    private void CopySelectedParameter_ValueChanged(object sender, EventArgs e) {
108      if (CopySelected.Value != true) {
109        CopySelected.Value = true;
110      }
111      CopySelected.ValueChanged += CopySelected_ValueChanged;
112    }
113
114    private void SelectorParameter_ValueChanged(object sender, EventArgs e) {
115      ParameterizeSelector(Selector);
116    }
117
118    private void CopySelected_ValueChanged(object sender, EventArgs e) {
119      if (CopySelected.Value != true) {
120        CopySelected.Value = true;
121      }
122    }
123    #endregion
124
125    protected override IScope[] Select(List<IScope> scopes) {
126      var w = SimilarityWeight;
127      if (w.IsAlmost(0)) {
128        ApplyInnerSelector();
129        return CurrentScope.SubScopes[1].SubScopes.ToArray();
130      }
131
132      var trees = SymbolicExpressionTreeParameter.ActualValue;
133      var qualities = QualityParameter.ActualValue;
134
135      // calculate average similarity for each tree
136      var similarityMatrix = SymbolicExpressionTreeHash.ComputeSimilarityMatrix(trees, simplify: false, strict: StrictSimilarity);
137      var similarities = new double[trees.Length];
138      for (int i = 0; i < trees.Length; ++i) {
139        for (int j = 0; j < trees.Length; ++j) {
140          if (i != j) {
141            similarities[i] += similarityMatrix[i, j];
142          }
143        }
144        similarities[i] /= (trees.Length - 1);
145      }
146
147      var v = 1 - w;
148
149      var maximization = MaximizationParameter.ActualValue.Value;
150      var diversities = new ItemArray<DoubleValue>(trees.Length);
151      for (int i = 0; i < trees.Length; ++i) {
152        var q = qualities[i].Value;
153        var d = 1 - similarities[i]; // average distance
154
155        // assuming both q and d are in the interval [0, 1]
156        var value = maximization
157            ? (v * q) + (w * d)
158            : (v * q) - (w * d);
159
160        diversities[i] = new DoubleValue(value);
161      }
162
163      Selector.QualityParameter.ActualName = "Diversity";
164      DiversityParameter.ActualValue = diversities;
165      ApplyInnerSelector(); // apply inner selector
166
167      return CurrentScope.SubScopes[1].SubScopes.ToArray();
168    }
169
170    private void ParameterizeSelector(ISingleObjectiveSelector selector) {
171      selector.CopySelected = new BoolValue(true); // must always be true
172      selector.MaximizationParameter.ActualName = MaximizationParameter.Name;
173      selector.QualityParameter.ActualName = QualityParameter.Name;
174
175      IStochasticOperator stoOp = (selector as IStochasticOperator);
176      if (stoOp != null) stoOp.RandomParameter.ActualName = RandomParameter.Name;
177    }
178
179    private void ApplyInnerSelector() {
180      // necessary for inner GenderSpecificSelector to execute all operations in OperationCollection
181      Stack<IOperation> executionStack = new Stack<IOperation>();
182      executionStack.Push(ExecutionContext.CreateChildOperation(Selector));
183      while (executionStack.Count > 0) {
184        CancellationToken.ThrowIfCancellationRequested();
185        IOperation next = executionStack.Pop();
186        if (next is OperationCollection) {
187          OperationCollection coll = (OperationCollection)next;
188          for (int i = coll.Count - 1; i >= 0; i--)
189            if (coll[i] != null) executionStack.Push(coll[i]);
190        } else if (next is IAtomicOperation) {
191          IAtomicOperation operation = (IAtomicOperation)next;
192          next = operation.Operator.Execute((IExecutionContext)operation, CancellationToken);
193          if (next != null) executionStack.Push(next);
194        }
195      }
196    }
197  }
198}
Note: See TracBrowser for help on using the repository browser.