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
RevLine 
[3294]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]
[3338]40    private Dictionary<string, List<HashSet<string>>> allowedChildSymbols;
[3294]41    [Storable]
42    private HashSet<Symbol> allSymbols;
43
[3338]44    public DefaultSymbolicExpressionGrammar()
[3294]45      : base() {
[3338]46      Reset();
[3294]47    }
48
49    private void Initialize() {
50      startSymbol = new StartSymbol();
[3338]51      AddSymbol(startSymbol);
52      SetMinSubtreeCount(startSymbol, 1);
53      SetMaxSubtreeCount(startSymbol, 1);
54    }
[3294]55
[3338]56    #region ISymbolicExpressionGrammar Members
57
58    private Symbol startSymbol;
59    public Symbol StartSymbol {
60      get { return startSymbol; }
61      set { startSymbol = value; }
[3294]62    }
63
[3338]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();
[3294]73    }
74
[3338]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>>();
[3294]79      ClearCaches();
80    }
81
[3338]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);
[3294]87      ClearCaches();
88    }
89
[3338]90    public IEnumerable<Symbol> Symbols {
91      get { return allSymbols.AsEnumerable(); }
[3294]92    }
93
[3338]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();
[3294]100    }
101
[3338]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;
[3294]108    }
109
[3338]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();
[3294]120
[3338]121        cachedMinExpressionLength[symbol.Name] = (int)Math.Min(sumOfMinExpressionLengths, int.MaxValue);
[3294]122      }
[3338]123      return cachedMinExpressionLength[symbol.Name];
[3294]124    }
125
[3338]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()
[3294]135                                  select maxForSlot).DefaultIfEmpty(0).Sum();
136        long limit = int.MaxValue;
[3338]137        cachedMaxExpressionLength[symbol.Name] = (int)Math.Min(sumOfMaxTrees, limit);
[3294]138      }
[3338]139      return cachedMaxExpressionLength[symbol.Name];
[3294]140    }
141
[3338]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();
[3294]152      }
[3338]153      return cachedMinExpressionDepth[symbol.Name];
[3294]154    }
155
[3338]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();
[3294]165    }
166
[3338]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();
[3294]171    }
172
[3338]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];
[3294]176    }
177
[3338]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];
[3294]181    }
182
[3338]183    #endregion
184
185    private void ClearCaches() {
186      cachedMinExpressionLength.Clear();
187      cachedMaxExpressionLength.Clear();
188      cachedMinExpressionDepth.Clear();
[3294]189    }
190
[3338]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;
[3294]213    }
214  }
215}
Note: See TracBrowser for help on using the repository browser.