Free cookie consent management tool by TermsFeed Policy Generator

source: branches/GP.Grammar.Editor/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/SymbolicExpressionGrammarBase.cs @ 6296

Last change on this file since 6296 was 6296, checked in by mkommend, 13 years ago

#1479: Updated grammars and added GroupSymbol.

File size: 18.8 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2011 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 HeuristicLab.Common;
26using HeuristicLab.Core;
27using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
28
29namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding {
30  /// <summary>
31  /// The default symbolic expression grammar stores symbols and syntactic constraints for symbols.
32  /// Symbols are treated as equvivalent if they have the same name.
33  /// Syntactic constraints limit the number of allowed sub trees for a node with a symbol and which symbols are allowed
34  /// in the sub-trees of a symbol (can be specified for each sub-tree index separately).
35  /// </summary>
36  [StorableClass]
37  public abstract class SymbolicExpressionGrammarBase : NamedItem, ISymbolicExpressionGrammarBase {
38
39    #region properties for separation between implementation and persistence
40    [Storable(Name = "Symbols")]
41    private IEnumerable<ISymbol> StorableSymbols {
42      get { return symbols.Values.ToArray(); }
43      set { symbols = value.ToDictionary(sym => sym.Name); }
44    }
45
46    [Storable(Name = "SymbolSubtreeCount")]
47    private IEnumerable<KeyValuePair<ISymbol, Tuple<int, int>>> StorableSymbolSubtreeCount {
48      get { return symbolSubtreeCount.Select(x => new KeyValuePair<ISymbol, Tuple<int, int>>(GetSymbol(x.Key), x.Value)).ToArray(); }
49      set { symbolSubtreeCount = value.ToDictionary(x => x.Key.Name, x => x.Value); }
50    }
51
52    [Storable(Name = "AllowedChildSymbols")]
53    private IEnumerable<KeyValuePair<ISymbol, IEnumerable<ISymbol>>> StorableAllowedChildSymbols {
54      get { return allowedChildSymbols.Select(x => new KeyValuePair<ISymbol, IEnumerable<ISymbol>>(GetSymbol(x.Key), x.Value.Select(y => GetSymbol(y)).ToArray())).ToArray(); }
55      set { allowedChildSymbols = value.ToDictionary(x => x.Key.Name, x => x.Value.Select(y => y.Name).ToList()); }
56    }
57
58    [Storable(Name = "AllowedChildSymbolsPerIndex")]
59    private IEnumerable<KeyValuePair<Tuple<ISymbol, int>, IEnumerable<ISymbol>>> StorableAllowedChildSymbolsPerIndex {
60      get { return allowedChildSymbolsPerIndex.Select(x => new KeyValuePair<Tuple<ISymbol, int>, IEnumerable<ISymbol>>(Tuple.Create<ISymbol, int>(GetSymbol(x.Key.Item1), x.Key.Item2), x.Value.Select(y => GetSymbol(y)).ToArray())).ToArray(); }
61      set { allowedChildSymbolsPerIndex = value.ToDictionary(x => Tuple.Create(x.Key.Item1.Name, x.Key.Item2), x => x.Value.Select(y => y.Name).ToList()); }
62    }
63    #endregion
64
65    protected bool suppressEvents;
66    protected Dictionary<string, ISymbol> symbols;
67    protected Dictionary<string, Tuple<int, int>> symbolSubtreeCount;
68    protected Dictionary<string, List<string>> allowedChildSymbols;
69    protected Dictionary<Tuple<string, int>, List<string>> allowedChildSymbolsPerIndex;
70
71    public override bool CanChangeName {
72      get { return false; }
73    }
74    public override bool CanChangeDescription {
75      get { return false; }
76    }
77
78    [StorableConstructor]
79    protected SymbolicExpressionGrammarBase(bool deserializing)
80      : base(deserializing) {
81      cachedMinExpressionLength = new Dictionary<string, int>();
82      cachedMaxExpressionLength = new Dictionary<string, int>();
83      cachedMinExpressionDepth = new Dictionary<string, int>();
84
85      suppressEvents = false;
86    }
87    [StorableHook(HookType.AfterDeserialization)]
88    private void AfterDeserialization() {
89      foreach (ISymbol symbol in symbols.Values)
90        RegisterSymbolEvents(symbol);
91    }
92
93    protected SymbolicExpressionGrammarBase(SymbolicExpressionGrammarBase original, Cloner cloner)
94      : base(original, cloner) {
95      cachedMinExpressionLength = new Dictionary<string, int>();
96      cachedMaxExpressionLength = new Dictionary<string, int>();
97      cachedMinExpressionDepth = new Dictionary<string, int>();
98
99      symbols = original.symbols.ToDictionary(x => x.Key, y => (ISymbol)cloner.Clone(y.Value));
100      symbolSubtreeCount = new Dictionary<string, Tuple<int, int>>(original.symbolSubtreeCount);
101
102      allowedChildSymbols = new Dictionary<string, List<string>>();
103      foreach (var element in original.allowedChildSymbols)
104        allowedChildSymbols.Add(element.Key, new List<string>(element.Value));
105
106      allowedChildSymbolsPerIndex = new Dictionary<Tuple<string, int>, List<string>>();
107      foreach (var element in original.allowedChildSymbolsPerIndex)
108        allowedChildSymbolsPerIndex.Add(element.Key, new List<string>(element.Value));
109
110      foreach (ISymbol symbol in symbols.Values)
111        RegisterSymbolEvents(symbol);
112
113      suppressEvents = false;
114    }
115
116    protected SymbolicExpressionGrammarBase(string name, string description)
117      : base(name, description) {
118      cachedMinExpressionLength = new Dictionary<string, int>();
119      cachedMaxExpressionLength = new Dictionary<string, int>();
120      cachedMinExpressionDepth = new Dictionary<string, int>();
121
122      symbols = new Dictionary<string, ISymbol>();
123      symbolSubtreeCount = new Dictionary<string, Tuple<int, int>>();
124      allowedChildSymbols = new Dictionary<string, List<string>>();
125      allowedChildSymbolsPerIndex = new Dictionary<Tuple<string, int>, List<string>>();
126
127      suppressEvents = false;
128    }
129
130    #region protected grammar manipulation methods
131    protected void AddSymbol(ISymbol symbol) {
132      symbols.Add(symbol.Name, symbol);
133      symbolSubtreeCount.Add(symbol.Name, Tuple.Create(0, 0));
134      RegisterSymbolEvents(symbol);
135
136      var groupSymbol = symbol as GroupSymbol;
137      if (groupSymbol != null) AddSymbol(groupSymbol);
138
139      ClearCaches();
140      OnChanged();
141    }
142
143    private void AddSymbol(GroupSymbol groupSymbol) {
144      foreach (ISymbol symbol in groupSymbol.Symbols) {
145        symbols.Add(symbol.Name, symbol);
146        symbolSubtreeCount.Add(symbol.Name, Tuple.Create(0, 0));
147        RegisterSymbolEvents(symbol);
148
149        var childGroup = symbol as GroupSymbol;
150        if (childGroup != null) AddSymbol(childGroup);
151      }
152    }
153
154    protected void RemoveSymbol(ISymbol symbol) {
155      symbols.Remove(symbol.Name);
156      allowedChildSymbols.Remove(symbol.Name);
157      for (int i = 0; i < GetMaximumSubtreeCount(symbol); i++)
158        allowedChildSymbolsPerIndex.Remove(Tuple.Create(symbol.Name, i));
159      symbolSubtreeCount.Remove(symbol.Name);
160
161      foreach (var parent in Symbols) {
162        List<string> allowedChilds;
163        if (allowedChildSymbols.TryGetValue(parent.Name, out allowedChilds))
164          allowedChilds.Remove(symbol.Name);
165
166        for (int i = 0; i < GetMaximumSubtreeCount(parent); i++) {
167          if (allowedChildSymbolsPerIndex.TryGetValue(Tuple.Create(parent.Name, i), out allowedChilds))
168            allowedChilds.Remove(symbol.Name);
169        }
170      }
171      DeregisterSymbolEvents(symbol);
172      ClearCaches();
173      OnChanged();
174    }
175
176    public virtual ISymbol GetSymbol(string symbolName) {
177      ISymbol symbol;
178      if (symbols.TryGetValue(symbolName, out symbol)) return symbol;
179      return null;
180    }
181
182    protected void AddAllowedChildSymbol(ISymbol parent, ISymbol child) {
183      suppressEvents = true;
184      for (int argumentIndex = 0; argumentIndex < GetMaximumSubtreeCount(parent); argumentIndex++)
185        RemoveAllowedChildSymbol(parent, child, argumentIndex);
186      suppressEvents = false;
187
188      List<string> childSymbols;
189      if (!allowedChildSymbols.TryGetValue(parent.Name, out childSymbols)) {
190        childSymbols = new List<string>();
191        allowedChildSymbols.Add(parent.Name, childSymbols);
192      }
193
194      if (!childSymbols.Contains(child.Name)) {
195        childSymbols.Add(child.Name);
196        ClearCaches();
197        OnChanged();
198      }
199    }
200
201    protected void AddAllowedChildSymbol(ISymbol parent, ISymbol child, int argumentIndex) {
202      List<string> childSymbols;
203      if (allowedChildSymbols.TryGetValue(parent.Name, out childSymbols))
204        if (childSymbols.Contains(child.Name)) return;
205
206      var key = Tuple.Create(parent.Name, argumentIndex);
207      if (!allowedChildSymbolsPerIndex.TryGetValue(key, out childSymbols)) {
208        childSymbols = new List<string>();
209        allowedChildSymbolsPerIndex.Add(key, childSymbols);
210      }
211
212      if (!childSymbols.Contains(child.Name)) {
213        childSymbols.Add(child.Name);
214        ClearCaches();
215        OnChanged();
216      }
217    }
218
219    protected void RemoveAllowedChildSymbol(ISymbol parent, ISymbol child) {
220      bool changed = false;
221      List<string> childSymbols;
222      if (allowedChildSymbols.TryGetValue(child.Name, out childSymbols)) {
223        if (allowedChildSymbols[parent.Name].Remove(child.Name)) changed = true;
224      }
225
226      for (int argumentIndex = 0; argumentIndex < GetMaximumSubtreeCount(parent); argumentIndex++) {
227        var key = Tuple.Create(parent.Name, argumentIndex);
228        if (allowedChildSymbolsPerIndex.TryGetValue(key, out childSymbols)) {
229          if (allowedChildSymbolsPerIndex[key].Remove(child.Name)) changed = true;
230        }
231      }
232
233      if (changed) {
234        ClearCaches();
235        OnChanged();
236      }
237    }
238
239    protected void RemoveAllowedChildSymbol(ISymbol parent, ISymbol child, int argumentIndex) {
240      bool changed = false;
241
242      List<string> childSymbols;
243      if (allowedChildSymbols.TryGetValue(parent.Name, out childSymbols)) {
244        if (childSymbols.Remove(child.Name)) {
245          suppressEvents = true;
246          for (int i = 0; i < GetMaximumSubtreeCount(parent); i++) {
247            if (i != argumentIndex) AddAllowedChildSymbol(parent, child, i);
248          }
249          suppressEvents = false;
250          changed = true;
251        }
252      }
253
254      var key = Tuple.Create(parent.Name, argumentIndex);
255      if (allowedChildSymbolsPerIndex.TryGetValue(key, out childSymbols)) {
256        if (allowedChildSymbolsPerIndex[key].Remove(child.Name))
257          changed = true;
258      }
259
260      if (changed) {
261        ClearCaches();
262        OnChanged();
263      }
264    }
265
266    protected void SetSubtreeCount(ISymbol symbol, int minimumSubtreeCount, int maximumSubtreeCount) {
267      for (int i = GetMaximumSubtreeCount(symbol) - 1; i >= maximumSubtreeCount; i--) {
268        var key = Tuple.Create(symbol.Name, i);
269        allowedChildSymbolsPerIndex.Remove(key);
270      }
271
272      symbolSubtreeCount[symbol.Name] = Tuple.Create(minimumSubtreeCount, maximumSubtreeCount);
273      ClearCaches();
274      OnChanged();
275    }
276    #endregion
277
278    public virtual IEnumerable<ISymbol> Symbols {
279      get { return symbols.Values; }
280    }
281    public virtual IEnumerable<ISymbol> AllowedSymbols {
282      get { return Symbols.Where(s => s.Enabled); }
283    }
284    public virtual bool ContainsSymbol(ISymbol symbol) {
285      return symbols.ContainsKey(symbol.Name);
286    }
287
288    public virtual bool IsAllowedChildSymbol(ISymbol parent, ISymbol child) {
289      if (!child.Enabled) return false;
290
291      List<string> temp;
292      if (allowedChildSymbols.TryGetValue(parent.Name, out temp))
293        if (temp.Contains(child.Name)) return true;
294      return false;
295    }
296
297    public virtual bool IsAllowedChildSymbol(ISymbol parent, ISymbol child, int argumentIndex) {
298      if (!child.Enabled) return false;
299
300      List<string> temp;
301      if (allowedChildSymbols.TryGetValue(parent.Name, out temp))
302        if (temp.Contains(child.Name)) return true;
303
304      var key = Tuple.Create(parent.Name, argumentIndex);
305      if (allowedChildSymbolsPerIndex.TryGetValue(key, out temp))
306        return temp.Contains(child.Name);
307      return false;
308    }
309
310    public virtual IEnumerable<ISymbol> GetAllowedChildSymbols(ISymbol parent) {
311      List<string> childs;
312      if (allowedChildSymbols.TryGetValue(parent.Name, out childs))
313        return childs.Select(s => GetSymbol(s)).Where(s => s.Enabled);
314      return Enumerable.Empty<ISymbol>();
315    }
316
317    public virtual IEnumerable<ISymbol> GetAllowedChildSymbols(ISymbol parent, int argumentIndex) {
318      var result = Enumerable.Empty<string>();
319
320      List<string> temp;
321      if (allowedChildSymbols.TryGetValue(parent.Name, out temp))
322        result = result.Union(temp);
323      var key = Tuple.Create(parent.Name, argumentIndex);
324      if (allowedChildSymbolsPerIndex.TryGetValue(key, out temp))
325        result = result.Union(temp);
326
327      return result.Select(x => GetSymbol(x)).Where(s => s.Enabled);
328    }
329
330    public virtual int GetMinimumSubtreeCount(ISymbol symbol) {
331      return symbolSubtreeCount[symbol.Name].Item1;
332    }
333    public virtual int GetMaximumSubtreeCount(ISymbol symbol) {
334      return symbolSubtreeCount[symbol.Name].Item2;
335    }
336
337    private void ClearCaches() {
338      cachedMinExpressionLength.Clear();
339      cachedMaxExpressionLength.Clear();
340      cachedMinExpressionDepth.Clear();
341    }
342
343    private Dictionary<string, int> cachedMinExpressionLength;
344    public int GetMinimumExpressionLength(ISymbol symbol) {
345      int temp;
346      if (!cachedMinExpressionLength.TryGetValue(symbol.Name, out temp)) {
347        cachedMinExpressionLength[symbol.Name] = int.MaxValue; // prevent infinite recursion
348        long sumOfMinExpressionLengths = 1 + (from argIndex in Enumerable.Range(0, GetMinimumSubtreeCount(symbol))
349                                              let minForSlot = (long)(from s in GetAllowedChildSymbols(symbol, argIndex)
350                                                                      select GetMinimumExpressionLength(s)).DefaultIfEmpty(0).Min()
351                                              select minForSlot).DefaultIfEmpty(0).Sum();
352
353        cachedMinExpressionLength[symbol.Name] = (int)Math.Min(sumOfMinExpressionLengths, int.MaxValue);
354        return cachedMinExpressionLength[symbol.Name];
355      }
356      return temp;
357    }
358
359    private Dictionary<string, int> cachedMaxExpressionLength;
360    public int GetMaximumExpressionLength(ISymbol symbol) {
361      int temp;
362      if (!cachedMaxExpressionLength.TryGetValue(symbol.Name, out temp)) {
363        cachedMaxExpressionLength[symbol.Name] = int.MaxValue; // prevent infinite recursion
364        long sumOfMaxTrees = 1 + (from argIndex in Enumerable.Range(0, GetMaximumSubtreeCount(symbol))
365                                  let maxForSlot = (long)(from s in GetAllowedChildSymbols(symbol, argIndex)
366                                                          select GetMaximumExpressionLength(s)).DefaultIfEmpty(0).Max()
367                                  select maxForSlot).DefaultIfEmpty(0).Sum();
368        cachedMaxExpressionLength[symbol.Name] = (int)Math.Min(sumOfMaxTrees, int.MaxValue);
369        return cachedMaxExpressionLength[symbol.Name];
370      }
371      return temp;
372    }
373
374    private Dictionary<string, int> cachedMinExpressionDepth;
375    public int GetMinimumExpressionDepth(ISymbol symbol) {
376      int temp;
377      if (!cachedMinExpressionDepth.TryGetValue(symbol.Name, out temp)) {
378        cachedMinExpressionDepth[symbol.Name] = int.MaxValue; // prevent infinite recursion
379        long minDepth = 1 + (from argIndex in Enumerable.Range(0, GetMinimumSubtreeCount(symbol))
380                             let minForSlot = (long)(from s in GetAllowedChildSymbols(symbol, argIndex)
381                                                     select GetMinimumExpressionDepth(s)).DefaultIfEmpty(0).Min()
382                             select minForSlot).DefaultIfEmpty(0).Max();
383        cachedMinExpressionDepth[symbol.Name] = (int)Math.Min(minDepth, int.MaxValue);
384        return cachedMinExpressionDepth[symbol.Name];
385      }
386      return temp;
387    }
388
389
390    #region events
391    private void RegisterSymbolEvents(ISymbol symbol) {
392      symbol.NameChanging += new EventHandler<CancelEventArgs<string>>(Symbol_NameChanging);
393      symbol.NameChanged += new EventHandler(Symbol_NameChanged);
394      symbol.Changed += new EventHandler(Symbol_Changed);
395    }
396    private void DeregisterSymbolEvents(ISymbol symbol) {
397      symbol.NameChanging -= new EventHandler<CancelEventArgs<string>>(Symbol_NameChanging);
398      symbol.NameChanged -= new EventHandler(Symbol_NameChanged);
399      symbol.Changed -= new EventHandler(Symbol_Changed);
400    }
401
402    private void Symbol_NameChanging(object sender, CancelEventArgs<string> e) {
403      if (symbols.ContainsKey(e.Value)) e.Cancel = true;
404    }
405    private void Symbol_NameChanged(object sender, EventArgs e) {
406      ISymbol symbol = (ISymbol)sender;
407      string oldName = symbols.Where(x => x.Value == symbol).First().Key;
408      string newName = symbol.Name;
409
410      symbols.Remove(oldName);
411      symbols.Add(newName, symbol);
412
413      var subtreeCount = symbolSubtreeCount[oldName];
414      symbolSubtreeCount.Remove(oldName);
415      symbolSubtreeCount.Add(newName, subtreeCount);
416
417      List<string> allowedChilds;
418      if (allowedChildSymbols.TryGetValue(oldName, out allowedChilds)) {
419        allowedChildSymbols.Remove(oldName);
420        allowedChildSymbols.Add(newName, allowedChilds);
421      }
422
423      for (int i = 0; i < GetMaximumSubtreeCount(symbol); i++) {
424        if (allowedChildSymbolsPerIndex.TryGetValue(Tuple.Create(oldName, i), out allowedChilds)) {
425          allowedChildSymbolsPerIndex.Remove(Tuple.Create(oldName, i));
426          allowedChildSymbolsPerIndex.Add(Tuple.Create(newName, i), allowedChilds);
427        }
428      }
429
430      foreach (var parent in Symbols) {
431        if (allowedChildSymbols.TryGetValue(parent.Name, out allowedChilds))
432          if (allowedChilds.Remove(oldName))
433            allowedChilds.Add(newName);
434
435        for (int i = 0; i < GetMaximumSubtreeCount(parent); i++) {
436          if (allowedChildSymbolsPerIndex.TryGetValue(Tuple.Create(parent.Name, i), out allowedChilds))
437            if (allowedChilds.Remove(oldName)) allowedChilds.Add(newName);
438        }
439      }
440
441      ClearCaches();
442      OnChanged();
443    }
444
445    private void Symbol_Changed(object sende, EventArgs e) {
446      ClearCaches();
447      OnChanged();
448    }
449
450    public event EventHandler Changed;
451    protected virtual void OnChanged() {
452      if (suppressEvents) return;
453      var handler = Changed;
454      if (handler != null) Changed(this, EventArgs.Empty);
455    }
456    #endregion
457  }
458}
Note: See TracBrowser for help on using the repository browser.