#region License Information
/* HeuristicLab
* Copyright (C) 2002-2011 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.Linq;
using HeuristicLab.Common;
using HeuristicLab.Core;
using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
using System.Collections.Generic;
namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding {
[StorableClass]
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; }
}
#endregion
[StorableHook(HookType.AfterDeserialization)]
private void AfterDeserialization() {
foreach (ISymbol symbol in symbols.Values)
RegisterSymbolEvents(symbol);
}
[StorableConstructor]
protected SymbolicExpressionGrammar(bool deserializing) : base(deserializing) { }
protected SymbolicExpressionGrammar(SymbolicExpressionGrammar original, Cloner cloner)
: base(original, cloner) {
foreach (ISymbol symbol in Symbols)
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;
}
public SymbolicExpressionGrammar(string name, string description)
: base(name, description) {
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);
}
}
protected override void AddSymbol(ISymbol symbol) {
base.AddSymbol(symbol);
RegisterSymbolEvents(symbol);
}
protected override void RemoveSymbol(ISymbol symbol) {
DeregisterSymbolEvents(symbol);
base.RemoveSymbol(symbol);
}
public event EventHandler ReadOnlyChanged;
protected virtual void OnReadOnlyChanged() {
var handler = ReadOnlyChanged;
if (handler != null)
handler(this, EventArgs.Empty);
}
#region IStatefulItem
void IStatefulItem.InitializeState() { }
void IStatefulItem.ClearState() {
ReadOnly = false;
}
#endregion
#region symbol events
protected virtual void RegisterSymbolEvents(ISymbol symbol) {
symbol.NameChanging += new EventHandler>(Symbol_NameChanging);
symbol.NameChanged += new EventHandler(Symbol_NameChanged);
}
protected virtual void DeregisterSymbolEvents(ISymbol symbol) {
symbol.NameChanging -= new EventHandler>(Symbol_NameChanging);
symbol.NameChanged -= new EventHandler(Symbol_NameChanged);
}
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.Where(x => x.Value == symbol).First().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();
}
#endregion
}
}