Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 3376 was 3376, checked in by swagner, 14 years ago

Moved interfaces and classes for deep cloning from HeuristicLab.Core to HeuristicLab.Common (#975).

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