Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.3/DefaultSymbolicExpressionGrammar.cs @ 4656

Last change on this file since 4656 was 4262, checked in by mkommend, 14 years ago

Made DefaultGrammar abstract and sealed GlobalGrammar (ticket #1028).

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