Free cookie consent management tool by TermsFeed Policy Generator

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

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

Fixed bugs in ADF operators and added test classes for ADF operators. #290 (Implement ADFs)

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