Free cookie consent management tool by TermsFeed Policy Generator

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

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

Changed way the grammar is stored in tree nodes to make it more efficient and fixed bugs in symbolic expression tree operators. #290 (Implement ADFs)

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