Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.EvolutionTracking/HeuristicLab.EvolutionTracking/3.4/Analyzers/GenealogyAnalyzer.cs @ 10755

Last change on this file since 10755 was 10755, checked in by bburlacu, 10 years ago

#1772: Simplified genealogy graph and fragment graph creation:

  • the genealogy graph now has a 1-1 mapping between content and vertices (as opposed to 1-n as it was previously, to account for elites); this required changes to the directed graph implementation
  • the fragment graph only contains bifurcation points (where the subtree contains the fragment so tracing must be done both ways (in the root parent AND in the other parent). in the other cases, tracing is restarted from the parent genealogy graph node.
File size: 12.1 KB
Line 
1using System.Linq;
2using HeuristicLab.Common;
3using HeuristicLab.Core;
4using HeuristicLab.Data;
5using HeuristicLab.Operators;
6using HeuristicLab.Optimization;
7using HeuristicLab.Parameters;
8using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
9
10namespace HeuristicLab.EvolutionTracking {
11  [StorableClass]
12  [Item("GenealogyAnalyzer", "An analyzer which performs the necessary instrumentation to record the evolution of a genetic algorithm.")]
13  public class GenealogyAnalyzer<T> : SingleSuccessorOperator, IAnalyzer
14  where T : class,IItem {
15
16    public string CrossoverParentsParameterName { get; set; }
17    public string CrossoverChildParameterName { get; set; }
18    public string ManipulatorChildParameterName { get; set; }
19
20    public IScopeTreeLookupParameter<DoubleValue> QualityParameter;
21    public IScopeTreeLookupParameter<T> PopulationParameter;
22
23    public ICrossoverOperator<T> BeforeCrossoverOperator { get; set; }
24    public ICrossoverOperator<T> AfterCrossoverOperator { get; set; }
25    public IManipulatorOperator<T> BeforeManipulatorOperator { get; set; }
26    public IManipulatorOperator<T> AfterManipulatorOperator { get; set; }
27
28    private const string PopulationParameterName = "Population";
29    private const string QualityParameterName = "Quality";
30
31    private const string GenerationsParameterName = "Generations";
32    private const string ResultsParameterName = "Results";
33    private const string PopulationGraphParameterName = "PopulationGraph";
34
35    private const string CrossoverParameterName = "Crossover";
36    private const string ManipulatorParameterName = "Mutator";
37    private const string SolutionCreatorParameterName = "SolutionCreator";
38
39    private const string EnableCrossoverTrackingParameterName = "EnableCrossoverTracking";
40    private const string EnableManipulatorTrackingParameterName = "EnableManipulatorTracking";
41    private const string EnableSolutionCreatorTrackingParameterName = "EnableSolutionCreatorTracking"; // should always be enabled. maybe superfluous
42
43    #region parameter properties
44    public ILookupParameter<ResultCollection> ResultsParameter {
45      get { return (ILookupParameter<ResultCollection>)Parameters[ResultsParameterName]; }
46    }
47    public ILookupParameter<IntValue> GenerationsParameter {
48      get { return (ILookupParameter<IntValue>)Parameters[GenerationsParameterName]; }
49    }
50    public IValueParameter<BoolValue> EnableCrossoverTrackingParameter {
51      get { return (IValueParameter<BoolValue>)Parameters[EnableCrossoverTrackingParameterName]; }
52    }
53    public IValueParameter<BoolValue> EnableManipulatorTrackingParameter {
54      get { return (IValueParameter<BoolValue>)Parameters[EnableManipulatorTrackingParameterName]; }
55    }
56    public IValueParameter<BoolValue> EnableSolutionCreatorTrackingParameter {
57      get { return (IValueParameter<BoolValue>)Parameters[EnableSolutionCreatorTrackingParameterName]; }
58    }
59    public ILookupParameter<ICrossover> CrossoverParameter {
60      get { return (ILookupParameter<ICrossover>)Parameters[CrossoverParameterName]; }
61    }
62    public ILookupParameter<IManipulator> ManipulatorParameter {
63      get { return (ILookupParameter<IManipulator>)Parameters[ManipulatorParameterName]; }
64    }
65    public ILookupParameter<ISolutionCreator> SolutionCreatorParameter {
66      get { return (ILookupParameter<ISolutionCreator>)Parameters[SolutionCreatorParameterName]; }
67    }
68    #endregion
69
70    #region properties
71    public ICrossover Crossover {
72      get { return CrossoverParameter.ActualValue; }
73    }
74    public IManipulator Manipulator {
75      get { return ManipulatorParameter.ActualValue; }
76    }
77    public ISolutionCreator SolutionCreator {
78      get { return SolutionCreatorParameter.ActualValue; }
79    }
80    public BoolValue EnableCrossoverTracking {
81      get { return EnableCrossoverTrackingParameter.Value; }
82    }
83    public BoolValue EnableManipulatorTracking {
84      get { return EnableManipulatorTrackingParameter.Value; }
85    }
86    public BoolValue EnableSolutionCreatorTracking {
87      get { return EnableSolutionCreatorTrackingParameter.Value; }
88    }
89    public ResultCollection Results {
90      get { return ResultsParameter.ActualValue; }
91    }
92    public IntValue Generations {
93      get { return GenerationsParameter.ActualValue; }
94    }
95    public IGenealogyGraph<T> GenealogyGraph {
96      get {
97        IResult result;
98        if (!Results.ContainsKey(PopulationGraphParameterName)) {
99          result = new Result(PopulationGraphParameterName, new GenealogyGraph<T>());
100          Results.Add(result);
101        } else {
102          result = Results[PopulationGraphParameterName];
103        }
104        var graph = (IGenealogyGraph<T>)result.Value;
105        return graph;
106      }
107    }
108    #endregion
109
110    public GenealogyAnalyzer() {
111      // the instrumented operators
112      Parameters.Add(new LookupParameter<ICrossover>(CrossoverParameterName, "The crossover operator."));
113      Parameters.Add(new LookupParameter<IManipulator>(ManipulatorParameterName, "The manipulator operator."));
114      Parameters.Add(new LookupParameter<ISolutionCreator>(SolutionCreatorParameterName, "The solution creator operator."));
115      // the analyzer parameters
116      Parameters.Add(new ValueParameter<BoolValue>(EnableCrossoverTrackingParameterName, new BoolValue(true)));
117      Parameters.Add(new ValueParameter<BoolValue>(EnableManipulatorTrackingParameterName, new BoolValue(true)));
118      Parameters.Add(new ValueParameter<BoolValue>(EnableSolutionCreatorTrackingParameterName, new BoolValue(true)));
119      // parameters required by the analyzer to do its work
120      Parameters.Add(new LookupParameter<IntValue>(GenerationsParameterName, "The number of generations so far."));
121      Parameters.Add(new LookupParameter<ResultCollection>(ResultsParameterName));
122      PopulationParameter = new ScopeTreeLookupParameter<T>(PopulationParameterName);
123      QualityParameter = new ScopeTreeLookupParameter<DoubleValue>(QualityParameterName);
124      Parameters.Add(PopulationParameter);
125      Parameters.Add(QualityParameter);
126    }
127    public override IDeepCloneable Clone(Cloner cloner) {
128      return new GenealogyAnalyzer<T>(this, cloner);
129    }
130    protected GenealogyAnalyzer(GenealogyAnalyzer<T> original, Cloner cloner)
131      : base(original, cloner) {
132    }
133    [StorableHook(HookType.AfterDeserialization)]
134    private void AfterDeserialization() {
135      // the instrumented operators
136      if (!Parameters.ContainsKey(CrossoverParameterName))
137        Parameters.Add(new LookupParameter<ICrossover>(CrossoverParameterName, "The crossover operator."));
138      if (!Parameters.ContainsKey(ManipulatorParameterName))
139        Parameters.Add(new LookupParameter<IManipulator>(ManipulatorParameterName, "The manipulator operator."));
140      if (!Parameters.ContainsKey(SolutionCreatorParameterName))
141        Parameters.Add(new LookupParameter<ISolutionCreator>(SolutionCreatorParameterName, "The solution creator operator."));
142      // the analyzer parameters
143      if (!Parameters.ContainsKey(EnableCrossoverTrackingParameterName))
144        Parameters.Add(new ValueParameter<BoolValue>(EnableCrossoverTrackingParameterName, new BoolValue(true)));
145      if (!Parameters.ContainsKey(EnableManipulatorTrackingParameterName))
146        Parameters.Add(new ValueParameter<BoolValue>(EnableManipulatorTrackingParameterName, new BoolValue(true)));
147      if (!Parameters.ContainsKey(EnableSolutionCreatorTrackingParameterName))
148        Parameters.Add(new ValueParameter<BoolValue>(EnableSolutionCreatorTrackingParameterName, new BoolValue(true)));
149      // parameters required by the analyzer to do its work
150      if (!Parameters.ContainsKey(GenerationsParameterName))
151        Parameters.Add(new LookupParameter<IntValue>(GenerationsParameterName, "The number of generations so far."));
152      if (!Parameters.ContainsKey(ResultsParameterName))
153        Parameters.Add(new LookupParameter<ResultCollection>(ResultsParameterName));
154      if (!Parameters.ContainsKey(PopulationParameterName)) {
155        PopulationParameter = new ScopeTreeLookupParameter<T>(PopulationParameterName);
156        Parameters.Add(PopulationParameter);
157      }
158      if (!Parameters.ContainsKey(QualityParameterName)) {
159        QualityParameter = new ScopeTreeLookupParameter<DoubleValue>(QualityParameterName);
160        Parameters.Add(QualityParameter);
161      }
162    }
163
164    public bool EnabledByDefault {
165      get { return false; }
166    }
167
168    private void ConfigureTrackingOperators() {
169      // at the beginning we add the before/after operators to the instrumented operators
170      if (Crossover != null) {
171        var instrumentedCrossover = (InstrumentedOperator)Crossover;
172        instrumentedCrossover.AfterExecutionOperators.Clear();
173        instrumentedCrossover.BeforeExecutionOperators.Clear();
174
175        if (EnableCrossoverTracking.Value) {
176          if (BeforeCrossoverOperator != null) {
177            BeforeCrossoverOperator.ParentsParameter.ActualName = CrossoverParentsParameterName;
178            BeforeCrossoverOperator.ChildParameter.ActualName = CrossoverChildParameterName;
179            instrumentedCrossover.BeforeExecutionOperators.Add(BeforeCrossoverOperator);
180          }
181          if (AfterCrossoverOperator != null) {
182            AfterCrossoverOperator.ParentsParameter.ActualName = CrossoverParentsParameterName;
183            AfterCrossoverOperator.ChildParameter.ActualName = CrossoverChildParameterName;
184            instrumentedCrossover.AfterExecutionOperators.Add(AfterCrossoverOperator);
185          }
186        }
187      }
188
189      if (Manipulator != null) {
190        var instrumentedManipulator = (InstrumentedOperator)Manipulator;
191        instrumentedManipulator.AfterExecutionOperators.Clear();
192        instrumentedManipulator.BeforeExecutionOperators.Clear();
193
194        if (EnableManipulatorTracking.Value) {
195          if (BeforeManipulatorOperator != null) {
196            BeforeManipulatorOperator.ChildParameter.ActualName = ManipulatorChildParameterName;
197            instrumentedManipulator.BeforeExecutionOperators.Add(BeforeManipulatorOperator);
198          }
199          if (AfterManipulatorOperator != null) {
200            AfterManipulatorOperator.ChildParameter.ActualName = ManipulatorChildParameterName;
201            instrumentedManipulator.AfterExecutionOperators.Add(AfterManipulatorOperator);
202          }
203        }
204      }
205    }
206
207    public override IOperation Apply() {
208      var population = PopulationParameter.ActualValue.ToList();
209      var qualities = QualityParameter.ActualValue.ToList();
210
211      if (Generations.Value == 0) {
212        ConfigureTrackingOperators();
213
214        for (int i = 0; i < population.Count; ++i) {
215          var individual = population[i];
216          var vertex = new GenealogyGraphNode<T> { Content = individual, Rank = Generations.Value, };
217          GenealogyGraph.AddVertex(vertex);
218          // save the vertex id in the individual scope (so that we can identify graph indices)
219          ExecutionContext.Scope.SubScopes[i].Variables.Add(new Variable("Id", new StringValue(vertex.Id)));
220        }
221      } else {
222        var elite = population.FirstOrDefault(x => GenealogyGraph.Contains(x));
223        if (elite != null) {
224          var vertex = new GenealogyGraphNode<T> {
225            Content = (T)elite.Clone(),
226            Rank = Generations.Value,
227            IsElite = true
228          };
229          var previousVertex = (IGenealogyGraphNode<T>)GenealogyGraph[elite];
230          GenealogyGraph.AddVertex(vertex);
231          previousVertex.AddForwardArc(vertex);
232          vertex.AddReverseArc(previousVertex);
233          vertex.Id = previousVertex.Id; // another way would be to introduce the vertex.Id into the scope of the elite
234          vertex.Quality = previousVertex.Quality;
235
236          if (previousVertex.InArcs.Any()) {
237            vertex.InArcs.Last().Data = previousVertex.InArcs.Last().Data; // save the fragment in case there is one
238          }
239        }
240      }
241      // update qualities
242      for (int i = 0; i < population.Count; ++i) {
243        var vertex = (IGenealogyGraphNode)GenealogyGraph[population[i]];
244        vertex.Quality = qualities[i].Value;
245      }
246
247      return base.Apply();
248    }
249  }
250}
Note: See TracBrowser for help on using the repository browser.