Free cookie consent management tool by TermsFeed Policy Generator

source: branches/CloningRefactoring/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.3/DefaultSymbolicExpressionGrammar.cs @ 4674

Last change on this file since 4674 was 4674, checked in by gkronber, 13 years ago

Refactored cloning in SymbolicExpressionTreeEncoding. #922

File size: 15.2 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2010 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 System.Linq;
25using HeuristicLab.Common;
26using HeuristicLab.Core;
27using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Symbols;
28using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
29
30namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding {
31  /// <summary>
32  /// The default symbolic expression grammar stores symbols and syntactic constraints for symbols.
33  /// Symbols are treated as equvivalent if they have the same name.
34  /// Syntactic constraints limit the number of allowed sub trees for a node with a symbol and which symbols are allowed
35  /// in the sub-trees of a symbol (can be specified for each sub-tree index separately).
36  /// </summary>
37  [StorableClass]
38  [Item("DefaultSymbolicExpressionGrammar", "Represents a grammar that defines the syntax of symbolic expression trees.")]
39  public abstract class DefaultSymbolicExpressionGrammar : Item, ISymbolicExpressionGrammar {
40
41    #region properties for separation between implementation and persistence
42    [Storable]
43    private IEnumerable<KeyValuePair<string, int>> MinSubTreeCount {
44      get { return minSubTreeCount.AsEnumerable(); }
45      set { minSubTreeCount = value.ToDictionary(x => x.Key, x => x.Value); }
46    }
47
48    [Storable]
49    private IEnumerable<KeyValuePair<string, int>> MaxSubTreeCount {
50      get { return maxSubTreeCount.AsEnumerable(); }
51      set { maxSubTreeCount = value.ToDictionary(x => x.Key, x => x.Value); }
52    }
53
54    [Storable]
55    private IEnumerable<KeyValuePair<string, IEnumerable<IEnumerable<string>>>> AllowedChildSymbols {
56      get {
57        return (from parentEntry in allowedChildSymbols
58                let setEnumeration = parentEntry.Value.Select(set => set.AsEnumerable()).ToList()
59                select new KeyValuePair<string, IEnumerable<IEnumerable<string>>>(parentEntry.Key, setEnumeration))
60                .ToList();
61      }
62      set {
63        allowedChildSymbols = new Dictionary<string, List<List<string>>>();
64        foreach (var pair in value) {
65          allowedChildSymbols[pair.Key] = new List<List<string>>();
66          foreach (var entry in pair.Value) {
67            var hashSet = new List<string>();
68            foreach (string child in entry) {
69              hashSet.Add(child);
70            }
71            allowedChildSymbols[pair.Key].Add(hashSet);
72          }
73        }
74      }
75    }
76    [Storable]
77    private IEnumerable<KeyValuePair<string, Symbol>> AllSymbols {
78      get { return allSymbols.AsEnumerable(); }
79      set { allSymbols = value.ToDictionary(x => x.Key, x => x.Value); }
80    }
81    #endregion
82
83    private Dictionary<string, int> minSubTreeCount;
84    private Dictionary<string, int> maxSubTreeCount;
85    private Dictionary<string, List<List<string>>> allowedChildSymbols;
86    private Dictionary<string, Symbol> allSymbols;
87    [Storable]
88    private Symbol startSymbol;
89
90    [StorableConstructor]
91    protected DefaultSymbolicExpressionGrammar(bool deserializing)
92      : base(deserializing) {
93      cachedMinExpressionLength = new Dictionary<string, int>();
94      cachedMaxExpressionLength = new Dictionary<string, int>();
95      cachedMinExpressionDepth = new Dictionary<string, int>();
96    }
97    // cloning ctor
98    protected DefaultSymbolicExpressionGrammar(DefaultSymbolicExpressionGrammar original, Cloner cloner)
99      : base(original, cloner) {
100      this.cachedMinExpressionLength = new Dictionary<string, int>();
101      this.cachedMaxExpressionLength = new Dictionary<string, int>();
102      this.cachedMinExpressionDepth = new Dictionary<string, int>();
103      minSubTreeCount = new Dictionary<string, int>(original.minSubTreeCount);
104      maxSubTreeCount = new Dictionary<string, int>(original.maxSubTreeCount);
105
106      allSymbols = new Dictionary<string, Symbol>();
107      foreach (Symbol symbol in original.allSymbols.Values.Select(s => cloner.Clone(s)))
108        allSymbols.Add(symbol.Name, symbol);
109
110      startSymbol = cloner.Clone<Symbol>(original.startSymbol);
111      allowedChildSymbols = new Dictionary<string, List<List<string>>>();
112      foreach (var entry in original.allowedChildSymbols) {
113        allowedChildSymbols[entry.Key] = new List<List<string>>(entry.Value.Count);
114        foreach (var set in entry.Value) {
115          allowedChildSymbols[entry.Key].Add(new List<string>(set));
116        }
117      }
118    }
119    protected DefaultSymbolicExpressionGrammar()
120      : base() {
121      this.minSubTreeCount = new Dictionary<string, int>();
122      this.maxSubTreeCount = new Dictionary<string, int>();
123      this.allowedChildSymbols = new Dictionary<string, List<List<string>>>();
124      this.allSymbols = new Dictionary<string, Symbol>();
125      this.cachedMinExpressionLength = new Dictionary<string, int>();
126      this.cachedMaxExpressionLength = new Dictionary<string, int>();
127      this.cachedMinExpressionDepth = new Dictionary<string, int>();
128
129      this.startSymbol = new StartSymbol();
130      this.AddSymbol(startSymbol);
131      this.SetMinSubtreeCount(startSymbol, 1);
132      this.SetMaxSubtreeCount(startSymbol, 1);
133    }
134
135    protected DefaultSymbolicExpressionGrammar(ISymbolicExpressionGrammar grammar)
136      : base() {
137      Cloner cloner = new Cloner();
138      this.cachedMinExpressionLength = new Dictionary<string, int>();
139      this.cachedMaxExpressionLength = new Dictionary<string, int>();
140      this.cachedMinExpressionDepth = new Dictionary<string, int>();
141
142      this.minSubTreeCount = new Dictionary<string, int>();
143      this.maxSubTreeCount = new Dictionary<string, int>();
144      this.allowedChildSymbols = new Dictionary<string, List<List<string>>>();
145      this.allSymbols = new Dictionary<string, Symbol>();
146
147      this.StartSymbol = (Symbol)cloner.Clone(grammar.StartSymbol);
148
149      foreach (Symbol symbol in grammar.Symbols) {
150        Symbol clonedSymbol = (Symbol)cloner.Clone(symbol);
151        this.AddSymbol(clonedSymbol);
152        this.SetMinSubtreeCount(clonedSymbol, grammar.GetMinSubtreeCount(symbol));
153        this.SetMaxSubtreeCount(clonedSymbol, grammar.GetMaxSubtreeCount(symbol));
154      }
155
156      foreach (Symbol parent in grammar.Symbols) {
157        for (int i = 0; i < grammar.GetMaxSubtreeCount(parent); i++) {
158          foreach (Symbol child in grammar.Symbols) {
159            if (grammar.IsAllowedChild(parent, child, i)) {
160              this.SetAllowedChild((Symbol)cloner.Clone(parent), (Symbol)cloner.Clone(child), i);
161            }
162          }
163        }
164      }
165    }
166
167    public override IDeepCloneable Clone(Cloner cloner) {
168      return new DefaultSymbolicExpressionGrammar(this, cloner);
169    }
170
171    public void Clear() {
172      minSubTreeCount.Clear();
173      maxSubTreeCount.Clear();
174      allowedChildSymbols.Clear();
175      allSymbols.Clear();
176
177      cachedMaxExpressionLength.Clear();
178      cachedMinExpressionLength.Clear();
179      cachedMinExpressionDepth.Clear();
180
181      startSymbol = new StartSymbol();
182      AddSymbol(startSymbol);
183      SetMinSubtreeCount(startSymbol, 1);
184      SetMaxSubtreeCount(startSymbol, 1);
185    }
186
187    #region ISymbolicExpressionGrammar Members
188    public Symbol StartSymbol {
189      get { return startSymbol; }
190      set { startSymbol = value; }
191    }
192
193    public void AddSymbol(Symbol symbol) {
194      if (ContainsSymbol(symbol)) throw new ArgumentException("Symbol " + symbol + " is already defined.");
195      allSymbols.Add(symbol.Name, symbol);
196      allowedChildSymbols[symbol.Name] = new List<List<string>>();
197      ClearCaches();
198    }
199
200    public void RemoveSymbol(Symbol symbol) {
201      foreach (var parent in Symbols) {
202        for (int i = 0; i < GetMaxSubtreeCount(parent); i++)
203          if (IsAllowedChild(parent, symbol, i))
204            allowedChildSymbols[parent.Name][i].Remove(symbol.Name);
205      }
206      allSymbols.Remove(symbol.Name);
207      minSubTreeCount.Remove(symbol.Name);
208      maxSubTreeCount.Remove(symbol.Name);
209      allowedChildSymbols.Remove(symbol.Name);
210      ClearCaches();
211    }
212
213    public IEnumerable<Symbol> Symbols {
214      get { return allSymbols.Values.AsEnumerable(); }
215    }
216
217    public bool ContainsSymbol(Symbol symbol) {
218      return allSymbols.ContainsKey(symbol.Name);
219    }
220
221    public void SetAllowedChild(Symbol parent, Symbol child, int argumentIndex) {
222      if (!ContainsSymbol(parent)) throw new ArgumentException("Unknown symbol: " + parent, "parent");
223      if (!ContainsSymbol(child)) throw new ArgumentException("Unknown symbol: " + child, "child");
224      if (argumentIndex >= GetMaxSubtreeCount(parent)) throw new ArgumentException("Symbol " + parent + " can have only " + GetMaxSubtreeCount(parent) + " subtrees.");
225      allowedChildSymbols[parent.Name][argumentIndex].Add(child.Name);
226      ClearCaches();
227    }
228
229    public bool IsAllowedChild(Symbol parent, Symbol child, int argumentIndex) {
230      if (!ContainsSymbol(parent)) throw new ArgumentException("Unknown symbol: " + parent, "parent");
231      if (!ContainsSymbol(child)) throw new ArgumentException("Unknown symbol: " + child, "child");
232      if (argumentIndex >= GetMaxSubtreeCount(parent)) throw new ArgumentException("Symbol " + parent + " can have only " + GetMaxSubtreeCount(parent) + " subtrees.");
233      return allowedChildSymbols[parent.Name][argumentIndex].Contains(child.Name);
234    }
235
236    private Dictionary<string, int> cachedMinExpressionLength;
237    public int GetMinExpressionLength(Symbol symbol) {
238      if (!ContainsSymbol(symbol)) throw new ArgumentException("Unknown symbol: " + symbol);
239      if (!cachedMinExpressionLength.ContainsKey(symbol.Name)) {
240        cachedMinExpressionLength[symbol.Name] = int.MaxValue; // prevent infinite recursion
241        long sumOfMinExpressionLengths = 1 + (from argIndex in Enumerable.Range(0, GetMinSubtreeCount(symbol))
242                                              let minForSlot = (long)(from s in Symbols
243                                                                      where IsAllowedChild(symbol, s, argIndex)
244                                                                      select GetMinExpressionLength(s)).DefaultIfEmpty(0).Min()
245                                              select minForSlot).DefaultIfEmpty(0).Sum();
246
247        cachedMinExpressionLength[symbol.Name] = (int)Math.Min(sumOfMinExpressionLengths, int.MaxValue);
248      }
249      return cachedMinExpressionLength[symbol.Name];
250    }
251
252    private Dictionary<string, int> cachedMaxExpressionLength;
253    public int GetMaxExpressionLength(Symbol symbol) {
254      if (!ContainsSymbol(symbol)) throw new ArgumentException("Unknown symbol: " + symbol);
255      if (!cachedMaxExpressionLength.ContainsKey(symbol.Name)) {
256        cachedMaxExpressionLength[symbol.Name] = int.MaxValue; // prevent infinite recursion
257        long sumOfMaxTrees = 1 + (from argIndex in Enumerable.Range(0, GetMaxSubtreeCount(symbol))
258                                  let maxForSlot = (long)(from s in Symbols
259                                                          where IsAllowedChild(symbol, s, argIndex)
260                                                          select GetMaxExpressionLength(s)).DefaultIfEmpty(0).Max()
261                                  select maxForSlot).DefaultIfEmpty(0).Sum();
262        long limit = int.MaxValue;
263        cachedMaxExpressionLength[symbol.Name] = (int)Math.Min(sumOfMaxTrees, limit);
264      }
265      return cachedMaxExpressionLength[symbol.Name];
266    }
267
268    private Dictionary<string, int> cachedMinExpressionDepth;
269    public int GetMinExpressionDepth(Symbol symbol) {
270      if (!ContainsSymbol(symbol)) throw new ArgumentException("Unknown symbol: " + symbol);
271      if (!cachedMinExpressionDepth.ContainsKey(symbol.Name)) {
272        cachedMinExpressionDepth[symbol.Name] = int.MaxValue; // prevent infinite recursion
273        cachedMinExpressionDepth[symbol.Name] = 1 + (from argIndex in Enumerable.Range(0, GetMinSubtreeCount(symbol))
274                                                     let minForSlot = (from s in Symbols
275                                                                       where IsAllowedChild(symbol, s, argIndex)
276                                                                       select GetMinExpressionDepth(s)).DefaultIfEmpty(0).Min()
277                                                     select minForSlot).DefaultIfEmpty(0).Max();
278      }
279      return cachedMinExpressionDepth[symbol.Name];
280    }
281
282    public void SetMaxSubtreeCount(Symbol symbol, int nSubTrees) {
283      if (!ContainsSymbol(symbol)) throw new ArgumentException("Unknown symbol: " + symbol);
284      maxSubTreeCount[symbol.Name] = nSubTrees;
285      while (allowedChildSymbols[symbol.Name].Count <= nSubTrees)
286        allowedChildSymbols[symbol.Name].Add(new List<string>());
287      while (allowedChildSymbols[symbol.Name].Count > nSubTrees) {
288        allowedChildSymbols[symbol.Name].RemoveAt(allowedChildSymbols[symbol.Name].Count - 1);
289      }
290      ClearCaches();
291    }
292
293    public void SetMinSubtreeCount(Symbol symbol, int nSubTrees) {
294      if (!ContainsSymbol(symbol)) throw new ArgumentException("Unknown symbol: " + symbol);
295      minSubTreeCount[symbol.Name] = nSubTrees;
296      ClearCaches();
297    }
298
299    public int GetMinSubtreeCount(Symbol symbol) {
300      if (!ContainsSymbol(symbol)) throw new ArgumentException("Unknown symbol: " + symbol);
301      return minSubTreeCount[symbol.Name];
302    }
303
304    public int GetMaxSubtreeCount(Symbol symbol) {
305      if (!ContainsSymbol(symbol)) throw new ArgumentException("Unknown symbol: " + symbol);
306      return maxSubTreeCount[symbol.Name];
307    }
308    #endregion
309
310    private void ClearCaches() {
311      cachedMinExpressionLength.Clear();
312      cachedMaxExpressionLength.Clear();
313      cachedMinExpressionDepth.Clear();
314    }
315
316    protected void InitializeShallowClone(DefaultSymbolicExpressionGrammar original) {
317      minSubTreeCount = new Dictionary<string, int>(original.minSubTreeCount);
318      maxSubTreeCount = new Dictionary<string, int>(original.maxSubTreeCount);
319
320      allSymbols = new Dictionary<string, Symbol>(original.allSymbols);
321      startSymbol = original.startSymbol;
322      allowedChildSymbols = new Dictionary<string, List<List<string>>>(original.allowedChildSymbols.Count);
323      foreach (var entry in original.allowedChildSymbols) {
324        allowedChildSymbols[entry.Key] = new List<List<string>>(entry.Value.Count);
325        foreach (var set in entry.Value) {
326          allowedChildSymbols[entry.Key].Add(new List<string>(set));
327        }
328      }
329    }
330
331  }
332}
Note: See TracBrowser for help on using the repository browser.