Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior/3.3/Analyzers/BuildingBlockAnalyzer.cs @ 8216

Last change on this file since 8216 was 8216, checked in by jkarder, 13 years ago

#1886:

  • added SchemaAnalyzer
  • added BrokenInteritanceSchemaAnalyzer
File size: 12.1 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2012 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.Linq;
23using HeuristicLab.Common;
24using HeuristicLab.Core;
25using HeuristicLab.Operators;
26using HeuristicLab.Optimization;
27using HeuristicLab.Parameters;
28using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
29
30namespace HeuristicLab.Analysis.AlgorithmBehavior {
31  using System;
32  using System.Collections.Generic;
33  using HeuristicLab.Data;
34  using HeuristicLab.Encodings.PermutationEncoding;
35  using TraceMapType = HeuristicLab.Core.ItemDictionary<HeuristicLab.Core.IItem, HeuristicLab.Core.IItemList<HeuristicLab.Core.IItem>>;
36
37  /// <summary>
38  /// An operator that analyzes building blocks.
39  /// </summary>
40  [Item("BuildingBlockAnalyzer", "An operator that analyzes building blocks.")]
41  [StorableClass]
42  public sealed class BuildingBlockAnalyzer : SingleSuccessorOperator, IAnalyzer {
43    private const string GlobalTraceMapParameterName = "GlobalTraceMap";
44    private const string ResultsParameterName = "Results";
45    private const string PopulationGraphResultParameterName = "PopulationGraph";
46    private const string BuildingBlockSchemaMatrixParameterName = "BuildingBlockSchemaMatrix";
47    private const string BrokenInteritanceSchemaOccurrenceName = "BrokenInteritanceSchemaOccurrenceMatrix";
48    private const string UnbrokenInteritanceSchemaOccurrenceName = "UnbrokenInteritanceSchemaOccurrence";
49    private const string BuildingBlockPatternMatrixParameterName = "BuildingBlockPatternMatrix";
50
51    #region IAnalyzer Members
52    public bool EnabledByDefault {
53      get { return true; }
54    }
55    #endregion
56
57    #region Parameter properties
58    public ILookupParameter<TraceMapType> GlobalTraceMapParameter {
59      get { return (ILookupParameter<TraceMapType>)Parameters[GlobalTraceMapParameterName]; }
60    }
61    public ILookupParameter<ResultCollection> ResultsParameter {
62      get { return (ILookupParameter<ResultCollection>)Parameters[ResultsParameterName]; }
63    }
64    #endregion
65
66    #region Properties
67    public TraceMapType GlobalTraceMap {
68      get { return GlobalTraceMapParameter.ActualValue; }
69    }
70    public ResultCollection Results {
71      get { return ResultsParameter.ActualValue; }
72    }
73    #endregion
74
75    [StorableConstructor]
76    private BuildingBlockAnalyzer(bool deserializing) : base(deserializing) { }
77    private BuildingBlockAnalyzer(BuildingBlockAnalyzer original, Cloner cloner) : base(original, cloner) { }
78    public BuildingBlockAnalyzer()
79      : base() {
80      Parameters.Add(new LookupParameter<TraceMapType>(GlobalTraceMapParameterName, "A global cache containing the whole genealogy."));
81      Parameters.Add(new LookupParameter<ResultCollection>(ResultsParameterName, "The results collection where the analysis values should are stored."));
82    }
83
84    public override IDeepCloneable Clone(Cloner cloner) {
85      return new BuildingBlockAnalyzer(this, cloner);
86    }
87
88    public override IOperation Apply() {
89      var graph = (GenealogyGraph<Permutation>)Results[PopulationGraphResultParameterName].Value;
90      var generationZero = graph.Values.Where(x => x.Rank == 0);
91
92      // extract all subtours for each individual in generation zero
93      var subtours = new Dictionary<Permutation, IList<int[]>>();
94      foreach (var individual in generationZero) {
95        subtours[(Permutation)individual.Data] = ExtractSubtours((Permutation)individual.Data);
96      }
97
98      // process all schemata
99      var schemataMatrix = new Dictionary<int[], int[]>(new SchemaEqualityComparer());
100      foreach (var entry in subtours) {
101        foreach (var schema in entry.Value) {
102          if (!schemataMatrix.ContainsKey(schema)) {
103            var categories = new int[3];
104            categories[0] = ExploreGlobalSchemaOccurrence(graph, schema);
105            categories[1] = -1;
106            categories[2] = -1;
107            schemataMatrix.Add(schema, categories);
108          }
109        }
110      }
111
112      // order schemas according to their global occurrence count
113      var sortedSchemataMatrix = schemataMatrix.OrderByDescending(x => x.Value[0]).ToDictionary(x => x.Key, x => x.Value);
114      IList<string> rowNames = new List<string>();
115      var schemataStringMatrix = new StringMatrix(sortedSchemataMatrix.Keys.Count, 3);
116      for (int i = 0; i < sortedSchemataMatrix.Keys.Count; i++) {
117        var element = sortedSchemataMatrix.ElementAt(i);
118        rowNames.Add(new Permutation(PermutationTypes.RelativeUndirected, element.Key).ToString());
119        for (int j = 0; j < element.Value.Count(); j++) {
120          schemataStringMatrix[i, j] = element.Value[j].ToString();
121        }
122      }
123      schemataStringMatrix.RowNames = rowNames;
124      schemataStringMatrix.ColumnNames = new[] { "GlobalSchemaOccurrence", "<unused>", "<unused>" };
125      Results.Add(new Result(BuildingBlockSchemaMatrixParameterName, schemataStringMatrix));
126
127      var brokenInteritanceSchemaOccurrenceMatrix = new StringMatrix(sortedSchemataMatrix.Keys.Count, generationZero.Count());
128      IList<string> brokenRowNames = new List<string>();
129      IList<string> brokenColumnNames = new List<string>();
130      for (int i = 0; i < sortedSchemataMatrix.Keys.Count; i++) {
131        var entry = sortedSchemataMatrix.ElementAt(i);
132        brokenRowNames.Add(new Permutation(PermutationTypes.RelativeUndirected, entry.Key).ToString());
133        for (int j = 0; j < generationZero.Count(); j++) {
134          var individual = generationZero.ElementAt(j);
135          if (i == 0) brokenColumnNames.Add(((Permutation)individual.Data).ToString());
136          brokenInteritanceSchemaOccurrenceMatrix[i, j] = CalculateBrokenInheritanceOccurrences(entry.Key, individual).ToString();
137        }
138      }
139      brokenInteritanceSchemaOccurrenceMatrix.RowNames = brokenRowNames;
140      brokenInteritanceSchemaOccurrenceMatrix.ColumnNames = brokenColumnNames;
141      Results.Add(new Result(BrokenInteritanceSchemaOccurrenceName, brokenInteritanceSchemaOccurrenceMatrix));
142
143      var unbrokenInteritanceSchemaOccurrenceMatrix = new StringMatrix(sortedSchemataMatrix.Keys.Count, generationZero.Count());
144      IList<string> unbrokenRowNames = new List<string>();
145      IList<string> unbrokenColumnNames = new List<string>();
146      for (int i = 0; i < sortedSchemataMatrix.Keys.Count; i++) {
147        var entry = sortedSchemataMatrix.ElementAt(i);
148        unbrokenRowNames.Add(new Permutation(PermutationTypes.RelativeUndirected, entry.Key).ToString());
149        for (int j = 0; j < generationZero.Count(); j++) {
150          var individual = generationZero.ElementAt(j);
151          if (i == 0) unbrokenColumnNames.Add(((Permutation)individual.Data).ToString());
152          unbrokenInteritanceSchemaOccurrenceMatrix[i, j] = CalculateUnbrokenInheritanceOccurrences(entry.Key, individual).ToString();
153        }
154      }
155      unbrokenInteritanceSchemaOccurrenceMatrix.RowNames = unbrokenRowNames;
156      unbrokenInteritanceSchemaOccurrenceMatrix.ColumnNames = brokenColumnNames;
157      Results.Add(new Result(UnbrokenInteritanceSchemaOccurrenceName, unbrokenInteritanceSchemaOccurrenceMatrix));
158
159      return base.Apply();
160    }
161
162    private int CalculateBrokenInheritanceOccurrences(int[] schema, GenealogyGraphNode individual) {
163      // TODO
164      return -1;
165    }
166
167    private int CalculateUnbrokenInheritanceOccurrences(int[] schema, GenealogyGraphNode individual) {
168      var filteredDescendants = individual.Descendants().Where(x => IsMatch(schema, ((Permutation)x.Data).ToArray()));
169      return filteredDescendants.Any() ? (int)filteredDescendants.Max(x => x.Rank) : 0;
170    }
171
172    private int ExploreGlobalSchemaOccurrence(GenealogyGraph<Permutation> graph, int[] schema) {
173      int occurrences = 0;
174      foreach (var individual in graph.Values)
175        if (IsSubtour(schema, (Permutation)individual.Data)) occurrences++;
176      return occurrences;
177    }
178
179    private IList<int[]> ExtractSubtours(Permutation permutation) {
180      var subtours = new List<int[]>();
181      for (int i = 2; i <= permutation.Count() / 2; i++) { // increase schema length from 2 to n/2
182        for (int j = 0; j < permutation.Count(); j++) { // visit all positions in the permutation
183          var schema = new int[i];
184          for (int k = 0; k < i; k++) schema[k] = permutation[(j + k) % permutation.Length]; // copy edge to schema
185          subtours.Add(schema);
186        }
187      }
188      return subtours;
189    }
190
191    private bool IsSubtour(int[] tour, Permutation permutation) {
192      // determine starting position for subtour match
193      int idx = permutation.Select((x, index) => new { Value = x, Index = index }).Single(x => x.Value == tour[0]).Index;
194      bool isSubtour = true;
195      for (int i = 1; i < tour.Length; i++) {
196        if (tour[i] == permutation[(idx + 1) % permutation.Length]) { // check right side
197          idx = (idx + 1) % permutation.Length;
198        } else if (tour[i] == permutation[(idx - 1 + permutation.Length) % permutation.Length]) { // check left side
199          idx = (idx - 1 + permutation.Length) % permutation.Length;
200        } else {
201          isSubtour = false;
202          break;
203        }
204      }
205      return isSubtour;
206    }
207
208    // attention: brute force matching
209    // should be replaced with KMP, BM or RK
210    private bool IsMatch(int[] pattern, int[] tour) {
211      bool match = false;
212      for (int i = 0; i <= tour.Length - pattern.Length && !match; i++) {
213        for (int j = 0; j < pattern.Length && (match = pattern[j] == tour[i + j] || pattern[j] == -1); j++) ;
214      }
215      return match;
216    }
217
218    private IList<int[]> GenerateWildcardSchemata(int[] schema) {
219      string formatString = "{0:d" + schema.Length + "}";
220      var combs = new List<bool[]>();
221      string comb = string.Empty;
222
223      // create all desired wildcard combinations
224      int i = 0;
225      int wildcardCount = 0; // first wildcard combination contains no wildcards
226      while (wildcardCount < schema.Length) {
227        if (wildcardCount > schema.Length / 8 && wildcardCount < schema.Length / 2)
228          combs.Add(comb.Select(x => x == '1').ToArray()); // '1' becomes true which indicates a wildcard
229        wildcardCount = (comb = string.Format(formatString, Convert.ToString(++i, 2))).Count(x => x == '1');
230      }
231
232      // create all desired wildcard instances
233      var wildcardSchemata = new List<int[]>();
234      foreach (var c in combs) {
235        wildcardSchemata.Add(schema.Select((x, index) => c[index] ? -1 : x).ToArray()); // -1 is a wildcard in the schema
236      }
237
238      return wildcardSchemata;
239    }
240
241
242    private class SchemaEqualityComparer : EqualityComparer<int[]> {
243      public override bool Equals(int[] x, int[] y) {
244        if (object.ReferenceEquals(x, y)) return true;
245        if (x == null || y == null || x.Length != y.Length) return false;
246        EqualityComparer<int> comparer = EqualityComparer<int>.Default;
247        bool match = true;
248        for (int i = 0; i < x.Length && match; i++) // check normal tour
249          if (!comparer.Equals(x[i], y[i])) match = false;
250        if (!match) {
251          match = true;
252          for (int i = x.Length - 1; i >= 0 && match; i--) // check inverse tour
253            if (!comparer.Equals(x[i], y[i])) match = false;
254        }
255        return match;
256      }
257
258      public override int GetHashCode(int[] obj) {
259        return 0; // return the same hash code for each object, otherwise Equals will not be called
260      }
261    }
262  }
263}
Note: See TracBrowser for help on using the repository browser.