Free cookie consent management tool by TermsFeed Policy Generator

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

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

Fixed bugs related to dynamic symbol constraints with ADFs. #290 (Implement ADFs)

File size: 10.2 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      allSymbols.RemoveWhere(s => s.Name == symbol.Name);
84      minSubTreeCount.Remove(symbol.Name);
85      maxSubTreeCount.Remove(symbol.Name);
86      allowedChildSymbols.Remove(symbol.Name);
87      ClearCaches();
88    }
89
90    public IEnumerable<Symbol> Symbols {
91      get { return allSymbols.AsEnumerable(); }
92    }
93
94    public void SetAllowedChild(Symbol parent, Symbol child, int argumentIndex) {
95      if (!allSymbols.Any(s => s.Name == parent.Name)) throw new ArgumentException("Unknown symbol: " + parent, "parent");
96      if (!allSymbols.Any(s => s.Name == child.Name)) throw new ArgumentException("Unknown symbol: " + child, "child");
97      if (argumentIndex >= GetMaxSubtreeCount(parent)) throw new ArgumentException("Symbol " + parent + " can have only " + GetMaxSubtreeCount(parent) + " subtrees.");
98      allowedChildSymbols[parent.Name][argumentIndex].Add(child.Name);
99      ClearCaches();
100    }
101
102    public bool IsAllowedChild(Symbol parent, Symbol child, int argumentIndex) {
103      if (!allSymbols.Any(s => s.Name == parent.Name)) throw new ArgumentException("Unknown symbol: " + parent, "parent");
104      if (!allSymbols.Any(s => s.Name == child.Name)) throw new ArgumentException("Unknown symbol: " + child, "child");
105      if (argumentIndex >= GetMaxSubtreeCount(parent)) throw new ArgumentException("Symbol " + parent + " can have only " + GetMaxSubtreeCount(parent) + " subtrees.");
106      if (allowedChildSymbols.ContainsKey(parent.Name)) return allowedChildSymbols[parent.Name][argumentIndex].Contains(child.Name);
107      return false;
108    }
109
110    private Dictionary<string, int> cachedMinExpressionLength;
111    public int GetMinExpressionLength(Symbol symbol) {
112      if (!allSymbols.Any(s => s.Name == symbol.Name)) throw new ArgumentException("Unknown symbol: " + symbol);
113      if (!cachedMinExpressionLength.ContainsKey(symbol.Name)) {
114        cachedMinExpressionLength[symbol.Name] = int.MaxValue; // prevent infinite recursion
115        long sumOfMinExpressionLengths = 1 + (from argIndex in Enumerable.Range(0, GetMinSubtreeCount(symbol))
116                                              let minForSlot = (long)(from s in allSymbols
117                                                                      where IsAllowedChild(symbol, s, argIndex)
118                                                                      select GetMinExpressionLength(s)).DefaultIfEmpty(0).Min()
119                                              select minForSlot).DefaultIfEmpty(0).Sum();
120
121        cachedMinExpressionLength[symbol.Name] = (int)Math.Min(sumOfMinExpressionLengths, int.MaxValue);
122      }
123      return cachedMinExpressionLength[symbol.Name];
124    }
125
126    private Dictionary<string, int> cachedMaxExpressionLength;
127    public int GetMaxExpressionLength(Symbol symbol) {
128      if (!allSymbols.Any(s => s.Name == symbol.Name)) throw new ArgumentException("Unknown symbol: " + symbol);
129      if (!cachedMaxExpressionLength.ContainsKey(symbol.Name)) {
130        cachedMaxExpressionLength[symbol.Name] = int.MaxValue; // prevent infinite recursion
131        long sumOfMaxTrees = 1 + (from argIndex in Enumerable.Range(0, GetMaxSubtreeCount(symbol))
132                                  let maxForSlot = (long)(from s in allSymbols
133                                                          where IsAllowedChild(symbol, s, argIndex)
134                                                          select GetMaxExpressionLength(s)).DefaultIfEmpty(0).Max()
135                                  select maxForSlot).DefaultIfEmpty(0).Sum();
136        long limit = int.MaxValue;
137        cachedMaxExpressionLength[symbol.Name] = (int)Math.Min(sumOfMaxTrees, limit);
138      }
139      return cachedMaxExpressionLength[symbol.Name];
140    }
141
142    private Dictionary<string, int> cachedMinExpressionDepth;
143    public int GetMinExpressionDepth(Symbol symbol) {
144      if (!allSymbols.Any(s => s.Name == symbol.Name)) throw new ArgumentException("Unknown symbol: " + symbol);
145      if (!cachedMinExpressionDepth.ContainsKey(symbol.Name)) {
146        cachedMinExpressionDepth[symbol.Name] = int.MaxValue; // prevent infinite recursion
147        cachedMinExpressionDepth[symbol.Name] = 1 + (from argIndex in Enumerable.Range(0, GetMinSubtreeCount(symbol))
148                                                     let minForSlot = (from s in allSymbols
149                                                                       where IsAllowedChild(symbol, s, argIndex)
150                                                                       select GetMinExpressionDepth(s)).DefaultIfEmpty(0).Min()
151                                                     select minForSlot).DefaultIfEmpty(0).Max();
152      }
153      return cachedMinExpressionDepth[symbol.Name];
154    }
155
156    public void SetMaxSubtreeCount(Symbol symbol, int nSubTrees) {
157      if (!allSymbols.Any(s => s.Name == symbol.Name)) throw new ArgumentException("Unknown symbol: " + symbol);
158      maxSubTreeCount[symbol.Name] = nSubTrees;
159      while (allowedChildSymbols[symbol.Name].Count <= nSubTrees)
160        allowedChildSymbols[symbol.Name].Add(new HashSet<string>());
161      while (allowedChildSymbols[symbol.Name].Count > nSubTrees) {
162        allowedChildSymbols[symbol.Name].RemoveAt(allowedChildSymbols[symbol.Name].Count - 1);
163      }
164      ClearCaches();
165    }
166
167    public void SetMinSubtreeCount(Symbol symbol, int nSubTrees) {
168      if (!allSymbols.Any(s => s.Name == symbol.Name)) throw new ArgumentException("Unknown symbol: " + symbol);
169      minSubTreeCount[symbol.Name] = nSubTrees;
170      ClearCaches();
171    }
172
173    public int GetMinSubtreeCount(Symbol symbol) {
174      if (!allSymbols.Any(s => s.Name == symbol.Name)) throw new ArgumentException("Unknown symbol: " + symbol);
175      return minSubTreeCount[symbol.Name];
176    }
177
178    public int GetMaxSubtreeCount(Symbol symbol) {
179      if (!allSymbols.Any(s => s.Name == symbol.Name)) throw new ArgumentException("Unknown symbol: " + symbol);
180      return maxSubTreeCount[symbol.Name];
181    }
182
183    #endregion
184
185    private void ClearCaches() {
186      cachedMinExpressionLength.Clear();
187      cachedMaxExpressionLength.Clear();
188      cachedMinExpressionDepth.Clear();
189    }
190
191    //private void symbol_ToStringChanged(object sender, EventArgs e) {
192    //  OnToStringChanged();
193    //}
194
195    //private bool IsValidExpression(SymbolicExpressionTreeNode root) {
196    //  if (root.SubTrees.Count < root.GetMinSubtreeCount()) return false;
197    //  else if (root.SubTrees.Count > root.GetMaxSubtreeCount()) return false;
198    //  else for (int i = 0; i < root.SubTrees.Count; i++) {
199    //      if (!root.GetAllowedSymbols(i).Select(x => x.Name).Contains(root.SubTrees[i].Symbol.Name)) return false;
200    //      if (!IsValidExpression(root.SubTrees[i])) return false;
201    //    }
202    //  return true;
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>>>(allowedChildSymbols);
211      clone.allSymbols = new HashSet<Symbol>(allSymbols);
212      return clone;
213    }
214  }
215}
Note: See TracBrowser for help on using the repository browser.