Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Selectors/DiversitySelector.cs @ 16623

Last change on this file since 16623 was 16623, checked in by bburlacu, 5 years ago

#2991: DiversitySelector initial implementation.

File size: 8.1 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 += new EventHandler(SelectorParameter_ValueChanged);
103      CopySelected.ValueChanged += new EventHandler(CopySelected_ValueChanged);
104    }
105
106    private void SelectorParameter_ValueChanged(object sender, EventArgs e) {
107      ParameterizeSelector(Selector);
108    }
109
110    private void CopySelected_ValueChanged(object sender, EventArgs e) {
111      if (CopySelected.Value != true) {
112        CopySelected.Value = true;
113      }
114    }
115    #endregion
116
117    protected override IScope[] Select(List<IScope> scopes) {
118      var w = SimilarityWeight;
119      if (w.IsAlmost(0)) {
120        ApplyInnerSelector();
121        return CurrentScope.SubScopes[1].SubScopes.ToArray();
122      }
123
124      var trees = SymbolicExpressionTreeParameter.ActualValue;
125      var qualities = QualityParameter.ActualValue;
126
127      // calculate average similarity for each tree
128      var similarityMatrix = SymbolicExpressionTreeHash.ComputeSimilarityMatrix(trees, simplify: false, strict: StrictSimilarity);
129      var similarities = new double[trees.Length];
130      for (int i = 0; i < trees.Length; ++i) {
131        for (int j = 0; j < trees.Length; ++j) {
132          if (i != j) {
133            similarities[i] += similarityMatrix[i, j];
134          }
135        }
136        similarities[i] /= (trees.Length - 1);
137      }
138
139      var v = 1 - w;
140
141      var maximization = MaximizationParameter.ActualValue.Value;
142      var diversities = new ItemArray<DoubleValue>(trees.Length);
143      for (int i = 0; i < trees.Length; ++i) {
144        var q = qualities[i].Value;
145        var d = 1 - similarities[i]; // average distance
146
147        // assuming both q and d are in the interval [0, 1]
148        var value = maximization
149            ? (v * q) + (w * d)
150            : (v * q) - (w * d);
151
152        diversities[i] = new DoubleValue(value);
153      }
154
155      Selector.QualityParameter.ActualName = "Diversity";
156      DiversityParameter.ActualValue = diversities;
157      ApplyInnerSelector(); // apply inner selector
158
159      return CurrentScope.SubScopes[1].SubScopes.ToArray();
160    }
161
162    private void ParameterizeSelector(ISingleObjectiveSelector selector) {
163      selector.CopySelected = new BoolValue(true); // must always be true
164      selector.MaximizationParameter.ActualName = MaximizationParameter.Name;
165      selector.QualityParameter.ActualName = QualityParameter.Name;
166
167      IStochasticOperator stoOp = (selector as IStochasticOperator);
168      if (stoOp != null) stoOp.RandomParameter.ActualName = RandomParameter.Name;
169    }
170
171    private void ApplyInnerSelector() {
172      // necessary for inner GenderSpecificSelector to execute all operations in OperationCollection
173      Stack<IOperation> executionStack = new Stack<IOperation>();
174      executionStack.Push(ExecutionContext.CreateChildOperation(Selector));
175      while (executionStack.Count > 0) {
176        CancellationToken.ThrowIfCancellationRequested();
177        IOperation next = executionStack.Pop();
178        if (next is OperationCollection) {
179          OperationCollection coll = (OperationCollection)next;
180          for (int i = coll.Count - 1; i >= 0; i--)
181            if (coll[i] != null) executionStack.Push(coll[i]);
182        } else if (next is IAtomicOperation) {
183          IAtomicOperation operation = (IAtomicOperation)next;
184          next = operation.Operator.Execute((IExecutionContext)operation, CancellationToken);
185          if (next != null) executionStack.Push(next);
186        }
187      }
188    }
189  }
190}
Note: See TracBrowser for help on using the repository browser.