#region License Information /* HeuristicLab * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * HeuristicLab is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HeuristicLab. If not, see . */ #endregion using System; using System.Collections.Generic; using System.Linq; using HeuristicLab.Collections; using HeuristicLab.Common; using HeuristicLab.Core; using HEAL.Attic; namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding { [StorableType("925BDEE9-0D46-48DB-BA1B-DCE82C0480B3")] public abstract class SymbolicExpressionGrammar : SymbolicExpressionGrammarBase, ISymbolicExpressionGrammar { #region fields & properties [Storable(DefaultValue = false)] private bool readOnly; public bool ReadOnly { get { return readOnly; } set { if (readOnly != value) { readOnly = value; OnReadOnlyChanged(); } } } [Storable] private int minimumFunctionDefinitions; public int MinimumFunctionDefinitions { get { return minimumFunctionDefinitions; } set { minimumFunctionDefinitions = value; UpdateAdfConstraints(); } } [Storable] private int maximumFunctionDefinitions; public int MaximumFunctionDefinitions { get { return maximumFunctionDefinitions; } set { maximumFunctionDefinitions = value; UpdateAdfConstraints(); } } [Storable] private int minimumFunctionArguments; public int MinimumFunctionArguments { get { return minimumFunctionArguments; } set { minimumFunctionArguments = value; } } [Storable] private int maximumFunctionArguments; public int MaximumFunctionArguments { get { return maximumFunctionArguments; } set { maximumFunctionArguments = value; } } private ProgramRootSymbol programRootSymbol; public ProgramRootSymbol ProgramRootSymbol { get { return programRootSymbol; } } ISymbol ISymbolicExpressionGrammar.ProgramRootSymbol { get { return ProgramRootSymbol; } } [Storable(Name = "ProgramRootSymbol")] private ISymbol StorableProgramRootSymbol { get { return programRootSymbol; } set { programRootSymbol = (ProgramRootSymbol)value; } } private StartSymbol startSymbol; public StartSymbol StartSymbol { get { return startSymbol; } } ISymbol ISymbolicExpressionGrammar.StartSymbol { get { return StartSymbol; } } [Storable(Name = "StartSymbol")] private ISymbol StorableStartSymbol { get { return startSymbol; } set { startSymbol = (StartSymbol)value; } } private Defun defunSymbol; protected Defun DefunSymbol { get { return defunSymbol; } } [Storable(Name = "DefunSymbol")] private ISymbol StorableDefunSymbol { get { return defunSymbol; } set { defunSymbol = (Defun)value; } } private readonly ISymbolicExpressionTreeGrammar emptyGrammar; #endregion [StorableHook(HookType.AfterDeserialization)] private void AfterDeserialization() { foreach (ISymbol symbol in symbols.Values) RegisterSymbolEvents(symbol); } [StorableConstructor] protected SymbolicExpressionGrammar(StorableConstructorFlag _) : base(_) { emptyGrammar = new EmptySymbolicExpressionTreeGrammar(this); } protected SymbolicExpressionGrammar(SymbolicExpressionGrammar original, Cloner cloner) : base(original, cloner) { emptyGrammar = new EmptySymbolicExpressionTreeGrammar(this); foreach (ISymbol symbol in symbols.Values) RegisterSymbolEvents(symbol); programRootSymbol = cloner.Clone(original.programRootSymbol); startSymbol = cloner.Clone(original.StartSymbol); defunSymbol = cloner.Clone(original.defunSymbol); maximumFunctionArguments = original.maximumFunctionArguments; minimumFunctionArguments = original.minimumFunctionArguments; maximumFunctionDefinitions = original.maximumFunctionDefinitions; minimumFunctionDefinitions = original.minimumFunctionDefinitions; } protected SymbolicExpressionGrammar(string name, string description) : base(name, description) { emptyGrammar = new EmptySymbolicExpressionTreeGrammar(this); programRootSymbol = new ProgramRootSymbol(); AddSymbol(programRootSymbol); SetSubtreeCount(programRootSymbol, 1, 1); startSymbol = new StartSymbol(); AddSymbol(startSymbol); SetSubtreeCount(startSymbol, 1, 1); defunSymbol = new Defun(); AddSymbol(defunSymbol); SetSubtreeCount(defunSymbol, 1, 1); AddAllowedChildSymbol(programRootSymbol, startSymbol, 0); UpdateAdfConstraints(); } private void UpdateAdfConstraints() { SetSubtreeCount(programRootSymbol, minimumFunctionDefinitions + 1, maximumFunctionDefinitions + 1); // ADF branches maxFunctionDefinitions for (int argumentIndex = 1; argumentIndex < maximumFunctionDefinitions + 1; argumentIndex++) { RemoveAllowedChildSymbol(programRootSymbol, defunSymbol, argumentIndex); AddAllowedChildSymbol(programRootSymbol, defunSymbol, argumentIndex); } } public ISymbolicExpressionTreeGrammar CreateExpressionTreeGrammar() { if (MaximumFunctionDefinitions == 0) return emptyGrammar; else return new SymbolicExpressionTreeGrammar(this); } public override sealed void AddSymbol(ISymbol symbol) { if (ReadOnly) throw new InvalidOperationException(); base.AddSymbol(symbol); RegisterSymbolEvents(symbol); OnChanged(); } public override sealed void RemoveSymbol(ISymbol symbol) { if (ReadOnly) throw new InvalidOperationException(); DeregisterSymbolEvents(symbol); base.RemoveSymbol(symbol); OnChanged(); } public event EventHandler ReadOnlyChanged; protected virtual void OnReadOnlyChanged() { ReadOnlyChanged?.Invoke(this, EventArgs.Empty); } public sealed override void AddAllowedChildSymbol(ISymbol parent, ISymbol child) { if (ReadOnly) throw new InvalidOperationException(); base.AddAllowedChildSymbol(parent, child); } public sealed override void AddAllowedChildSymbol(ISymbol parent, ISymbol child, int argumentIndex) { if (ReadOnly) throw new InvalidOperationException(); base.AddAllowedChildSymbol(parent, child, argumentIndex); } public sealed override void RemoveAllowedChildSymbol(ISymbol parent, ISymbol child) { if (ReadOnly) throw new InvalidOperationException(); base.RemoveAllowedChildSymbol(parent, child); } public sealed override void RemoveAllowedChildSymbol(ISymbol parent, ISymbol child, int argumentIndex) { if (ReadOnly) throw new InvalidOperationException(); base.RemoveAllowedChildSymbol(parent, child, argumentIndex); } public sealed override void SetSubtreeCount(ISymbol symbol, int minimumSubtreeCount, int maximumSubtreeCount) { if (ReadOnly) throw new InvalidOperationException(); base.SetSubtreeCount(symbol, minimumSubtreeCount, maximumSubtreeCount); } private bool suppressEvents = false; public void StartGrammarManipulation() { suppressEvents = true; } public void FinishedGrammarManipulation() { suppressEvents = false; OnChanged(); } protected sealed override void OnChanged() { if (suppressEvents) return; base.OnChanged(); } #region symbol events private void RegisterSymbolEvents(ISymbol symbol) { foreach (var s in symbol.Flatten()) { s.NameChanging += new EventHandler>(Symbol_NameChanging); s.NameChanged += new EventHandler(Symbol_NameChanged); var groupSymbol = s as GroupSymbol; if (groupSymbol != null) RegisterGroupSymbolEvents(groupSymbol); else s.Changed += new EventHandler(Symbol_Changed); } } private void DeregisterSymbolEvents(ISymbol symbol) { foreach (var s in symbol.Flatten()) { s.NameChanging -= new EventHandler>(Symbol_NameChanging); s.NameChanged -= new EventHandler(Symbol_NameChanged); var groupSymbol = s as GroupSymbol; if (groupSymbol != null) DeregisterGroupSymbolEvents(groupSymbol); else s.Changed -= new EventHandler(Symbol_Changed); } } private void RegisterGroupSymbolEvents(GroupSymbol groupSymbol) { groupSymbol.Changed += new EventHandler(GroupSymbol_Changed); groupSymbol.SymbolsCollection.ItemsAdded += new Collections.CollectionItemsChangedEventHandler(GroupSymbol_ItemsAdded); groupSymbol.SymbolsCollection.ItemsRemoved += new Collections.CollectionItemsChangedEventHandler(GroupSymbol_ItemsRemoved); groupSymbol.SymbolsCollection.CollectionReset += new Collections.CollectionItemsChangedEventHandler(GroupSymbol_CollectionReset); } private void DeregisterGroupSymbolEvents(GroupSymbol groupSymbol) { groupSymbol.Changed -= new EventHandler(GroupSymbol_Changed); groupSymbol.SymbolsCollection.ItemsAdded -= new Collections.CollectionItemsChangedEventHandler(GroupSymbol_ItemsAdded); groupSymbol.SymbolsCollection.ItemsRemoved -= new Collections.CollectionItemsChangedEventHandler(GroupSymbol_ItemsRemoved); groupSymbol.SymbolsCollection.CollectionReset -= new Collections.CollectionItemsChangedEventHandler(GroupSymbol_CollectionReset); } private void Symbol_Changed(object sender, EventArgs e) { ClearCaches(); OnChanged(); } private void GroupSymbol_Changed(object sender, EventArgs e) { GroupSymbol groupSymbol = (GroupSymbol)sender; foreach (ISymbol symbol in groupSymbol.Flatten()) symbol.Enabled = groupSymbol.Enabled; ClearCaches(); OnChanged(); } private void Symbol_NameChanging(object sender, CancelEventArgs e) { if (symbols.ContainsKey(e.Value)) e.Cancel = true; } private void Symbol_NameChanged(object sender, EventArgs e) { ISymbol symbol = (ISymbol)sender; string oldName = symbols.First(x => x.Value == symbol).Key; string newName = symbol.Name; symbols.Remove(oldName); symbols.Add(newName, symbol); var subtreeCount = symbolSubtreeCount[oldName]; symbolSubtreeCount.Remove(oldName); symbolSubtreeCount.Add(newName, subtreeCount); List allowedChilds; if (allowedChildSymbols.TryGetValue(oldName, out allowedChilds)) { allowedChildSymbols.Remove(oldName); allowedChildSymbols.Add(newName, allowedChilds); } for (int i = 0; i < GetMaximumSubtreeCount(symbol); i++) { if (allowedChildSymbolsPerIndex.TryGetValue(Tuple.Create(oldName, i), out allowedChilds)) { allowedChildSymbolsPerIndex.Remove(Tuple.Create(oldName, i)); allowedChildSymbolsPerIndex.Add(Tuple.Create(newName, i), allowedChilds); } } foreach (var parent in Symbols) { if (allowedChildSymbols.TryGetValue(parent.Name, out allowedChilds)) if (allowedChilds.Remove(oldName)) allowedChilds.Add(newName); for (int i = 0; i < GetMaximumSubtreeCount(parent); i++) { if (allowedChildSymbolsPerIndex.TryGetValue(Tuple.Create(parent.Name, i), out allowedChilds)) if (allowedChilds.Remove(oldName)) allowedChilds.Add(newName); } } ClearCaches(); OnChanged(); } private void GroupSymbol_ItemsAdded(object sender, CollectionItemsChangedEventArgs e) { foreach (ISymbol symbol in e.Items) if (!ContainsSymbol(symbol)) AddSymbol(symbol); OnChanged(); } private void GroupSymbol_ItemsRemoved(object sender, CollectionItemsChangedEventArgs e) { foreach (ISymbol symbol in e.Items) if (ContainsSymbol(symbol)) RemoveSymbol(symbol); OnChanged(); } private void GroupSymbol_CollectionReset(object sender, CollectionItemsChangedEventArgs e) { foreach (ISymbol symbol in e.Items) if (!ContainsSymbol(symbol)) AddSymbol(symbol); foreach (ISymbol symbol in e.OldItems) if (ContainsSymbol(symbol)) RemoveSymbol(symbol); OnChanged(); } #endregion } }