Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2988_ModelsOfModels2/HeuristicLab.Algorithms.EMM/EMMAlgorithm/EMMAlgorithm.cs @ 17364

Last change on this file since 17364 was 17134, checked in by msemenki, 5 years ago

#2988:

  1. The file system was changed, folders was added and part of files was transferred in these folders.
  2. HelpFunctions class was divided on 2 parts: HelpFuctions for common purposes static functions and SelfConfiguration that include functions for self-configuration mechanism realization (is used in EMMSucsessMap).
  3. Parts of self-configuration mechanism was transferred from EMMSucsessMap.cs to SelfConfiguration.cs. Now EMMSucsessMap used SelfConfiguration like one of data member. Other parts of project was adopted for this changing.
  4. FileComunication class was added. It include the majority of functions for printing to files or reading from files. Here were realized possibility to write and read to hl files.
  5. ModelTreeNode.cs has additional possibility - to write sub-model in string (then it is possible to write it in file).
  6. InfixExpressionFormatter.cs can work with TreeModelNode.
  7. Possibility for different map types to be readable from files was extended and cheeked.
  8. Such parameters like - ClusterNumbers, ClusterNumbersShow, NegbourNumber, NegbourType (that is used only in several maps) was transferred from EMMAlgorithm to Map Parameters. Now EMMBaseMap class inherited from ParameterizedNamedItem (not from Item). And EMMIslandMap and EMMNetworkMap contains their parameters (constructors was modified). CreationMap calls functions were simplified.
  9. Functions for different distance metric calculation was added. Now, it is possible to calculate different types of distances between models (with different random values of constants).
  10. DistanceParametr was added. Now maps can be created according different types of distance calculations.
  11. The class EMMClustering has new name KMeansClusterizationAlgorithm. On KMeansClusterizationAlgorithm bug with bloating of centroids list was fixed. Algorithm was adopted for working with different type of distance metric and get maximum number of iterations.
  12. Possibilities for constants optimization in sub-models an whole tree was added. EMMAlgorithm get new function for evaluation of individuals (and some additional technical stuff for that). Function for trees with model in usual tree transformation and back was added.
  13. EMMAlgorithm was divided on 2 parts:
  • EMMAlgorithm, that contain evolutionary algorithm working with sub-models, and use ready to use maps;
  • ModelSetPreparation, that contain distance calculation, model set simplification and map creation.
