#region License Information /* HeuristicLab * Copyright (C) 2002-2008 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.Text; using HeuristicLab.Data; using HeuristicLab.Core; using System.Xml; using HeuristicLab.Constraints; using System.Diagnostics; namespace HeuristicLab.GP { public abstract class FunctionBase : ItemBase, IFunction { private List> allowedSubFunctions = new List>(); private int minArity = -1; private int maxArity = -1; private double tickets = 1.0; private IOperator initializer; private IOperator manipulator; private int minTreeHeight = -1; private int minTreeSize = -1; public virtual string Name { get { return this.GetType().Name; } } public virtual string Description { get { return "Description for this function is missing (TODO)"; } } public int MinArity { get { return minArity; } protected set { minArity = value; while (minArity > allowedSubFunctions.Count) allowedSubFunctions.Add(new List()); } } public int MaxArity { get { return maxArity; } protected set { maxArity = value; while (allowedSubFunctions.Count > maxArity) allowedSubFunctions.RemoveAt(allowedSubFunctions.Count - 1); while (maxArity > allowedSubFunctions.Count) allowedSubFunctions.Add(new List()); } } public int MinTreeSize { get { if (minTreeSize <= 0) RecalculateMinimalTreeSize(); return minTreeSize; } } public int MinTreeHeight { get { if (minTreeHeight <= 0) RecalculateMinimalTreeHeight(); return minTreeHeight; } } public double Tickets { get { return tickets; } set { if (value < 0.0) throw new ArgumentException("Number of tickets must be positive"); else tickets = value; } } public IOperator Initializer { get { return initializer; } set { initializer = value; } } public IOperator Manipulator { get { return manipulator; } set { manipulator = value; } } public virtual IEnumerable LocalParameterNames { get { return new string[0]; } } public virtual IFunctionTree GetTreeNode() { return new BakedFunctionTree(this); } //private List constraints = new List(); //public ICollection Constraints { // get { return constraints; } //} //private void RefreshArity() { // minArity = 2; maxArity = 2; // default arity is 2 // foreach (IConstraint constraint in Constraints) { // NumberOfSubOperatorsConstraint theConstraint = constraint as NumberOfSubOperatorsConstraint; // if (theConstraint != null) { // minArity = theConstraint.MinOperators.Data; // maxArity = theConstraint.MaxOperators.Data; // } // } //} public ICollection GetAllowedSubFunctions(int index) { if (index < 0 || index > MaxArity) throw new ArgumentException("Index outside of allowed range. index = " + index); //if (allowedSubFunctions == null) { // // first time: analyze the constraint and create a cached copy of the allowed sub-functions // allowedSubFunctions = new List[MaxArity]; // for (int i = 0; i < MaxArity; i++) { // allowedSubFunctions[i] = GetAllowedSubFunctions(i); // } //} return allowedSubFunctions[index]; } public void AddAllowedSubFunction(IFunction function, int index) { if (index < 0 || index > MaxArity) throw new ArgumentException("Index outside of allowed range. index = " + index); if (allowedSubFunctions[index] == null) { allowedSubFunctions[index] = new List(); } if (!allowedSubFunctions[index].Contains(function)) { allowedSubFunctions[index].Add(function); } } public void RemoveAllowedSubFunction(IFunction function, int index) { if (index < 0 || index > MaxArity) throw new ArgumentException("Index outside of allowed range. index = " + index); allowedSubFunctions[index].Add(function); } public bool IsAllowedSubFunction(IFunction function, int index) { return GetAllowedSubFunctions(index).Contains(function); } //private List GetAllowedSubFunctions(int index) { // List allowedSubFunctions = new List(); // foreach (IConstraint constraint in Constraints) { // if (constraint is SubOperatorTypeConstraint) { // SubOperatorTypeConstraint subOpConstraint = constraint as SubOperatorTypeConstraint; // if (subOpConstraint.SubOperatorIndex.Data == index) { // foreach (IFunction f in subOpConstraint.AllowedSubOperators) allowedSubFunctions.Add(f); // subOpConstraint.Changed += new EventHandler(subOpConstraint_Changed); // register an event-handler to invalidate the cache on constraint changes // return allowedSubFunctions; // } // } else if (constraint is AllSubOperatorsTypeConstraint) { // AllSubOperatorsTypeConstraint subOpConstraint = constraint as AllSubOperatorsTypeConstraint; // foreach (IFunction f in subOpConstraint.AllowedSubOperators) allowedSubFunctions.Add(f); // subOpConstraint.Changed += new EventHandler(subOpConstraint_Changed); // register an event-handler to invalidate the cache on constraint changes // return allowedSubFunctions; // } // } // return allowedSubFunctions; //} //private void subOpConstraint_Changed(object sender, EventArgs e) { // allowedSubFunctions = null; //} public override IView CreateView() { return new FunView(this); } private void RecalculateMinimalTreeSize() { minTreeSize = int.MaxValue; int sum = 1; int minSize = int.MaxValue; for (int i = 0; i < MinArity; i++) { foreach (IFunction subFun in GetAllowedSubFunctions(i)) { minSize = Math.Min(minSize, subFun.MinTreeSize); } sum += minSize; } minTreeSize = sum; } private void RecalculateMinimalTreeHeight() { minTreeHeight = int.MaxValue; int height = 0; int minHeight = int.MaxValue; for (int i = 0; i < MinArity; i++) { foreach (IFunction subFun in GetAllowedSubFunctions(i)) { minHeight = Math.Min(minHeight, subFun.MinTreeHeight); } height = Math.Max(height, minHeight); } minTreeHeight = height + 1; } } }