Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2947_ConfigurableIndexedDataTable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/Grammars/SymbolicExpressionGrammar.cs @ 16189

Last change on this file since 16189 was 15583, checked in by swagner, 7 years ago

#2640: Updated year of copyrights in license headers

File size: 13.3 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2018 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.Collections;
26using HeuristicLab.Common;
27using HeuristicLab.Core;
28using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
29
30namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding {
31  [StorableClass]
32  public abstract class SymbolicExpressionGrammar : SymbolicExpressionGrammarBase, ISymbolicExpressionGrammar {
33    #region fields & properties
34    [Storable(DefaultValue = false)]
35    private bool readOnly;
36    public bool ReadOnly {
37      get { return readOnly; }
38      set {
39        if (readOnly != value) {
40          readOnly = value;
41          OnReadOnlyChanged();
42        }
43      }
44    }
45
46    [Storable]
47    private int minimumFunctionDefinitions;
48    public int MinimumFunctionDefinitions {
49      get { return minimumFunctionDefinitions; }
50      set {
51        minimumFunctionDefinitions = value;
52        UpdateAdfConstraints();
53      }
54    }
55    [Storable]
56    private int maximumFunctionDefinitions;
57    public int MaximumFunctionDefinitions {
58      get { return maximumFunctionDefinitions; }
59      set {
60        maximumFunctionDefinitions = value;
61        UpdateAdfConstraints();
62      }
63    }
64    [Storable]
65    private int minimumFunctionArguments;
66    public int MinimumFunctionArguments {
67      get { return minimumFunctionArguments; }
68      set { minimumFunctionArguments = value; }
69    }
70    [Storable]
71    private int maximumFunctionArguments;
72    public int MaximumFunctionArguments {
73      get { return maximumFunctionArguments; }
74      set { maximumFunctionArguments = value; }
75    }
76
77    private ProgramRootSymbol programRootSymbol;
78    public ProgramRootSymbol ProgramRootSymbol {
79      get { return programRootSymbol; }
80    }
81    ISymbol ISymbolicExpressionGrammar.ProgramRootSymbol {
82      get { return ProgramRootSymbol; }
83    }
84    [Storable(Name = "ProgramRootSymbol")]
85    private ISymbol StorableProgramRootSymbol {
86      get { return programRootSymbol; }
87      set { programRootSymbol = (ProgramRootSymbol)value; }
88    }
89
90    private StartSymbol startSymbol;
91    public StartSymbol StartSymbol {
92      get { return startSymbol; }
93    }
94    ISymbol ISymbolicExpressionGrammar.StartSymbol {
95      get { return StartSymbol; }
96    }
97    [Storable(Name = "StartSymbol")]
98    private ISymbol StorableStartSymbol {
99      get { return startSymbol; }
100      set { startSymbol = (StartSymbol)value; }
101    }
102
103    private Defun defunSymbol;
104    protected Defun DefunSymbol {
105      get { return defunSymbol; }
106    }
107    [Storable(Name = "DefunSymbol")]
108    private ISymbol StorableDefunSymbol {
109      get { return defunSymbol; }
110      set { defunSymbol = (Defun)value; }
111    }
112
113    private readonly ISymbolicExpressionTreeGrammar emptyGrammar;
114    #endregion
115
116    [StorableHook(HookType.AfterDeserialization)]
117    private void AfterDeserialization() {
118      foreach (ISymbol symbol in symbols.Values)
119        RegisterSymbolEvents(symbol);
120    }
121
122    [StorableConstructor]
123    protected SymbolicExpressionGrammar(bool deserializing)
124      : base(deserializing) {
125      emptyGrammar = new EmptySymbolicExpressionTreeGrammar(this);
126    }
127    protected SymbolicExpressionGrammar(SymbolicExpressionGrammar original, Cloner cloner)
128      : base(original, cloner) {
129      emptyGrammar = new EmptySymbolicExpressionTreeGrammar(this);
130
131      foreach (ISymbol symbol in symbols.Values)
132        RegisterSymbolEvents(symbol);
133
134      programRootSymbol = cloner.Clone(original.programRootSymbol);
135      startSymbol = cloner.Clone(original.StartSymbol);
136      defunSymbol = cloner.Clone(original.defunSymbol);
137
138      maximumFunctionArguments = original.maximumFunctionArguments;
139      minimumFunctionArguments = original.minimumFunctionArguments;
140      maximumFunctionDefinitions = original.maximumFunctionDefinitions;
141      minimumFunctionDefinitions = original.minimumFunctionDefinitions;
142    }
143
144    protected SymbolicExpressionGrammar(string name, string description)
145      : base(name, description) {
146      emptyGrammar = new EmptySymbolicExpressionTreeGrammar(this);
147
148      programRootSymbol = new ProgramRootSymbol();
149      AddSymbol(programRootSymbol);
150      SetSubtreeCount(programRootSymbol, 1, 1);
151
152      startSymbol = new StartSymbol();
153      AddSymbol(startSymbol);
154      SetSubtreeCount(startSymbol, 1, 1);
155
156      defunSymbol = new Defun();
157      AddSymbol(defunSymbol);
158      SetSubtreeCount(defunSymbol, 1, 1);
159
160      AddAllowedChildSymbol(programRootSymbol, startSymbol, 0);
161      UpdateAdfConstraints();
162    }
163
164    private void UpdateAdfConstraints() {
165      SetSubtreeCount(programRootSymbol, minimumFunctionDefinitions + 1, maximumFunctionDefinitions + 1);
166
167      // ADF branches maxFunctionDefinitions
168      for (int argumentIndex = 1; argumentIndex < maximumFunctionDefinitions + 1; argumentIndex++) {
169        RemoveAllowedChildSymbol(programRootSymbol, defunSymbol, argumentIndex);
170        AddAllowedChildSymbol(programRootSymbol, defunSymbol, argumentIndex);
171      }
172    }
173
174    public ISymbolicExpressionTreeGrammar CreateExpressionTreeGrammar() {
175      if (MaximumFunctionDefinitions == 0) return emptyGrammar;
176      else return new SymbolicExpressionTreeGrammar(this);
177    }
178
179    public override sealed void AddSymbol(ISymbol symbol) {
180      if (ReadOnly) throw new InvalidOperationException();
181      base.AddSymbol(symbol);
182      RegisterSymbolEvents(symbol);
183      OnChanged();
184    }
185    public override sealed void RemoveSymbol(ISymbol symbol) {
186      if (ReadOnly) throw new InvalidOperationException();
187      DeregisterSymbolEvents(symbol);
188      base.RemoveSymbol(symbol);
189      OnChanged();
190    }
191
192    public event EventHandler ReadOnlyChanged;
193    protected virtual void OnReadOnlyChanged() {
194      var handler = ReadOnlyChanged;
195      if (handler != null)
196        handler(this, EventArgs.Empty);
197    }
198
199    #region IStatefulItem methods
200    void IStatefulItem.InitializeState() {
201      ReadOnly = false;
202    }
203    void IStatefulItem.ClearState() {
204      ReadOnly = false;
205    }
206    #endregion
207
208    public sealed override void AddAllowedChildSymbol(ISymbol parent, ISymbol child) {
209      if (ReadOnly) throw new InvalidOperationException();
210      base.AddAllowedChildSymbol(parent, child);
211    }
212    public sealed override void AddAllowedChildSymbol(ISymbol parent, ISymbol child, int argumentIndex) {
213      if (ReadOnly) throw new InvalidOperationException();
214      base.AddAllowedChildSymbol(parent, child, argumentIndex);
215    }
216    public sealed override void RemoveAllowedChildSymbol(ISymbol parent, ISymbol child) {
217      if (ReadOnly) throw new InvalidOperationException();
218      base.RemoveAllowedChildSymbol(parent, child);
219    }
220    public sealed override void RemoveAllowedChildSymbol(ISymbol parent, ISymbol child, int argumentIndex) {
221      if (ReadOnly) throw new InvalidOperationException();
222      base.RemoveAllowedChildSymbol(parent, child, argumentIndex);
223    }
224
225    public sealed override void SetSubtreeCount(ISymbol symbol, int minimumSubtreeCount, int maximumSubtreeCount) {
226      if (ReadOnly) throw new InvalidOperationException();
227      base.SetSubtreeCount(symbol, minimumSubtreeCount, maximumSubtreeCount);
228    }
229
230    private bool suppressEvents = false;
231    public void StartGrammarManipulation() {
232      suppressEvents = true;
233    }
234    public void FinishedGrammarManipulation() {
235      suppressEvents = false;
236      OnChanged();
237    }
238
239    protected sealed override void OnChanged() {
240      if (suppressEvents) return;
241      base.OnChanged();
242    }
243
244    #region symbol events
245    private void RegisterSymbolEvents(ISymbol symbol) {
246      foreach (var s in symbol.Flatten()) {
247        s.NameChanging += new EventHandler<CancelEventArgs<string>>(Symbol_NameChanging);
248        s.NameChanged += new EventHandler(Symbol_NameChanged);
249
250        var groupSymbol = s as GroupSymbol;
251        if (groupSymbol != null) RegisterGroupSymbolEvents(groupSymbol);
252        else s.Changed += new EventHandler(Symbol_Changed);
253      }
254    }
255    private void DeregisterSymbolEvents(ISymbol symbol) {
256      foreach (var s in symbol.Flatten()) {
257        s.NameChanging -= new EventHandler<CancelEventArgs<string>>(Symbol_NameChanging);
258        s.NameChanged -= new EventHandler(Symbol_NameChanged);
259
260        var groupSymbol = s as GroupSymbol;
261        if (groupSymbol != null) DeregisterGroupSymbolEvents(groupSymbol);
262        else s.Changed -= new EventHandler(Symbol_Changed);
263      }
264    }
265
266    private void RegisterGroupSymbolEvents(GroupSymbol groupSymbol) {
267      groupSymbol.Changed += new EventHandler(GroupSymbol_Changed);
268      groupSymbol.SymbolsCollection.ItemsAdded += new Collections.CollectionItemsChangedEventHandler<ISymbol>(GroupSymbol_ItemsAdded);
269      groupSymbol.SymbolsCollection.ItemsRemoved += new Collections.CollectionItemsChangedEventHandler<ISymbol>(GroupSymbol_ItemsRemoved);
270      groupSymbol.SymbolsCollection.CollectionReset += new Collections.CollectionItemsChangedEventHandler<ISymbol>(GroupSymbol_CollectionReset);
271    }
272    private void DeregisterGroupSymbolEvents(GroupSymbol groupSymbol) {
273      groupSymbol.Changed -= new EventHandler(GroupSymbol_Changed);
274      groupSymbol.SymbolsCollection.ItemsAdded -= new Collections.CollectionItemsChangedEventHandler<ISymbol>(GroupSymbol_ItemsAdded);
275      groupSymbol.SymbolsCollection.ItemsRemoved -= new Collections.CollectionItemsChangedEventHandler<ISymbol>(GroupSymbol_ItemsRemoved);
276      groupSymbol.SymbolsCollection.CollectionReset -= new Collections.CollectionItemsChangedEventHandler<ISymbol>(GroupSymbol_CollectionReset);
277    }
278
279    private void Symbol_Changed(object sender, EventArgs e) {
280      ClearCaches();
281      OnChanged();
282    }
283
284    private void GroupSymbol_Changed(object sender, EventArgs e) {
285      GroupSymbol groupSymbol = (GroupSymbol)sender;
286      foreach (ISymbol symbol in groupSymbol.Flatten())
287        symbol.Enabled = groupSymbol.Enabled;
288
289      ClearCaches();
290      OnChanged();
291    }
292
293    private void Symbol_NameChanging(object sender, CancelEventArgs<string> e) {
294      if (symbols.ContainsKey(e.Value)) e.Cancel = true;
295    }
296    private void Symbol_NameChanged(object sender, EventArgs e) {
297      ISymbol symbol = (ISymbol)sender;
298      string oldName = symbols.First(x => x.Value == symbol).Key;
299      string newName = symbol.Name;
300
301      symbols.Remove(oldName);
302      symbols.Add(newName, symbol);
303
304      var subtreeCount = symbolSubtreeCount[oldName];
305      symbolSubtreeCount.Remove(oldName);
306      symbolSubtreeCount.Add(newName, subtreeCount);
307
308      List<string> allowedChilds;
309      if (allowedChildSymbols.TryGetValue(oldName, out allowedChilds)) {
310        allowedChildSymbols.Remove(oldName);
311        allowedChildSymbols.Add(newName, allowedChilds);
312      }
313
314      for (int i = 0; i < GetMaximumSubtreeCount(symbol); i++) {
315        if (allowedChildSymbolsPerIndex.TryGetValue(Tuple.Create(oldName, i), out allowedChilds)) {
316          allowedChildSymbolsPerIndex.Remove(Tuple.Create(oldName, i));
317          allowedChildSymbolsPerIndex.Add(Tuple.Create(newName, i), allowedChilds);
318        }
319      }
320
321      foreach (var parent in Symbols) {
322        if (allowedChildSymbols.TryGetValue(parent.Name, out allowedChilds))
323          if (allowedChilds.Remove(oldName))
324            allowedChilds.Add(newName);
325
326        for (int i = 0; i < GetMaximumSubtreeCount(parent); i++) {
327          if (allowedChildSymbolsPerIndex.TryGetValue(Tuple.Create(parent.Name, i), out allowedChilds))
328            if (allowedChilds.Remove(oldName)) allowedChilds.Add(newName);
329        }
330      }
331
332      ClearCaches();
333      OnChanged();
334    }
335
336    private void GroupSymbol_ItemsAdded(object sender, CollectionItemsChangedEventArgs<ISymbol> e) {
337      foreach (ISymbol symbol in e.Items)
338        if (!ContainsSymbol(symbol))
339          AddSymbol(symbol);
340      OnChanged();
341    }
342    private void GroupSymbol_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<ISymbol> e) {
343      foreach (ISymbol symbol in e.Items)
344        if (ContainsSymbol(symbol))
345          RemoveSymbol(symbol);
346      OnChanged();
347    }
348    private void GroupSymbol_CollectionReset(object sender, CollectionItemsChangedEventArgs<ISymbol> e) {
349      foreach (ISymbol symbol in e.Items)
350        if (!ContainsSymbol(symbol))
351          AddSymbol(symbol);
352      foreach (ISymbol symbol in e.OldItems)
353        if (ContainsSymbol(symbol))
354          RemoveSymbol(symbol);
355      OnChanged();
356    }
357    #endregion
358  }
359}
Note: See TracBrowser for help on using the repository browser.