File size: 17.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 HEAL.Attic;
23using HeuristicLab.Common;
24using HeuristicLab.Core;
25using HeuristicLab.Data;
26using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
27using HeuristicLab.Problems.DataAnalysis;
28using HeuristicLab.Problems.DataAnalysis.Symbolic;
29using HeuristicLab.Problems.DataAnalysis.Symbolic.Regression;
30using HeuristicLab.Random;
31using HeuristicLab.Selection;
32using System.Collections.Generic;
33using System.Linq;
34using CancellationToken = System.Threading.CancellationToken;
35using Variable = HeuristicLab.Core.Variable;
36
37namespace HeuristicLab.Algorithms.EvolvmentModelsOfModels {
38  [Item("Evolvement Models Of Models Algorithm (EMM) ", "EMM implementation")]
39  [Creatable(CreatableAttribute.Categories.PopulationBasedAlgorithms, Priority = 125)]
40  [StorableType("AD23B21F-089A-4C6C-AD2E-1B01E7939CF5")]
41  public class EMMAlgorithm : EvolvmentModelsOfModelsAlgorithmBase {
42    #region Constructors
43    public EMMAlgorithm() : base() { }
44    protected EMMAlgorithm(EMMAlgorithm original, Cloner cloner) : base(original, cloner) { }
45    public override IDeepCloneable Clone(Cloner cloner) {
46      return new EMMAlgorithm(this, cloner);
47    }
48
49    [StorableConstructor]
50    protected EMMAlgorithm(StorableConstructorFlag _) : base(_) { }
51    #endregion
52    #region Algorithm run
53    protected override void Run(CancellationToken cancellationToken) {
54
55      Map.DistanceParametr = DistanceType.Value;
56
57      if (AlgorithmImplemetationType.Value == "Read") {
58        Map.MapRead(trees);
59      } else {
60        Map.MapCreationPrepare(trees);
61        Map.CreateMap(RandomParameter.Value, Problem);
62      }
63      if (previousExecutionState != ExecutionState.Paused) {
64        InitializeAlgorithm(cancellationToken);
65      }
66      if (!globalScope.Variables.ContainsKey("TreeModelMap"))
67        globalScope.Variables.Add(new Variable("TreeModelMap", Map));
68      if (!globalScope.Variables.ContainsKey("Map"))
69        globalScope.Variables.Add(new Variable("Map", Map));
70      EMMAlgorithmRun(cancellationToken);
71    }
72    private void EMMAlgorithmRun(CancellationToken cancellationToken) {
73      var bestSelector = new BestSelector();
74      bestSelector.CopySelected = new BoolValue(false);
75      bestSelector.MaximizationParameter.ActualName = "Maximization";
76      bestSelector.NumberOfSelectedSubScopesParameter.ActualName = "Elites";
77      bestSelector.QualityParameter.ActualName = "Quality";
78
79      var maximumEvaluatedSolutions = MaximumEvaluatedSolutions.Value;
80      var crossover = Crossover;
81      var selector = Selector;
82      var crossoverProbability = CrossoverProbability.Value;
83      var mutator = Mutator;
84      var mutationProbability = MutationProbability.Value;
85      var evaluator = Problem.Evaluator;
86      var analyzer = Analyzer;
87      var rand = RandomParameter.Value;
88      var elites = Elites.Value;
89      var fmd = new InfixExpressionFormatter();
90      // cancellation token for the inner operations which should not be immediately canceled
91      var innerToken = new CancellationToken();
92      // for future
93      //var mutatorTypes = new SymbolicExpressionTreeManipulator[]
94      //{
95      //     new EMMMultyPointsMutator(),
96      //     new EMMMultyPointsMutatorNodeTypeSaving (),
97      //     new EMMMutators()
98      //};
99      //var tuu = MutatorParameter.ValidValues;
100      //var select = SelectorParameter.ValidValues;
101
102      while (EvaluatedSolutions < maximumEvaluatedSolutions && !cancellationToken.IsCancellationRequested) {
103
104        var op4 = executionContext.CreateChildOperation(bestSelector, executionContext.Scope); // select elites
105        ExecuteOperation(executionContext, innerToken, op4);
106
107        var remaining = executionContext.Scope.SubScopes.Single(x => x.Name == "Remaining");
108        executionContext.Scope.SubScopes.AddRange(remaining.SubScopes);
109        var selected = executionContext.Scope.SubScopes.Single(x => x.Name == "Selected");
110        executionContext.Scope.SubScopes.AddRange(selected.SubScopes);
111        Population.Clear();
112        Population.AddRange(selected.SubScopes.Select(x => new EMMSolution(x)));
113        executionContext.Scope.SubScopes.Remove(remaining);
114        executionContext.Scope.SubScopes.Remove(selected);
115
116        var op = executionContext.CreateChildOperation(selector, executionContext.Scope);// select the rest of the Population
117        ExecuteOperation(executionContext, innerToken, op);
118
119        remaining = executionContext.Scope.SubScopes.Single(x => x.Name == "Remaining");
120        selected = executionContext.Scope.SubScopes.Single(x => x.Name == "Selected");
121
122        for (int i = 0; i < selector.NumberOfSelectedSubScopesParameter.Value.Value; i += 2) {
123          IScope childScope = null;
124          // for future
125          //var obbbb = CrossoverParameter.ValidValues.ToList();
126          //int nn = 3;
127          //if (rand.NextDouble() < crossoverProbability) {
128          //  childScope = new Scope($"{i}+{i + 1}") { Parent = executionContext.Scope };
129          //  childScope.SubScopes.Add(selected.SubScopes[i]);
130          //  childScope.SubScopes.Add(selected.SubScopes[i + 1]);
131          //  var op1 = executionContext.CreateChildOperation(obbbb[nn], childScope);
132          //  ExecuteOperation(executionContext, innerToken, op1);
133          //  childScope.SubScopes.Clear();
134          //}
135
136          if (rand.NextDouble() < crossoverProbability) {
137            childScope = new Scope($"{i}+{i + 1}") { Parent = executionContext.Scope };
138            childScope.SubScopes.Add(selected.SubScopes[i]);
139            childScope.SubScopes.Add(selected.SubScopes[i + 1]);
140            var op1 = executionContext.CreateChildOperation(crossover, childScope);
141            ExecuteOperation(executionContext, innerToken, op1);
142            childScope.SubScopes.Clear();
143          }
144
145          childScope = childScope ?? selected.SubScopes[i];
146          // mutation
147          if (rand.NextDouble() < mutationProbability) {
148            var op2 = executionContext.CreateChildOperation(mutator, childScope);
149            ExecuteOperation(executionContext, innerToken, op2);
150          }
151
152          // evaluation
153          if (childScope != null) {
154            if (!childScope.Variables.ContainsKey("Quality"))
155              childScope.Variables.Add(new Variable("Quality"));
156            EvaluationComplex(executionContext, innerToken, childScope);
157          } else {// no crossover or mutation were applied, a child was not produced, do nothing
158            Population.Add(new EMMSolution(selected.SubScopes[i]));
159          }
160          if (EvaluatedSolutions >= maximumEvaluatedSolutions) {
161            break;
162          }
163        }
164
165        UpDateParameters();
166
167        globalScope.SubScopes.Replace(Population.Select(x => (IScope)x.Individual));
168        // run analyzer
169        var analyze = executionContext.CreateChildOperation(analyzer, globalScope);
170        ExecuteOperation(executionContext, innerToken, analyze);
171
172        Results.AddOrUpdateResult("Evaluated Solutions", new IntValue(EvaluatedSolutions));
173      }
174    }
175    protected virtual void UpDateParameters() {
176      if (Map is EMMSucsessMap) {
177        var population = new Dictionary<ISymbolicExpressionTree, double>();
178        foreach (var individ in Population) {
179          var tree = (ISymbolicExpressionTree)(((IScope)individ.Individual).Variables["SymbolicExpressionTree"].Value);
180          population.Add(tree, individ.Qualities.Value);
181        }
182        Map.MapUpDate(population);
183        population.Clear();
184      }
185    }
186    #endregion
187    #region Initialization
188    protected void InitializeAlgorithm(CancellationToken cancellationToken) {
189      globalScope = new Scope("Global Scope");
190      executionContext = new ExecutionContext(null, this, globalScope);
191
192      // set the execution context for parameters to allow lookup
193      foreach (var parameter in Problem.Parameters.OfType<IValueParameter>()) {
194        globalScope.Variables.Add(new Variable(parameter.Name, parameter.Value));
195      }
196      globalScope.Variables.Add(new Variable("Results", Results)); // make results available as a parameter for analyzers etc.
197
198      var rand = RandomParameter.Value;
199      if (SetSeedRandomly) Seed = RandomSeedGenerator.GetSeed();
200      rand.Reset(Seed);
201      EvaluatedSolutions = 0;
202      //  InitializeParametrs(); for future
203      InitializePopulation(executionContext, cancellationToken, rand);
204
205
206      base.Initialize(cancellationToken);
207    }
208    protected virtual void InitializeParametrs() { }
209
210    private void InitializePopulation(ExecutionContext executionContext, CancellationToken cancellationToken, IRandom random) {
211      Population = new List<IEMMSolution>();
212      var fmd = new InfixExpressionFormatter();
213      var evaluator = Problem.Evaluator;
214      var creator = Problem.SolutionCreator;
215      var parser = new InfixExpressionParser();
216
217      var parentScope = executionContext.Scope; //main scope for the next step work
218                                                // first, create all individuals
219      for (int i = 0; i < PopulationSize.Value; ++i) {
220        var childScope = new Scope(i.ToString()) { Parent = parentScope };
221        ExecuteOperation(executionContext, cancellationToken, executionContext.CreateChildOperation(creator, childScope));
222        var name = ((ISymbolicExpressionTreeCreator)creator).SymbolicExpressionTreeParameter.ActualName;
223        var tree = (ISymbolicExpressionTree)childScope.Variables[name].Value;
224
225        foreach (var node in tree.IterateNodesPostfix().OfType<TreeModelTreeNode>()) {
226          Map.NodeManipulationForInizializtion(random, node);
227        }
228        parentScope.SubScopes.Add(childScope);
229      }
230      // then, evaluate them and update qualities
231      for (int i = 0; i < PopulationSize.Value; ++i) {
232        var childScope = parentScope.SubScopes[i];
233        if (!childScope.Variables.ContainsKey("Quality"))
234          childScope.Variables.Add(new Variable("Quality", new DoubleValue(0)));
235        EvaluationComplex(executionContext, cancellationToken, childScope);
236      }
237    }
238    #endregion
239    #region Evaluators
240    private void EvaluationComplex(ExecutionContext executionContext, CancellationToken cancellationToken, IScope childScope) {
241      var evaluator = Problem.Evaluator;
242      if (evaluator is SymbolicRegressionConstantOptimizationEvaluator eval) {
243        var creator = Problem.SolutionCreator;
244        var name = ((ISymbolicExpressionTreeCreator)creator).SymbolicExpressionTreeParameter.ActualName;
245        var tree = (ISymbolicExpressionTree)childScope.Variables[name].Value;
246        var treeWithModelInside = ModelToTreePusher(tree);
247
248        //ExecuteOperation(executionContext, cancellationToken, executionContext.CreateChildOperation(evaluator, treeScope));
249        var pd = (IRegressionProblemData)Problem.ProblemData;
250        var estimationLimits = ((SymbolicRegressionSingleObjectiveProblem)Problem).EstimationLimits;
251        var interpreter = new SymbolicDataAnalysisExpressionTreeBatchInterpreter();
252        var quality = SymbolicRegressionConstantOptimizationEvaluator.OptimizeConstants(interpreter, treeWithModelInside, pd, pd.TrainingIndices, applyLinearScaling: true, maxIterations: 10, updateVariableWeights: true, lowerEstimationLimit: estimationLimits.Lower, upperEstimationLimit: estimationLimits.Upper, updateConstantsInTree: true);
253        childScope.Variables["Quality"].Value = new DoubleValue(quality);
254
255        int index = 0;
256        ConstuntValuesInTreeUpdate(tree, ConstantValuesFromTreeToListExtruction(treeWithModelInside), ref index);
257        childScope.Variables[name].Value = tree;
258        EvaluatedSolutions += 10;
259      } else {
260        var op3 = executionContext.CreateChildOperation(evaluator, childScope);
261        ExecuteOperation(executionContext, cancellationToken, op3);
262        EvaluatedSolutions += 1;
263      }
264      Population.Add(new EMMSolution(childScope));
265    }
266    private ISymbolicExpressionTree ModelToTreePusher(ISymbolicExpressionTree tree) {
267      //All model nodes in tree are exchange to trees that are stored in model nodes.
268      // After this function we have deal with usual tree
269      var clone = (ISymbolicExpressionTree)tree.Clone();
270      foreach (var node in clone.IterateNodesPostfix().OfType<TreeModelTreeNode>()) {
271        var newChild = node.Tree.Root.GetSubtree(0).GetSubtree(0);
272        Swap(node, newChild);
273      }
274      return clone;
275    }
276    protected static void Swap(ISymbolicExpressionTreeNode oldChild, ISymbolicExpressionTreeNode newChild) {
277      var parent = oldChild.Parent;
278      if (parent == null)
279        return;
280
281      var index = parent.IndexOfSubtree(oldChild);
282      parent.RemoveSubtree(index);
283      parent.InsertSubtree(index, newChild);
284    }
285    private List<double> ConstantValuesFromTreeToListExtruction(ISymbolicExpressionTree tree) {
286      //This function stored in a list all constants and coefficients from the tree
287      var constants = new List<double>();
288      foreach (var node in tree.IterateNodesPostfix()) {
289        if (node is ConstantTreeNode cNode) {
290          constants.Add(cNode.Value);
291        }
292        if (node is VariableTreeNode vNode) {
293          constants.Add(vNode.Weight);
294        }
295      }
296      return constants;
297    }
298    private void ConstuntValuesInTreeUpdate(ISymbolicExpressionTree tree, List<double> constants, ref int index) {
299      foreach (var node in tree.IterateNodesPostfix()) {
300        if (node is ConstantTreeNode cNode) {
301          cNode.Value = constants[index];
302          index++;
303        } else if (node is VariableTreeNode vNode) {
304          vNode.Weight = constants[index];
305          index++;
306        } else if (node is TreeModelTreeNode mNode) {
307          ConstuntValuesInTreeUpdate(mNode.Tree, constants, ref index);
308        }
309
310      }
311    }
312    #endregion
313    #region Local Search
314    // next function was not tested in real work
315    private void LocalDecent(ISymbolicDataAnalysisSingleObjectiveProblem problem, CancellationToken cancellationToken, IScope childScope) {
316      int maxStepNumber = 100;
317      var name = ((ISymbolicExpressionTreeCreator)Problem.SolutionCreator).SymbolicExpressionTreeParameter.ActualName;
318      var tree = (ISymbolicExpressionTree)childScope.Variables[name].Value;
319      var oldTree = tree.Clone();
320      ExecuteOperation(executionContext, cancellationToken, executionContext.CreateChildOperation(problem.Evaluator, childScope));
321      var rand = RandomParameter.Value;
322      if (SetSeedRandomly) Seed = RandomSeedGenerator.GetSeed();
323      rand.Reset(Seed);
324      while (maxStepNumber > 0) {
325        maxStepNumber = TreeIterator(tree.Root, rand, cancellationToken, childScope, maxStepNumber);
326      }
327    }
328    int TreeIterator(ISymbolicExpressionTreeNode a, IRandom rand, CancellationToken cancellationToken, IScope childScope, int maxStepNumber) {
329      if (a is TreeModelTreeNode modelNode) {
330        ModelChange(modelNode, rand, cancellationToken, childScope);
331        maxStepNumber--;
332      }
333      if (a.Subtrees != null) {
334        for (int i = 0; i < (a.Subtrees.Count()); i++) {
335          TreeIterator(a.Subtrees.ToList()[i], rand, cancellationToken, childScope, maxStepNumber);
336        }
337      }
338      return maxStepNumber;
339    }
340    void ModelChange(TreeModelTreeNode tree, IRandom rand, CancellationToken cancellationToken, IScope childScope) {
341      int treeNumber = tree.TreeNumber;
342      var oldSubTree = (ISymbolicExpressionTree)tree.Tree.Clone();
343      double oldQuality = ((DoubleValue)childScope.Variables["Quality"].Value).Value;
344      int cluster;
345      if (Map is EMMIslandMap map)
346        cluster = map.ClusterNumber[treeNumber];
347      else cluster = treeNumber;
348      int newTreeNumber = rand.Next(Map.Map[cluster].Count);
349      tree.Tree = (ISymbolicExpressionTree)Map.ModelSet[newTreeNumber].Clone();
350      tree.Tree.Root.ShakeLocalParameters(rand, 1);
351      var evaluator = Problem.Evaluator;
352      ExecuteOperation(executionContext, cancellationToken, executionContext.CreateChildOperation(evaluator, childScope));
353      double currentQuality = ((DoubleValue)childScope.Variables["Quality"].Value).Value;
354      if (oldQuality > currentQuality) {
355        tree.Tree = (ISymbolicExpressionTree)oldSubTree.Clone();
356        ((DoubleValue)childScope.Variables["Quality"].Value).Value = oldQuality;
357      }
358    }
359    #endregion
360  }
361
362
363}
364
Note: See TracBrowser for help on using the repository browser.