Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 3541 was 3541, checked in by gkronber, 14 years ago

Fixed bugs in persistence of grammars.#937 (Data types and operators for symbolic expression tree encoding)

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