Free cookie consent management tool by TermsFeed Policy Generator

Changeset 155 for trunk


Ignore:
Timestamp:
04/22/08 18:05:14 (16 years ago)
Author:
gkronber
Message:

merged FunctionsAndStructIdRefactoring-branch (r142, r143, r144, r145, r146, r147, r148, r149, r152, r153) back into the trunk (ticket #112)

Location:
trunk/sources
Files:
1 deleted
44 edited
3 copied

Legend:

Unmodified
Added
Removed
  • trunk/sources/HeuristicLab.Constraints/SubOperatorsConstraintAnalyser.cs

    r2 r155  
    9191    private static bool InSet(IOperator op, ICollection<IOperator> set) {
    9292      foreach(IOperator element in set) {
    93         if(((StringData)element.GetVariable("TypeId").Value).Data ==
     93        if(element==op ||
     94          ((StringData)element.GetVariable("TypeId").Value).Data ==
    9495          ((StringData)op.GetVariable("TypeId").Value).Data) {
    9596          return true;
  • trunk/sources/HeuristicLab.Functions/Addition.cs

    r2 r155  
    3333    public override string Description {
    3434      get {
    35         return @"Returns the sum of all sub-operator results.
     35        return @"Returns the sum of all sub-tree results.
    3636    (+ 3) => 3
    3737    (+ 2 3) => 5
     
    4646    }
    4747
    48     public Addition(Addition source, IDictionary<Guid, object> clonedObjects)
    49       : base(source, clonedObjects) {
    50     }
    51 
    52 
    53     public override double Evaluate(Dataset dataset, int sampleIndex) {
     48    public override double Apply(Dataset dataset, int sampleIndex, double[] args) {
    5449      // (+ 3) => 3
    5550      // (+ 2 3) => 5
    5651      // (+ 3 4 5) => 12
    5752      double sum = 0.0;
    58       for (int i = SubFunctions.Count - 1; i >= 0; i--) {
    59         sum += SubFunctions[i].Evaluate(dataset, sampleIndex);
     53      for (int i = 0; i < args.Length; i++) {
     54        sum += args[i];
    6055      }
    6156      return sum;
    62     }
    63 
    64     public override object Clone(IDictionary<Guid, object> clonedObjects) {
    65       Addition clone = new Addition(this, clonedObjects);
    66       clonedObjects.Add(clone.Guid, clone);
    67       return clone;
    6857    }
    6958
  • trunk/sources/HeuristicLab.Functions/And.cs

    r2 r155  
    3131    public override string Description {
    3232      get {
    33         return @"Logical AND operation. Only defined for sub-operator-results 0.0 and 1.0.";
     33        return @"Logical AND operation. Only defined for sub-tree-results 0.0 and 1.0.
     34AND is a special form, sub-trees are evaluated from the first to the last. Evaluation is
     35stopped as soon as one of the sub-trees evaluates to 0.0 (false).";
    3436      }
    3537    }
     
    4042    }
    4143
    42     public And(And source, IDictionary<Guid, object> clonedObjects)
    43       : base(source, clonedObjects) {
    44     }
    45 
    46 
    47     public override double Evaluate(Dataset dataset, int sampleIndex) {
    48       foreach(IFunction subFunction in SubFunctions) {
    49         double result = Math.Round(subFunction.Evaluate(dataset, sampleIndex));
    50         if(result == 0.0) return 0.0;
     44    // special form
     45    public override double Evaluate(Dataset dataset, int sampleIndex, IFunctionTree tree) {
     46      foreach(IFunctionTree subTree in tree.SubTrees) {
     47        double result = Math.Round(subTree.Evaluate(dataset, sampleIndex));
     48        if(result == 0.0) return 0.0; // one sub-tree is 0.0 (false) => return false
    5149        else if(result != 1.0) return double.NaN;
    5250      }
     51      // all sub-trees evaluated to 1.0 (true) => return 1.0 (true)
    5352      return 1.0;
    5453    }
    5554
    56     public override object Clone(IDictionary<Guid, object> clonedObjects) {
    57       And clone = new And(this, clonedObjects);
    58       clonedObjects.Add(clone.Guid, clone);
    59       return clone;
     55    public override double Apply(Dataset dataset, int sampleIndex, double[] args) {
     56      throw new NotImplementedException();
    6057    }
    6158
  • trunk/sources/HeuristicLab.Functions/Average.cs

    r2 r155  
    3131    public override string Description {
    3232      get {
    33         return @"Returns the average (arithmetic mean) of all sub-operator results.";
     33        return @"Returns the average (arithmetic mean) of all sub-tree results.";
    3434      }
    3535    }
     
    4040    }
    4141
    42     public Average(Average source, IDictionary<Guid, object> clonedObjects)
    43       : base(source, clonedObjects) {
    44     }
    45 
    46 
    47     public override double Evaluate(Dataset dataset, int sampleIndex) {
     42    public override double Apply(Dataset dataset, int sampleIndex, double[] args) {
    4843      double sum = 0.0;
    49       for(int i = 0; i < SubFunctions.Count; i++) {
    50         sum += SubFunctions[i].Evaluate(dataset, sampleIndex);
     44      for(int i = 0; i < args.Length; i++) {
     45        sum += args[i];
    5146      }
    52       return sum / SubFunctions.Count;
    53     }
    54 
    55     public override object Clone(IDictionary<Guid, object> clonedObjects) {
    56       Average clone = new Average(this, clonedObjects);
    57       clonedObjects.Add(clone.Guid, clone);
    58       return clone;
     47      return sum / args.Length;
    5948    }
    6049
  • trunk/sources/HeuristicLab.Functions/Constant.cs

    r2 r155  
    3131namespace HeuristicLab.Functions {
    3232  public class Constant : FunctionBase {
    33 
    34     private IVariable value;
     33    public static readonly string VALUE = "Value";
    3534
    3635    public override string Description {
     
    3837    }
    3938
    40     public ConstrainedDoubleData Value {
    41       get {
    42         return (ConstrainedDoubleData)value.Value;
    43       }
    44     }
    45 
    4639    public Constant()
    4740      : base() {
    48       AddVariableInfo(new VariableInfo("Value", "The constant value", typeof(ConstrainedDoubleData), VariableKind.None));
    49       GetVariableInfo("Value").Local = true;
     41      AddVariableInfo(new VariableInfo(VALUE, "The constant value", typeof(ConstrainedDoubleData), VariableKind.None));
     42      GetVariableInfo(VALUE).Local = true;
    5043
    5144      ConstrainedDoubleData valueData = new ConstrainedDoubleData();
    5245      // initialize a default range for the contant value
    5346      valueData.AddConstraint(new DoubleBoundedConstraint(-20.0, 20.0));
    54 
    55       // create the local variable
    56       value = new HeuristicLab.Core.Variable("Value", valueData);
    57       AddLocalVariable(value);
     47      HeuristicLab.Core.Variable value = new HeuristicLab.Core.Variable(VALUE, valueData);
     48      AddVariable(value);
    5849
    5950      // constant can't have suboperators
     
    6152    }
    6253
    63     public Constant(Constant source, IDictionary<Guid, object> clonedObjects)
    64       : base(source, clonedObjects) {
    65       value = GetVariable("Value");
     54    // constant is evaluated directly. Evaluation reads the local variable value from the tree and returns
     55    public override double Evaluate(Dataset dataset, int sampleIndex, IFunctionTree tree) {
     56      return ((ConstrainedDoubleData)tree.GetLocalVariable(VALUE).Value).Data;
    6657    }
    6758
    68     public override object Clone(IDictionary<Guid, object> clonedObjects) {
    69       Constant clone = new Constant(this, clonedObjects);
    70       clonedObjects.Add(clone.Guid, clone);
    71       return clone;
    72     }
    73 
    74 
    75     public override void Populate(XmlNode node, IDictionary<Guid,IStorable> restoredObjects) {
    76       base.Populate(node, restoredObjects);
    77 
    78       value = GetVariable("Value");
    79     }
    80 
    81     public override double Evaluate(Dataset dataset, int sampleIndex) {
    82       return ((ConstrainedDoubleData)value.Value).Data;
     59    // can't apply a constant
     60    public override double Apply(Dataset dataset, int sampleIndex, double[] args) {
     61      throw new NotSupportedException();
    8362    }
    8463
  • trunk/sources/HeuristicLab.Functions/Cosinus.cs

    r2 r155  
    3131  public class Cosinus : FunctionBase {
    3232    public override string Description {
    33       get { return "Returns the cosinus of the first sub-operator."; }
     33      get { return "Returns the cosinus of the first sub-tree."; }
    3434    }
    3535
    3636    public Cosinus()
    3737      : base() {
    38 
    3938      // must have exactly one subfunction
    4039      AddConstraint(new NumberOfSubOperatorsConstraint(1, 1));
    4140    }
    4241
    43     public Cosinus(Cosinus source, IDictionary<Guid, object> clonedObjects)
    44       : base(source, clonedObjects) {
     42    public override double Apply(Dataset dataset, int sampleIndex, double[] args) {
     43      return Math.Cos(args[0]);
    4544    }
    46 
    47     public override double Evaluate(Dataset dataset, int sampleIndex) {
    48       return Math.Cos(SubFunctions[0].Evaluate(dataset, sampleIndex));
    49     }
    50 
    51     public override object Clone(IDictionary<Guid, object> clonedObjects) {
    52       Cosinus clone = new Cosinus(this, clonedObjects);
    53       clonedObjects.Add(clone.Guid, clone);
    54       return clone;
    55     }
    56 
    5745
    5846    public override void Accept(IFunctionVisitor visitor) {
  • trunk/sources/HeuristicLab.Functions/Division.cs

    r2 r155  
    3636      get {
    3737        return @"Protected division
    38 Divides the result of the first sub-operator by the results of the following sub-operators.
     38Divides the result of the first sub-tree by the results of the following sub-tree.
    3939In case one of the divisors is 0 returns 0.
    4040    (/ 3) => 1/3
     
    4848    public Division()
    4949      : base() {
    50 
    5150      // 2 - 3 seems like an reasonable defaut (used for +,-,*,/) (discussion with swinkler and maffenze)
    5251      AddConstraint(new NumberOfSubOperatorsConstraint(2, 3));
    5352    }
    5453
    55     public Division(Division source, IDictionary<Guid, object> clonedObjects)
    56       : base(source, clonedObjects) {
    57     }
    58 
    59     public override double Evaluate(Dataset dataset, int sampleIndex) {
     54    public override double Apply(Dataset dataset, int sampleIndex, double[] args) {
    6055      // (/ 3) => 1/3
    6156      // (/ 2 3) => 2/3
    6257      // (/ 3 4 5) => 3/20
    6358
    64       if(SubFunctions.Count == 1) {
    65         double divisor = SubFunctions[0].Evaluate(dataset, sampleIndex);
     59      if(args.Length == 1) {
     60        double divisor = args[0];
    6661        if(Math.Abs(divisor) < EPSILON) return 0;
    6762        else return 1.0 / divisor;
    6863      } else {
    69         double result = SubFunctions[0].Evaluate(dataset, sampleIndex);
    70         for(int i = 1; i < SubFunctions.Count; i++) {
    71           double divisor = SubFunctions[i].Evaluate(dataset, sampleIndex);
     64        double result = args[0];
     65        for(int i = 1; i < args.Length; i++) {
     66          double divisor = args[i];
    7267          if(Math.Abs(divisor) < EPSILON) return 0.0;
    7368          result /= divisor;
     
    7772    }
    7873
    79     public override object Clone(IDictionary<Guid, object> clonedObjects) {
    80       Division clone = new Division(this, clonedObjects);
    81       clonedObjects.Add(clone.Guid, clone);
    82       return clone;
    83     }
    84 
    8574    public override void Accept(IFunctionVisitor visitor) {
    8675      visitor.Visit(this);
  • trunk/sources/HeuristicLab.Functions/Equal.cs

    r2 r155  
    3131    public override string Description {
    3232      get {
    33         return @"Equal condition. Returns 1.0 if both sub-functions evaluate to the same value and 0.0 if they differ.";
     33        return @"Equal condition. Returns 1.0 if both sub-trees evaluate to the same value and 0.0 if they differ.";
    3434      }
    3535    }
     
    4040    }
    4141
    42     public Equal(Equal source, IDictionary<Guid, object> clonedObjects)
    43       : base(source, clonedObjects) {
    44     }
    45 
    46 
    47     public override double Evaluate(Dataset dataset, int sampleIndex) {
    48       if(SubFunctions[0].Evaluate(dataset, sampleIndex) == SubFunctions[1].Evaluate(dataset, sampleIndex)) return 1.0;
     42    public override double Apply(Dataset dataset, int sampleIndex, double[] args) {
     43      if(args[0] == args[1]) return 1.0;
    4944      else return 0.0;
    50     }
    51 
    52     public override object Clone(IDictionary<Guid, object> clonedObjects) {
    53       Equal clone = new Equal(this, clonedObjects);
    54       clonedObjects.Add(clone.Guid, clone);
    55       return clone;
    5645    }
    5746
  • trunk/sources/HeuristicLab.Functions/Exponential.cs

    r2 r155  
    3131  public class Exponential : FunctionBase {
    3232    public override string Description {
    33       get { return "Returns returns exponential of the first sub-operator (power(e, x))."; }
     33      get { return "Returns returns exponential of the first sub-tree (power(e, x))."; }
    3434    }
    3535
     
    3939      AddConstraint(new NumberOfSubOperatorsConstraint(1, 1));
    4040    }
    41     public Exponential(Exponential source, IDictionary<Guid, object> clonedObjects)
    42       : base(source, clonedObjects) {
     41
     42    public override double Apply(Dataset dataset, int sampleIndex, double[] args) {
     43      return Math.Exp(args[0]);
    4344    }
    44 
    45 
    46     public override double Evaluate(Dataset dataset, int sampleIndex) {
    47       return Math.Exp(SubFunctions[0].Evaluate(dataset, sampleIndex));
    48     }
    49 
    50     public override object Clone(IDictionary<Guid, object> clonedObjects) {
    51       Exponential clone = new Exponential(this, clonedObjects);
    52       clonedObjects.Add(clone.Guid, clone);
    53       return clone;
    54     }
    55 
    5645
    5746    public override void Accept(IFunctionVisitor visitor) {
  • trunk/sources/HeuristicLab.Functions/FunctionBase.cs

    r2 r155  
    2929
    3030namespace HeuristicLab.Functions {
     31  /// <summary>
     32  /// Functions are like operators except that they do not allow sub-operators and the normal form of evaluation
     33  /// is to evaluate all children first.
     34  /// </summary>
    3135  public abstract class FunctionBase : OperatorBase, IFunction {
    32     private List<IFunction> subFunctions;
    33     // instance subfunctions
    34     public IList<IFunction> SubFunctions {
    35       get {
    36         return subFunctions;
     36   
     37    public virtual double Evaluate(Dataset dataset, int sampleIndex, IFunctionTree tree) {
     38      if(tree.SubTrees.Count > 0) {
     39        double[] evaluationResults = new double[tree.SubTrees.Count];
     40        for(int i = 0; i < evaluationResults.Length; i++) {
     41          evaluationResults[i] = tree.SubTrees[i].Evaluate(dataset, sampleIndex);
     42        }
     43        return Apply(dataset, sampleIndex, evaluationResults);
     44      } else {
     45        return Apply(dataset, sampleIndex, null);
    3746      }
    3847    }
    3948
    40     // instance variables
    41     private List<IVariable> variables;
    42     public ICollection<IVariable> LocalVariables {
    43       get { return variables.AsReadOnly(); }
     49    public abstract double Apply(Dataset dataset, int sampleIndex, double[] args);
     50
     51    // operator-tree style evaluation is not supported for functions.
     52    public override IOperation Apply(IScope scope) {
     53      throw new NotSupportedException();
    4454    }
    45 
    46     // reference to the 'type' of the function
    47     private FunctionBase metaObject;
    48     public IFunction MetaObject {
    49       get { return metaObject; }
    50     }
    51 
    52     public FunctionBase() {
    53       metaObject = this; // (FunctionBase)Activator.CreateInstance(this.GetType());
    54       AddVariableInfo(new VariableInfo("Dataset", "Dataset from which to read samples", typeof(DoubleMatrixData), VariableKind.In));
    55       AddVariableInfo(new VariableInfo("SampleIndex", "Gives the row index from which to read the sample", typeof(IntData), VariableKind.In));
    56       AddVariableInfo(new VariableInfo("Result", "The result of the evaluation of the function", typeof(DoubleData), VariableKind.Out));
    57 
    58       subFunctions = new List<IFunction>();
    59       variables = new List<IVariable>();
    60     }
    61 
    62     public FunctionBase(FunctionBase source, IDictionary<Guid, object> clonedObjects)
    63       : base() {
    64       this.metaObject = source.metaObject;
    65       variables = new List<IVariable>();
    66       subFunctions = new List<IFunction>();
    67       foreach (IFunction subFunction in source.SubFunctions) {
    68         subFunctions.Add((IFunction)Auxiliary.Clone(subFunction, clonedObjects));
    69       }
    70       foreach (IVariable variable in source.variables) {
    71         variables.Add((IVariable)Auxiliary.Clone(variable, clonedObjects));
    72       }
    73     }
    74 
    75     public abstract double Evaluate(Dataset dataset, int sampleIndex);
    76 
    77     public override IOperation Apply(IScope scope) {
    78       DoubleData result = this.GetVariableValue<DoubleData>("Result", scope, false);
    79       Dataset dataset = GetVariableValue<Dataset>("Dataset", scope, true);
    80       IntData sampleIndex = GetVariableValue<IntData>("SampleIndex", scope, true);
    81       result.Data = Evaluate(dataset, sampleIndex.Data);
    82       return null;
    83     }
    84 
    8555    public virtual void Accept(IFunctionVisitor visitor) {
    8656      visitor.Visit(this);
    8757    }
    8858
     59    private static readonly List<IOperator> emptySubOperatorList = new List<IOperator>();
     60    public override IList<IOperator> SubOperators {
     61      get { return emptySubOperatorList; }
     62    }
     63
    8964    public override void AddSubOperator(IOperator subOperator) {
    90       subFunctions.Add((IFunction)subOperator);
     65      throw new NotSupportedException();
    9166    }
    9267
    9368    public override bool TryAddSubOperator(IOperator subOperator) {
    94       subFunctions.Add((IFunction)subOperator);
    95       bool valid = IsValid();
    96       if (!valid) {
    97         subFunctions.RemoveAt(subFunctions.Count - 1);
    98       }
    99 
    100       return valid;
     69      throw new NotSupportedException();
    10170    }
    10271
    10372    public override bool TryAddSubOperator(IOperator subOperator, int index) {
    104       subFunctions.Insert(index, (IFunction)subOperator);
    105       bool valid = IsValid();
    106       if (!valid) {
    107         subFunctions.RemoveAt(index);
    108       }
    109       return valid;
     73      throw new NotSupportedException();
    11074    }
    11175
    11276    public override bool TryAddSubOperator(IOperator subOperator, int index, out ICollection<IConstraint> violatedConstraints) {
    113       subFunctions.Insert(index, (IFunction)subOperator);
    114       bool valid = IsValid(out violatedConstraints);
    115       if (!valid) {
    116         subFunctions.RemoveAt(index);
    117       }
    118       return valid;
     77      throw new NotSupportedException();
    11978    }
    12079
    12180    public override bool TryAddSubOperator(IOperator subOperator, out ICollection<IConstraint> violatedConstraints) {
    122       subFunctions.Add((IFunction)subOperator);
    123       bool valid = IsValid(out violatedConstraints);
    124       if (!valid) {
    125         subFunctions.RemoveAt(subFunctions.Count - 1);
    126       }
    127 
    128       return valid;
     81      throw new NotSupportedException();
    12982    }
    13083
    13184    public override void AddSubOperator(IOperator subOperator, int index) {
    132       subFunctions.Insert(index, (IFunction)subOperator);
     85      throw new NotSupportedException();
    13386    }
    13487
    13588    public override void RemoveSubOperator(int index) {
    136       if (index >= subFunctions.Count) throw new InvalidOperationException();
    137       subFunctions.RemoveAt(index);
     89      throw new NotSupportedException();
    13890    }
    13991
    140     public override IList<IOperator> SubOperators {
    141       get { return subFunctions.ConvertAll(f => (IOperator)f); }
    142     }
    143 
    144     public override ICollection<IVariable> Variables {
    145       get {
    146         List<IVariable> mergedVariables = new List<IVariable>(variables);
    147         if (this == metaObject) {
    148           foreach (IVariable variable in base.Variables) {
    149             if (!IsLocalVariable(variable.Name)) {
    150               mergedVariables.Add(variable);
    151             }
    152           }
    153         } else {
    154           foreach (IVariable variable in metaObject.Variables) {
    155             if (!IsLocalVariable(variable.Name)) {
    156               mergedVariables.Add(variable);
    157             }
    158           }
    159         }
    160         return mergedVariables;
    161       }
    162     }
    163 
    164     private bool IsLocalVariable(string name) {
    165       foreach (IVariable variable in variables) {
    166         if (variable.Name == name) return true;
    167       }
    168       return false;
    169     }
    170 
    171 
    17292    public override bool TryRemoveSubOperator(int index) {
    173       IFunction removedFunction = subFunctions[index];
    174       subFunctions.RemoveAt(index);
    175       bool valid = IsValid();
    176       if (!valid) {
    177         subFunctions.Insert(index, removedFunction);
    178       }
    179 
    180       return valid;
     93      throw new NotSupportedException();
    18194    }
    18295
    18396    public override bool TryRemoveSubOperator(int index, out ICollection<IConstraint> violatedConstraints) {
    184       IFunction removedFunction = subFunctions[index];
    185       subFunctions.RemoveAt(index);
    186       bool valid = IsValid(out violatedConstraints);
    187       if (!valid) {
    188         subFunctions.Insert(index, removedFunction);
    189       }
    190 
    191       return valid;
    192     }
    193 
    194     public override void AddVariable(IVariable variable) {
    195       if (metaObject == this) {
    196         base.AddVariable(variable);
    197       } else {
    198         metaObject.AddVariable(variable);
    199       }
    200     }
    201 
    202     public override IVariable GetVariable(string name) {
    203       foreach (IVariable variable in variables) {
    204         if (variable.Name == name) return variable;
    205       }
    206       if (metaObject == this) {
    207         return base.GetVariable(name);
    208       } else {
    209         return metaObject.GetVariable(name);
    210       }
    211     }
    212 
    213     public void AddLocalVariable(IVariable variable) {
    214       variables.Add(variable);
    215     }
    216 
    217     public override void RemoveVariable(string name) {
    218       foreach (IVariable variable in variables) {
    219         if (variable.Name == name) {
    220           variables.Remove(variable);
    221           return;
    222         }
    223       }
    224       if (metaObject == this) {
    225         base.RemoveVariable(name);
    226       } else {
    227         metaObject.RemoveVariable(name);
    228       }
    229     }
    230 
    231     public override IItem GetVariableValue(string formalName, IScope scope, bool recursiveLookup, bool throwOnError) {
    232       foreach (IVariable variable in Variables) {
    233         if (variable.Name == formalName) {
    234           return variable.Value;
    235         }
    236       }
    237       return metaObject.GetVariableValue(formalName, scope, recursiveLookup, throwOnError);
    238     }
    239 
    240     public override ICollection<IVariableInfo> VariableInfos {
    241       get {
    242         if (metaObject == this) {
    243           return base.VariableInfos;
    244         } else {
    245           return metaObject.VariableInfos;
    246         }
    247       }
    248     }
    249 
    250     public override void AddVariableInfo(IVariableInfo variableInfo) {
    251       if (metaObject == this) {
    252         base.AddVariableInfo(variableInfo);
    253       } else {
    254         metaObject.AddVariableInfo(variableInfo);
    255       }
    256     }
    257 
    258     public override void RemoveVariableInfo(string formalName) {
    259       if (metaObject == this) {
    260         base.RemoveVariableInfo(formalName);
    261       } else {
    262         metaObject.RemoveVariableInfo(formalName);
    263       }
    264     }
    265 
    266     public override ICollection<IConstraint> Constraints {
    267       get {
    268         if (metaObject == this) {
    269           return base.Constraints;
    270         } else {
    271           return metaObject.Constraints;
    272         }
    273       }
    274     }
    275 
    276     public override void AddConstraint(IConstraint constraint) {
    277       if (metaObject == this) {
    278         base.AddConstraint(constraint);
    279       } else {
    280         metaObject.AddConstraint(constraint);
    281       }
    282     }
    283     public override void RemoveConstraint(IConstraint constraint) {
    284       if (metaObject == this) {
    285         base.RemoveConstraint(constraint);
    286       } else {
    287         metaObject.RemoveConstraint(constraint);
    288       }
    289     }
    290 
    291     public override XmlNode GetXmlNode(string name, XmlDocument document, IDictionary<Guid, IStorable> persistedObjects) {
    292       XmlNode node = base.GetXmlNode(name, document, persistedObjects);
    293       if (metaObject != this) {
    294         XmlNode functionTemplateNode = document.CreateElement("FunctionTemplate");
    295         functionTemplateNode.AppendChild(PersistenceManager.Persist(metaObject, document, persistedObjects));
    296         node.AppendChild(functionTemplateNode);
    297       }
    298 
    299       // don't need to persist the sub-functions because OperatorBase.GetXmlNode already persisted the sub-operators
    300 
    301       // persist local variables
    302       XmlNode variablesNode = document.CreateNode(XmlNodeType.Element, "LocalVariables", null);
    303       foreach (IVariable variable in variables) {
    304         variablesNode.AppendChild(PersistenceManager.Persist(variable, document, persistedObjects));
    305       }
    306       node.AppendChild(variablesNode);
    307       return node;
    308     }
    309 
    310     public override void Populate(XmlNode node, IDictionary<Guid, IStorable> restoredObjects) {
    311       base.Populate(node, restoredObjects);
    312       XmlNode functionTemplateNode = node.SelectSingleNode("FunctionTemplate");
    313       if (functionTemplateNode != null) {
    314         metaObject = (FunctionBase)PersistenceManager.Restore(functionTemplateNode.ChildNodes[0], restoredObjects);
    315       } else {
    316         metaObject = this;
    317       }
    318       // don't need to explicitly load the sub-functions because that has already been done in OperatorBase.Populate()
    319 
    320       // load local variables
    321       XmlNode variablesNode = node.SelectSingleNode("LocalVariables");
    322      
    323       // remove the variables that have been added in a constructor
    324       variables.Clear();
    325       // load the persisted variables
    326       foreach (XmlNode variableNode in variablesNode.ChildNodes)
    327         variables.Add((IVariable)PersistenceManager.Restore(variableNode, restoredObjects));
    328     }
    329 
    330     public override IView CreateView() {
    331       return new FunctionView(this);
     97      throw new NotSupportedException();
    33298    }
    33399  }
  • trunk/sources/HeuristicLab.Functions/FunctionView.Designer.cs

    r2 r155  
    2222using System;
    2323namespace HeuristicLab.Functions {
    24   partial class FunctionView {
     24  partial class FunctionTreeView {
    2525    /// <summary>
    2626    /// Required designer variable.
     
    167167            this.copyToClipboardMenuItem});
    168168      this.treeNodeContextMenu.Name = "treeNodeContextMenu";
    169       this.treeNodeContextMenu.Size = new System.Drawing.Size(259, 26);
     169      this.treeNodeContextMenu.Size = new System.Drawing.Size(248, 26);
    170170      //
    171171      // copyToClipboardMenuItem
    172172      //
    173173      this.copyToClipboardMenuItem.Name = "copyToClipboardMenuItem";
    174       this.copyToClipboardMenuItem.Size = new System.Drawing.Size(258, 22);
     174      this.copyToClipboardMenuItem.Size = new System.Drawing.Size(247, 22);
    175175      this.copyToClipboardMenuItem.Text = "Copy to clip-board (Model-Analyzer)";
    176176      this.copyToClipboardMenuItem.Click += new System.EventHandler(this.copyToClipboardMenuItem_Click);
  • trunk/sources/HeuristicLab.Functions/FunctionView.cs

    r2 r155  
    3030using HeuristicLab.Core;
    3131using HeuristicLab.PluginInfrastructure;
     32using HeuristicLab.Data;
    3233
    3334namespace HeuristicLab.Functions {
    34   public partial class FunctionView : ViewBase {
    35     private IFunction function;
    36 
    37     private IFunction selectedFunction;
     35  public partial class FunctionTreeView : ViewBase {
     36    private IFunctionTree functionTree;
     37
     38    private IFunctionTree selectedBranch;
    3839    private IVariable selectedVariable;
    3940
    4041    private FunctionNameVisitor functionNameVisitor;
    41     public FunctionView() {
     42    public FunctionTreeView() {
    4243      InitializeComponent();
    4344      functionNameVisitor = new FunctionNameVisitor();
    4445    }
    4546
    46     public FunctionView(IFunction function)
     47    public FunctionTreeView(IFunctionTree functionTree)
    4748      : this() {
    48       this.function = function;
     49      this.functionTree = functionTree;
    4950      Refresh();
    5051    }
     
    5253    protected override void UpdateControls() {
    5354      functionTreeView.Nodes.Clear();
    54       function.Accept(functionNameVisitor);
     55      functionNameVisitor.Visit(functionTree);
    5556      TreeNode rootNode = new TreeNode();
    56       rootNode.Name = function.Name;
     57      rootNode.Name = functionTree.Function.Name;
    5758      rootNode.Text = functionNameVisitor.Name;
    58       rootNode.Tag = function;
     59      rootNode.Tag = functionTree;
    5960      rootNode.ContextMenuStrip = treeNodeContextMenu;
    6061      functionTreeView.Nodes.Add(rootNode);
    6162
    62       foreach(IFunction subFunction in function.SubFunctions) {
    63         CreateTree(rootNode, subFunction);
     63      foreach(IFunctionTree subTree in functionTree.SubTrees) {
     64        CreateTree(rootNode, subTree);
    6465      }
    6566      functionTreeView.ExpandAll();
    6667    }
    6768
    68     private void CreateTree(TreeNode rootNode, IFunction function) {
     69    private void CreateTree(TreeNode rootNode, IFunctionTree functionTree) {
    6970      TreeNode node = new TreeNode();
    70       function.Accept(functionNameVisitor);
    71       node.Tag = function;
    72       node.Name = function.Name;
     71      functionNameVisitor.Visit(functionTree);
     72      node.Name = functionTree.Function.Name;
    7373      node.Text = functionNameVisitor.Name;
     74      node.Tag = functionTree;
    7475      node.ContextMenuStrip = treeNodeContextMenu;
    7576      rootNode.Nodes.Add(node);
    76       foreach(IFunction subFunction in function.SubFunctions) {
    77         CreateTree(node, subFunction);
     77      foreach(IFunctionTree subTree in functionTree.SubTrees) {
     78        CreateTree(node, subTree);
    7879      }
    7980    }
     
    8586      editButton.Enabled = false;
    8687      if(functionTreeView.SelectedNode != null && functionTreeView.SelectedNode.Tag != null) {
    87         IFunction selectedFunction = (IFunction)functionTreeView.SelectedNode.Tag;
    88         UpdateVariablesList(selectedFunction);
    89         templateTextBox.Text = selectedFunction.MetaObject.Name;
    90         this.selectedFunction = selectedFunction;
     88        IFunctionTree selectedBranch = (IFunctionTree)functionTreeView.SelectedNode.Tag;
     89        UpdateVariablesList(selectedBranch);
     90        templateTextBox.Text = selectedBranch.Function.Name;
     91        this.selectedBranch = selectedBranch;
    9192        editButton.Enabled = true;
    9293      }
    9394    }
    9495
    95     private void UpdateVariablesList(IFunction function) {
    96       foreach(IVariable variable in function.LocalVariables) {
     96    private void UpdateVariablesList(IFunctionTree functionTree) {
     97      foreach(IVariable variable in functionTree.LocalVariables) {
    9798        variablesListBox.Items.Add(variable.Name);
    9899      }
     
    106107      if(variablesListBox.SelectedItem != null) {
    107108        string selectedVariableName = (string)variablesListBox.SelectedItem;
    108         selectedVariable = selectedFunction.GetVariable(selectedVariableName);
     109        selectedVariable = selectedBranch.GetLocalVariable(selectedVariableName);
    109110        variablesSplitContainer.Panel2.Controls.Clear();
    110111        Control editor = (Control)selectedVariable.CreateView();
     
    121122      if(functionTreeView.SelectedNode != null && functionTreeView.SelectedNode.Tag != null) {
    122123        TreeNode node = functionTreeView.SelectedNode;
    123         selectedFunction.Accept(functionNameVisitor);
     124        functionNameVisitor.Visit(selectedBranch);
    124125        node.Text = functionNameVisitor.Name;
    125126      }
    126127    }
    127128
    128     private void editButton_Click(object sender, EventArgs e) {
    129       OperatorBaseView operatorView = new OperatorBaseView(selectedFunction.MetaObject);
    130       PluginManager.ControlManager.ShowControl(operatorView);
     129    protected virtual void editButton_Click(object sender, EventArgs e) {
     130      PluginManager.ControlManager.ShowControl(selectedBranch.Function.CreateView());
    131131    }
    132132
     
    136136
    137137      ModelAnalyzerExportVisitor visitor = new ModelAnalyzerExportVisitor();
    138       ((IFunction)node.Tag).Accept(visitor);
     138      visitor.Visit((IFunctionTree)node.Tag);
    139139      Clipboard.SetText(visitor.ModelAnalyzerPrefix);
    140140    }
     
    142142    private class FunctionNameVisitor : IFunctionVisitor {
    143143      string name;
     144      IFunctionTree currentBranch;
    144145
    145146      public string Name {
     
    147148      }
    148149
     150      public void Visit(IFunctionTree tree) {
     151        currentBranch = tree;
     152        tree.Function.Accept(this);
     153      }
     154
    149155      #region IFunctionVisitor Members
    150 
    151156      public void Visit(IFunction function) {
    152157        name = function.Name;
     
    158163
    159164      public void Visit(Constant constant) {
    160         name = constant.Value + "";
     165        name = ((ConstrainedDoubleData)(currentBranch.GetLocalVariable(HeuristicLab.Functions.Constant.VALUE).Value)).Data + "";
    161166      }
    162167
     
    207212      public void Visit(Variable variable) {
    208213        string timeOffset = "";
    209         if(variable.SampleOffset < 0) {
    210           timeOffset = "(t" + variable.SampleOffset + ")";
    211         } else if(variable.SampleOffset > 0) {
    212           timeOffset = "(t+" + variable.SampleOffset + ")";
     214        int sampleOffset = ((ConstrainedIntData)currentBranch.GetLocalVariable(HeuristicLab.Functions.Variable.OFFSET).Value).Data;
     215        int variableIndex = ((ConstrainedIntData)currentBranch.GetLocalVariable(HeuristicLab.Functions.Variable.INDEX).Value).Data;
     216        double weight = ((ConstrainedDoubleData)currentBranch.GetLocalVariable(HeuristicLab.Functions.Variable.WEIGHT).Value).Data;
     217        if(sampleOffset < 0) {
     218          timeOffset = "(t" + sampleOffset + ")";
     219        } else if(sampleOffset > 0) {
     220          timeOffset = "(t+" + sampleOffset + ")";
    213221        } else {
    214222          timeOffset = "";
    215223        }
    216         name = "Var" + variable.VariableIndex + timeOffset + " * " + variable.Weight;
     224        name = "Var" + variableIndex + timeOffset + " * " + weight;
    217225      }
    218226
     
    255263      private string prefix;
    256264      private string currentIndend = "";
     265      private IFunctionTree currentBranch;
    257266      public string ModelAnalyzerPrefix {
    258267        get { return prefix; }
     
    263272
    264273      private void VisitFunction(string name, IFunction f) {
    265         prefix += currentIndend + "[F]"+name+"(\n";
     274        prefix += currentIndend + "[F]" + name + "(\n";
     275      }
     276
     277      #region IFunctionVisitor Members
     278
     279      public void Visit(IFunction function) {
     280        prefix += function.Name;
     281      }
     282
     283      public void Visit(Addition addition) {
     284        VisitFunction("Addition[0]", addition);
     285      }
     286
     287      public void Visit(Constant constant) {
     288        double value = ((ConstrainedDoubleData)currentBranch.GetLocalVariable(HeuristicLab.Functions.Constant.VALUE).Value).Data;
     289        prefix += currentIndend + "[T]Constant(" + value + ";0;0)";
     290      }
     291
     292      public void Visit(Cosinus cosinus) {
     293        VisitFunction("Trigonometrics[1]", cosinus);
     294      }
     295
     296      public void Visit(Division division) {
     297        VisitFunction("Division[0]", division);
     298      }
     299
     300      public void Visit(Exponential exponential) {
     301        VisitFunction("Exponential[0]", exponential);
     302      }
     303
     304      public void Visit(Logarithm logarithm) {
     305        VisitFunction("Logarithm[0]", logarithm);
     306      }
     307
     308      public void Visit(Multiplication multiplication) {
     309        VisitFunction("Multiplication[0]", multiplication);
     310      }
     311
     312      public void Visit(Power power) {
     313        VisitFunction("Power[0]", power);
     314      }
     315
     316      public void Visit(Signum signum) {
     317        VisitFunction("Signum[0]", signum);
     318      }
     319
     320      public void Visit(Sinus sinus) {
     321        VisitFunction("Trigonometrics[0]", sinus);
     322      }
     323
     324      public void Visit(Sqrt sqrt) {
     325        VisitFunction("Sqrt[0]", sqrt);
     326      }
     327
     328      public void Visit(Substraction substraction) {
     329        VisitFunction("Substraction[0]", substraction);
     330      }
     331
     332      public void Visit(Tangens tangens) {
     333        VisitFunction("Trigonometrics[2]", tangens);
     334      }
     335
     336      public void Visit(HeuristicLab.Functions.Variable variable) {
     337        double weight = ((ConstrainedDoubleData)currentBranch.GetLocalVariable(HeuristicLab.Functions.Variable.WEIGHT).Value).Data;
     338        double index = ((ConstrainedIntData)currentBranch.GetLocalVariable(HeuristicLab.Functions.Variable.INDEX).Value).Data;
     339        double offset = ((ConstrainedIntData)currentBranch.GetLocalVariable(HeuristicLab.Functions.Variable.OFFSET).Value).Data;
     340
     341        prefix += currentIndend + "[T]Variable(" + weight + ";" + index + ";" + -offset + ")";
     342      }
     343
     344      public void Visit(And and) {
     345        VisitFunction("Logical[0]", and);
     346      }
     347
     348      public void Visit(Average average) {
     349        VisitFunction("N/A (average)", average);
     350      }
     351
     352      public void Visit(IfThenElse ifThenElse) {
     353        VisitFunction("Conditional[0]", ifThenElse);
     354      }
     355
     356      public void Visit(Not not) {
     357        VisitFunction("Logical[2]", not);
     358      }
     359
     360      public void Visit(Or or) {
     361        VisitFunction("Logical[1]", or);
     362      }
     363
     364      public void Visit(Xor xor) {
     365        VisitFunction("N/A (xor)", xor);
     366      }
     367
     368      public void Visit(Equal equal) {
     369        VisitFunction("Boolean[2]", equal);
     370      }
     371
     372      public void Visit(LessThan lessThan) {
     373        VisitFunction("Boolean[0]", lessThan);
     374      }
     375      #endregion
     376
     377      public void Visit(IFunctionTree functionTree) {
     378        currentBranch = functionTree;
     379        functionTree.Function.Accept(this);
    266380        currentIndend += "  ";
    267         foreach(IFunction subFunction in f.SubFunctions) {
    268           subFunction.Accept(this);
     381        foreach(IFunctionTree subTree in functionTree.SubTrees) {
     382          Visit(subTree);
    269383          prefix += ";\n";
    270384        }
    271         prefix = prefix.TrimEnd(';','\n');
     385        prefix = prefix.TrimEnd(';', '\n');
    272386        prefix += ")";
    273387        currentIndend = currentIndend.Remove(0, 2);
    274388      }
    275 
    276       #region IFunctionVisitor Members
    277 
    278       public void Visit(IFunction function) {
    279         prefix += function.Name;
    280       }
    281 
    282       public void Visit(Addition addition) {
    283         VisitFunction("Addition[0]", addition);
    284       }
    285 
    286       public void Visit(Constant constant) {
    287         prefix += currentIndend + "[T]Constant(" + constant.Value.Data.ToString() + ";0;0)";
    288       }
    289 
    290       public void Visit(Cosinus cosinus) {
    291         VisitFunction("Trigonometrics[1]", cosinus);
    292       }
    293 
    294       public void Visit(Division division) {
    295         VisitFunction("Division[0]", division);
    296       }
    297 
    298       public void Visit(Exponential exponential) {
    299         VisitFunction("Exponential[0]", exponential);
    300       }
    301 
    302       public void Visit(Logarithm logarithm) {
    303         VisitFunction("Logarithm[0]", logarithm);
    304       }
    305 
    306       public void Visit(Multiplication multiplication) {
    307         VisitFunction("Multiplication[0]", multiplication);
    308       }
    309 
    310       public void Visit(Power power) {
    311         VisitFunction("Power[0]", power);
    312       }
    313 
    314       public void Visit(Signum signum) {
    315         VisitFunction("Signum[0]", signum);
    316       }
    317 
    318       public void Visit(Sinus sinus) {
    319         VisitFunction("Trigonometrics[0]", sinus);
    320       }
    321 
    322       public void Visit(Sqrt sqrt) {
    323         VisitFunction("Sqrt[0]", sqrt);
    324       }
    325 
    326       public void Visit(Substraction substraction) {
    327         VisitFunction("Substraction[0]", substraction);
    328       }
    329 
    330       public void Visit(Tangens tangens) {
    331         VisitFunction("Trigonometrics[2]", tangens);
    332       }
    333 
    334       public void Visit(HeuristicLab.Functions.Variable variable) {
    335         prefix += currentIndend + "[T]Variable(" + variable.Weight + ";" + variable.VariableIndex + ";" + -variable.SampleOffset + ")";
    336       }
    337 
    338       public void Visit(And and) {
    339         VisitFunction("Logical[0]", and);
    340       }
    341 
    342       public void Visit(Average average) {
    343         VisitFunction("N/A (average)", average);
    344       }
    345 
    346       public void Visit(IfThenElse ifThenElse) {
    347         VisitFunction("Conditional[0]", ifThenElse);
    348       }
    349 
    350       public void Visit(Not not) {
    351         VisitFunction("Logical[2]", not);
    352       }
    353 
    354       public void Visit(Or or) {
    355         VisitFunction("Logical[1]", or);
    356       }
    357 
    358       public void Visit(Xor xor) {
    359         VisitFunction("N/A (xor)", xor);
    360       }
    361 
    362       public void Visit(Equal equal) {
    363         VisitFunction("Boolean[2]", equal);
    364       }
    365 
    366       public void Visit(LessThan lessThan) {
    367         VisitFunction("Boolean[0]", lessThan);
    368       }
    369 
    370       #endregion
    371     }
    372 
     389    }
    373390  }
    374391}
  • trunk/sources/HeuristicLab.Functions/HeuristicLab.Functions.csproj

    r30 r155  
    5252    <Compile Include="Average.cs" />
    5353    <Compile Include="Constant.cs" />
     54    <Compile Include="FunctionTree.cs" />
     55    <Compile Include="IFunctionTree.cs" />
     56    <Compile Include="ProgrammableFunction.cs" />
    5457    <Compile Include="Equal.cs" />
    5558    <Compile Include="FunctionView.cs">
     
    99102      <Name>HeuristicLab.Data</Name>
    100103    </ProjectReference>
     104    <ProjectReference Include="..\HeuristicLab.Operators.Programmable\HeuristicLab.Operators.Programmable.csproj">
     105      <Project>{E3CCBFC6-900C-41B6-AFB8-6646DB097435}</Project>
     106      <Name>HeuristicLab.Operators.Programmable</Name>
     107    </ProjectReference>
    101108    <ProjectReference Include="..\HeuristicLab.PluginInfrastructure\HeuristicLab.PluginInfrastructure.csproj">
    102109      <Project>{94186A6A-5176-4402-AE83-886557B53CCA}</Project>
  • trunk/sources/HeuristicLab.Functions/IFunction.cs

    r2 r155  
    2828namespace HeuristicLab.Functions {
    2929  public interface IFunction : IOperator {
    30     IList<IFunction> SubFunctions { get;}
    31     ICollection<IVariable> LocalVariables { get; }
    32     IFunction MetaObject { get; }
    33     double Evaluate(Dataset dataset, int sampleIndex);
     30    double Evaluate(Dataset dataset, int sampleIndex, IFunctionTree tree);
     31    double Apply(Dataset dataset, int sampleIndex, double[] args);
    3432    void Accept(IFunctionVisitor visitor);
    3533  }
  • trunk/sources/HeuristicLab.Functions/IfThenElse.cs

    r2 r155  
    3131    public override string Description {
    3232      get {
    33         return @"Returns the result of the second branch if the first branch evaluates to a value >= 0.5 and the result
    34 of the third branch if the first branch evaluates to < 0.5.";
     33        return @"Returns the result of the second sub-tree if the first sub-tree evaluates to a value < 0.5 and the result
     34of the third sub-tree if the first sub-tree evaluates to >= 0.5.";
    3535      }
    3636    }
     
    4141    }
    4242
    43     public IfThenElse(IfThenElse source, IDictionary<Guid, object> clonedObjects)
    44       : base(source, clonedObjects) {
    45     }
    46 
    47 
    48     public override double Evaluate(Dataset dataset, int sampleIndex) {
    49       double condition = Math.Round(SubFunctions[0].Evaluate(dataset, sampleIndex));
    50       if(condition >= .5) return SubFunctions[2].Evaluate(dataset, sampleIndex);
    51       else if(condition < .5) return SubFunctions[1].Evaluate(dataset, sampleIndex);
     43    // special form
     44    public override double Evaluate(Dataset dataset, int sampleIndex, IFunctionTree tree) {
     45      double condition = Math.Round(tree.SubTrees[0].Evaluate(dataset, sampleIndex));
     46      if(condition < .5) return tree.SubTrees[1].Evaluate(dataset, sampleIndex);
     47      else if(condition >= .5) return tree.SubTrees[2].Evaluate(dataset, sampleIndex);
    5248      else return double.NaN;
    5349    }
    5450
    55     public override object Clone(IDictionary<Guid, object> clonedObjects) {
    56       IfThenElse clone = new IfThenElse(this, clonedObjects);
    57       clonedObjects.Add(clone.Guid, clone);
    58       return clone;
     51    public override double Apply(Dataset dataset, int sampleIndex, double[] args) {
     52      throw new NotImplementedException();
    5953    }
    6054
  • trunk/sources/HeuristicLab.Functions/LessThan.cs

    r2 r155  
    3131    public override string Description {
    3232      get {
    33         return @"Less-than condition. Returns 1.0 if the value of the first sub-function is less than the value of the second sub-function and 0.0 otherwise.";
     33        return @"Less-than condition. Returns 1.0 if the value of the first sub-tree is less than the value of the second sub-tree and 0.0 otherwise.";
    3434      }
    3535    }
     
    4040    }
    4141
    42     public LessThan(LessThan source, IDictionary<Guid, object> clonedObjects)
    43       : base(source, clonedObjects) {
    44     }
    45 
    46 
    47     public override double Evaluate(Dataset dataset, int sampleIndex) {
    48       if(SubFunctions[0].Evaluate(dataset, sampleIndex) < SubFunctions[1].Evaluate(dataset, sampleIndex)) return 1.0;
     42    public override double Apply(Dataset dataset, int sampleIndex, double[] args) {
     43      if(args[0] < args[1]) return 1.0;
    4944      else return 0.0;
    50     }
    51 
    52     public override object Clone(IDictionary<Guid, object> clonedObjects) {
    53       LessThan clone = new LessThan(this, clonedObjects);
    54       clonedObjects.Add(clone.Guid, clone);
    55       return clone;
    5645    }
    5746
  • trunk/sources/HeuristicLab.Functions/Logarithm.cs

    r2 r155  
    3131  public class Logarithm : FunctionBase {
    3232    public override string Description {
    33       get { return "Returns the natural (base e) logarithm of the first sub-operator."; }
     33      get { return "Returns the natural (base e) logarithm of the first sub-tree."; }
    3434    }
    3535
     
    4040    }
    4141
    42     public Logarithm(Logarithm source, IDictionary<Guid, object> clonedObjects)
    43       : base(source, clonedObjects) {
    44     }
    45 
    46     public override object Clone(IDictionary<Guid, object> clonedObjects) {
    47       Logarithm clone = new Logarithm(this, clonedObjects);
    48       clonedObjects.Add(clone.Guid, clone);
    49       return clone;
    50     }
    51 
    52     public override double Evaluate(Dataset dataset, int sampleIndex) {
    53       return Math.Log(SubFunctions[0].Evaluate(dataset, sampleIndex));
     42    public override double Apply(Dataset dataset, int sampleIndex, double[] args) {
     43      return Math.Log(args[0]);
    5444    }
    5545
  • trunk/sources/HeuristicLab.Functions/Multiplication.cs

    r2 r155  
    3333    public override string Description {
    3434      get {
    35         return @"Returns the product of the results of all sub-operators.
     35        return @"Returns the product of the results of all sub-tree.
    3636  (* 3) => 3
    3737  (* 2 3) => 6
     
    4646    }
    4747
    48     public Multiplication(Multiplication source, IDictionary<Guid, object> clonedObjects)
    49       : base(source, clonedObjects) {
    50     }
    51 
    52 
    53     public override double Evaluate(Dataset dataset, int sampleIndex) {
     48    public override double Apply(Dataset dataset, int sampleIndex, double[] args) {
    5449      // (* 3) => 3
    5550      // (* 2 3) => 6
    5651      // (* 3 4 5) => 60
    5752      double result = 1.0;
    58       for(int i = SubFunctions.Count - 1; i >= 0; i--) {
    59         result *= SubFunctions[i].Evaluate(dataset, sampleIndex);
     53      for(int i = 0; i < args.Length; i++) {
     54        result *= args[i];
    6055      }
    6156      return result;
    62     }
    63 
    64     public override object Clone(IDictionary<Guid, object> clonedObjects) {
    65       Multiplication clone = new Multiplication(this, clonedObjects);
    66       clonedObjects.Add(clone.Guid, clone);
    67       return clone;
    6857    }
    6958
  • trunk/sources/HeuristicLab.Functions/Not.cs

    r2 r155  
    3131    public override string Description {
    3232      get {
    33         return @"Logical NOT operation. Only defined for sub-operator-results 0.0 and 1.0.";
     33        return @"Logical NOT operation. Only defined for sub-tree-results 0.0 and 1.0.";
    3434      }
    3535    }
     
    4040    }
    4141
    42     public Not(Not source, IDictionary<Guid, object> clonedObjects)
    43       : base(source, clonedObjects) {
    44     }
    45 
    46 
    47     public override double Evaluate(Dataset dataset, int sampleIndex) {
    48       double result = Math.Round(SubFunctions[0].Evaluate(dataset, sampleIndex));
     42    public override double Apply(Dataset dataset, int sampleIndex, double[] args) {
     43      double result = Math.Round(args[0]);
    4944      if(result == 0.0) return 1.0;
    5045      else if(result == 1.0) return 0.0;
    5146      else return double.NaN;
    52     }
    53 
    54     public override object Clone(IDictionary<Guid, object> clonedObjects) {
    55       Not clone = new Not(this, clonedObjects);
    56       clonedObjects.Add(clone.Guid, clone);
    57       return clone;
    5847    }
    5948
  • trunk/sources/HeuristicLab.Functions/Or.cs

    r2 r155  
    3131    public override string Description {
    3232      get {
    33         return @"Logical OR operation. Only defined for sub-operator-results 0.0 and 1.0.";
     33        return @"Logical OR operation. Only defined for sub-tree-results 0.0 and 1.0.
     34Special form, evaluation stops at first sub-tree that evaluates to 1.0 (true).";
    3435      }
    3536    }
     
    4041    }
    4142
    42     public Or(Or source, IDictionary<Guid, object> clonedObjects)
    43       : base(source, clonedObjects) {
    44     }
    45 
    46 
    47     public override double Evaluate(Dataset dataset, int sampleIndex) {
    48       foreach(IFunction subFunction in SubFunctions) {
    49         double result = Math.Round(subFunction.Evaluate(dataset, sampleIndex));
    50         if(result == 1.0) return 1.0;
     43    public override double Evaluate(Dataset dataset, int sampleIndex, IFunctionTree tree) {
     44      foreach(IFunctionTree subTree in tree.SubTrees) {
     45        double result = Math.Round(subTree.Evaluate(dataset, sampleIndex));
     46        if(result == 1.0) return 1.0; // sub-tree evaluates to 1.0 (true) return 1.0
    5147        else if(result != 0.0) return double.NaN;
    5248      }
     49      // all sub-trees evaluated to 0.0 (false) return false
    5350      return 0.0;
    5451    }
    5552
    56     public override object Clone(IDictionary<Guid, object> clonedObjects) {
    57       Or clone = new Or(this, clonedObjects);
    58       clonedObjects.Add(clone.Guid, clone);
    59       return clone;
     53    public override double Apply(Dataset dataset, int sampleIndex, double[] args) {
     54      throw new NotImplementedException();
    6055    }
    61 
    6256    public override void Accept(IFunctionVisitor visitor) {
    6357      visitor.Visit(this);
  • trunk/sources/HeuristicLab.Functions/Power.cs

    r2 r155  
    3131  public class Power : FunctionBase {
    3232    public override string Description {
    33       get { return "Returns the result of the first sub-operator to the power of the second sub-operator (power(x, y))."; }
     33      get { return "Returns the result of the first sub-tree to the power of the second sub-tree (power(x, y))."; }
    3434    }
    3535
     
    4040    }
    4141
    42     public Power(Power source, IDictionary<Guid, object> clonedObjects)
    43       : base(source, clonedObjects) {
     42    public override double Apply(Dataset dataset, int sampleIndex, double[] args) {
     43      return Math.Pow(args[0], args[1]);
    4444    }
    45 
    46 
    47     public override double Evaluate(Dataset dataset, int sampleIndex) {
    48       return Math.Pow(SubFunctions[0].Evaluate(dataset, sampleIndex), SubFunctions[1].Evaluate(dataset, sampleIndex));
    49     }
    50 
    51     public override object Clone(IDictionary<Guid, object> clonedObjects) {
    52       Power clone = new Power(this, clonedObjects);
    53       clonedObjects.Add(clone.Guid, clone);
    54       return clone;
    55     }
    56 
    5745
    5846    public override void Accept(IFunctionVisitor visitor) {
  • trunk/sources/HeuristicLab.Functions/Signum.cs

    r2 r155  
    3131  public class Signum : FunctionBase {
    3232    public override string Description {
    33       get { return "Returns the signum of the first sub-operator."; }
     33      get { return "Returns the signum of the first sub-tree."; }
    3434    }
    3535
     
    4040    }
    4141
    42     public Signum(Signum source, IDictionary<Guid, object> clonedObjects)
    43       : base(source, clonedObjects) {
    44     }
    45 
    46 
    47     public override double Evaluate(Dataset dataset, int sampleIndex) {
    48       double value = SubFunctions[0].Evaluate(dataset, sampleIndex);
     42    public override double Apply(Dataset dataset, int sampleIndex, double[] args) {
     43      double value = args[0];
    4944      if(value < 0) return -1;
    5045      if(value > 0) return 1;
    5146      return 0;
    5247    }
    53 
    54     public override object Clone(IDictionary<Guid, object> clonedObjects) {
    55       Signum clone = new Signum(this, clonedObjects);
    56       clonedObjects.Add(clone.Guid, clone);
    57       return clone;
    58     }
    59 
    6048
    6149    public override void Accept(IFunctionVisitor visitor) {
  • trunk/sources/HeuristicLab.Functions/Sinus.cs

    r2 r155  
    3131  public class Sinus : FunctionBase {
    3232    public override string Description {
    33       get { return "Returns the sinus of the first sub-operator."; }
     33      get { return "Returns the sinus of the first sub-tree."; }
    3434    }
    3535
     
    4040    }
    4141
    42     public Sinus(Sinus source, IDictionary<Guid, object> clonedObjects)
    43       : base(source, clonedObjects) {
     42    public override double Apply(Dataset dataset, int sampleIndex, double[] args) {
     43      return Math.Sin(args[0]);
    4444    }
    45 
    46 
    47     public override double Evaluate(Dataset dataset, int sampleIndex) {
    48       return Math.Sin(SubFunctions[0].Evaluate(dataset, sampleIndex));
    49     }
    50 
    51     public override object Clone(IDictionary<Guid, object> clonedObjects) {
    52       Sinus clone = new Sinus(this, clonedObjects);
    53       clonedObjects.Add(clone.Guid, clone);
    54       return clone;
    55     }
    56 
    5745
    5846    public override void Accept(IFunctionVisitor visitor) {
  • trunk/sources/HeuristicLab.Functions/Sqrt.cs

    r2 r155  
    3131  public class Sqrt : FunctionBase {
    3232    public override string Description {
    33       get { return "Returns the square root of the first sub-operator."; }
     33      get { return "Returns the square root of the first sub-tree."; }
    3434    }
    3535
     
    4040    }
    4141
    42     public Sqrt(Sqrt source, IDictionary<Guid, object> clonedObjects)
    43       : base(source, clonedObjects) {
     42
     43    public override double Apply(Dataset dataset, int sampleIndex, double[] args) {
     44      return Math.Sqrt(args[0]);
    4445    }
    45 
    46 
    47     public override double Evaluate(Dataset dataset, int sampleIndex) {
    48       return Math.Sqrt(SubFunctions[0].Evaluate(dataset, sampleIndex));
    49     }
    50 
    51     public override object Clone(IDictionary<Guid, object> clonedObjects) {
    52       Sqrt clone = new Sqrt(this, clonedObjects);
    53       clonedObjects.Add(clone.Guid, clone);
    54       return clone;
    55     }
    56 
    5746
    5847    public override void Accept(IFunctionVisitor visitor) {
  • trunk/sources/HeuristicLab.Functions/Substraction.cs

    r2 r155  
    3333    public override string Description {
    3434      get {
    35         return @"Substracts the results of sub-operators 2..n from the result of the first sub-operator.
     35        return @"Substracts the results of sub-tree 2..n from the result of the first sub-tree.
    3636    (- 3) => -3
    3737    (- 2 3) => -1
     
    4646    }
    4747
    48     public Substraction(Substraction source, IDictionary<Guid, object> clonedObjects)
    49       : base(source, clonedObjects) {
    50     }
    5148
    52 
    53     public override double Evaluate(Dataset dataset, int sampleIndex) {
    54 
    55       if(SubFunctions.Count == 1) {
    56         return -SubFunctions[0].Evaluate(dataset, sampleIndex);
     49    public override double Apply(Dataset dataset, int sampleIndex, double[] args) {
     50      if(args.Length == 1) {
     51        return -args[0];
    5752      } else {
    58         double result = SubFunctions[0].Evaluate(dataset, sampleIndex);
    59         for(int i = 1; i < SubFunctions.Count; i++) {
    60           result -= SubFunctions[i].Evaluate(dataset, sampleIndex);
     53        double result = args[0];
     54        for(int i = 1; i < args.Length; i++) {
     55          result -= args[i];
    6156        }
    6257        return result;
    6358      }
    64     }
    65 
    66     public override object Clone(IDictionary<Guid, object> clonedObjects) {
    67       Substraction clone = new Substraction(this, clonedObjects);
    68       clonedObjects.Add(clone.Guid, clone);
    69       return clone;
    7059    }
    7160
  • trunk/sources/HeuristicLab.Functions/Tangens.cs

    r2 r155  
    3131  public class Tangens : FunctionBase {
    3232    public override string Description {
    33       get { return "Returns the tangens of the first sub-operator."; }
     33      get { return "Returns the tangens of the first sub-tree."; }
    3434    }
    3535
     
    4040    }
    4141
    42     public Tangens(Tangens source, IDictionary<Guid, object> clonedObjects)
    43       : base(source, clonedObjects) {
     42    public override double Apply(Dataset dataset, int sampleIndex, double[] args) {
     43      return Math.Tan(args[0]);
    4444    }
    45 
    46     public override double Evaluate(Dataset dataset, int sampleIndex) {
    47       return Math.Tan(SubFunctions[0].Evaluate(dataset, sampleIndex));
    48     }
    49 
    50     public override object Clone(IDictionary<Guid, object> clonedObjects) {
    51       Tangens clone = new Tangens(this, clonedObjects);
    52       clonedObjects.Add(clone.Guid, clone);
    53       return clone;
    54     }
    55 
    5645
    5746    public override void Accept(IFunctionVisitor visitor) {
  • trunk/sources/HeuristicLab.Functions/Variable.cs

    r133 r155  
    3232  public class Variable : FunctionBase {
    3333
    34     private ConstrainedIntData variable;
    35     private ConstrainedDoubleData weight;
    36     private ConstrainedIntData sampleOffset;
    37 
    38     public double SampleOffset {
    39       get { return sampleOffset.Data; }
    40     }
    41 
    42     public int VariableIndex {
    43       get { return variable.Data; }
    44     }
    45 
    46     public double Weight {
    47       get { return weight.Data; }
    48     }
     34    public static readonly string WEIGHT = "Weight";
     35    public static readonly string OFFSET = "SampleOffset";
     36    public static readonly string INDEX = "Variable";
    4937
    5038    public override string Description {
     
    5644    public Variable()
    5745      : base() {
    58       AddVariableInfo(new VariableInfo("Variable", "Index of the variable in the dataset representing this feature", typeof(ConstrainedIntData), VariableKind.None));
    59       GetVariableInfo("Variable").Local = true;
    60       AddVariableInfo(new VariableInfo("Weight", "Weight is multiplied to the feature value", typeof(ConstrainedDoubleData), VariableKind.None));
    61       GetVariableInfo("Weight").Local = true;
    62       AddVariableInfo(new VariableInfo("SampleOffset", "SampleOffset is added to the sample index", typeof(ConstrainedIntData), VariableKind.None));
    63       GetVariableInfo("SampleOffset").Local = true;
     46      AddVariableInfo(new VariableInfo(INDEX, "Index of the variable in the dataset representing this feature", typeof(ConstrainedIntData), VariableKind.None));
     47      GetVariableInfo(INDEX).Local = true;
     48      AddVariableInfo(new VariableInfo(WEIGHT, "Weight is multiplied to the feature value", typeof(ConstrainedDoubleData), VariableKind.None));
     49      GetVariableInfo(WEIGHT).Local = true;
     50      AddVariableInfo(new VariableInfo(OFFSET, "SampleOffset is added to the sample index", typeof(ConstrainedIntData), VariableKind.None));
     51      GetVariableInfo(OFFSET).Local = true;
    6452
    65       variable = new ConstrainedIntData();
    66       AddLocalVariable(new HeuristicLab.Core.Variable("Variable", variable));
    67 
    68       weight = new ConstrainedDoubleData();
     53      ConstrainedDoubleData weight = new ConstrainedDoubleData();
    6954      // initialize a totally arbitrary range for the weight = [-20.0, 20.0]
    7055      weight.AddConstraint(new DoubleBoundedConstraint(-20.0, 20.0));
    71       AddLocalVariable(new HeuristicLab.Core.Variable("Weight", weight));
     56      AddVariable(new HeuristicLab.Core.Variable(WEIGHT, weight));
    7257
    73       sampleOffset = new ConstrainedIntData();
     58      ConstrainedIntData variable = new ConstrainedIntData();
     59      AddVariable(new HeuristicLab.Core.Variable(INDEX, variable));
     60
     61      ConstrainedIntData sampleOffset = new ConstrainedIntData();
    7462      // initialize a totally arbitrary default range for sampleoffset = [-10, 10]
    7563      sampleOffset.AddConstraint(new IntBoundedConstraint(0, 0));
    76       AddLocalVariable(new HeuristicLab.Core.Variable("SampleOffset", sampleOffset));
     64      AddVariable(new HeuristicLab.Core.Variable(OFFSET, sampleOffset));
    7765
    78       // samplefeature can't have suboperators
     66      // variable can't have suboperators
    7967      AddConstraint(new NumberOfSubOperatorsConstraint(0, 0));
    8068    }
    8169
    82     public Variable(Variable source, IDictionary<Guid, object> clonedObjects)
    83       : base(source, clonedObjects) {
     70    // variable can be evaluated directly
     71    // evaluation reads local variables weight, index, offset from function-tree and returns the variable-value * weight
     72    public override double Evaluate(Dataset dataset, int sampleIndex, IFunctionTree tree) {
     73      double w = ((ConstrainedDoubleData)tree.GetLocalVariable(WEIGHT).Value).Data;
     74      int v = ((ConstrainedIntData)tree.GetLocalVariable(INDEX).Value).Data;
     75      int offset = ((ConstrainedIntData)tree.GetLocalVariable(OFFSET).Value).Data;
    8476
    85       variable = (ConstrainedIntData)GetVariable("Variable").Value;
    86       weight = (ConstrainedDoubleData)GetVariable("Weight").Value;
    87       sampleOffset = (ConstrainedIntData)GetVariable("SampleOffset").Value;
     77      if(sampleIndex + offset < 0 || sampleIndex + offset >= dataset.Rows) return double.NaN;
     78      return w * dataset.GetValue(sampleIndex + offset, v);
    8879    }
    8980
    90     public override object Clone(IDictionary<Guid, object> clonedObjects) {
    91       Variable clone = new Variable(this, clonedObjects);
    92       clonedObjects.Add(clone.Guid, clone);
    93       return clone;
    94     }
    95 
    96     public override void Populate(System.Xml.XmlNode node, IDictionary<Guid, IStorable> restoredObjects) {
    97       base.Populate(node, restoredObjects);
    98 
    99       variable = (ConstrainedIntData)GetVariable("Variable").Value;
    100       weight = (ConstrainedDoubleData)GetVariable("Weight").Value;
    101       sampleOffset = (ConstrainedIntData)GetVariable("SampleOffset").Value;
    102     }
    103 
    104 
    105     public override double Evaluate(Dataset dataset, int sampleIndex) {
    106       // local variables
    107       int v = variable.Data;
    108       double w = weight.Data;
    109       int offset = sampleOffset.Data;
    110 
    111       if(sampleIndex+offset<0 || sampleIndex+offset>=dataset.Rows) return double.NaN;
    112       return w * dataset.GetValue(sampleIndex + offset, v);
     81    // can't apply a variable
     82    public override double Apply(Dataset dataset, int sampleIndex, double[] args) {
     83      throw new NotSupportedException();
    11384    }
    11485
  • trunk/sources/HeuristicLab.Functions/Xor.cs

    r2 r155  
    3131    public override string Description {
    3232      get {
    33         return @"Logical XOR operation. Only defined for sub-operator-results 0.0 and 1.0.";
     33        return @"Logical XOR operation. Only defined for sub-tree-results 0.0 and 1.0.";
    3434      }
    3535    }
     
    4040    }
    4141
    42     public Xor(Xor source, IDictionary<Guid, object> clonedObjects)
    43       : base(source, clonedObjects) {
    44     }
    45 
    46 
    47     public override double Evaluate(Dataset dataset, int sampleIndex) {
    48       double r0 = Math.Round(SubFunctions[0].Evaluate(dataset, sampleIndex));
    49       double r1 = Math.Round(SubFunctions[1].Evaluate(dataset, sampleIndex));
    50       if((r0 == 0.0 && r1 == 0.0) ||
    51         (r0 == 1.0 && r1 == 1.0)) return 0.0;
    52       else if((r0 == 0.0 && r1 == 1.0) ||
    53         (r0 == 1.0 && r1 == 0.0)) return 1.0;
    54       else return double.NaN;
    55     }
    56 
    57     public override object Clone(IDictionary<Guid, object> clonedObjects) {
    58       Xor clone = new Xor(this, clonedObjects);
    59       clonedObjects.Add(clone.Guid, clone);
    60       return clone;
     42    public override double Apply(Dataset dataset, int sampleIndex, double[] args) {
     43      if(args[0] == 0.0 && args[1] == 0.0) return 0.0;
     44      if(args[0] * args[1] == 0.0) return 1.0;
     45      return 0.0;
    6146    }
    6247
  • trunk/sources/HeuristicLab.StructureIdentification/Evaluation/CoefficientOfDeterminationEvaluator.cs

    r128 r155  
    3434    public override string Description {
    3535      get {
    36         return @"Applies 'OperatorTree' to all samples of 'Dataset' and calculates
     36        return @"Evaluates 'FunctionTree' for all samples of 'Dataset' and calculates
    3737the 'coefficient of determination' of estimated values vs. real values of 'TargetVariable'.";
    3838      }
     
    4343    }
    4444
    45     public override double Evaluate(IScope scope, IFunction function, int targetVariable, Dataset dataset) {
     45    public override double Evaluate(IScope scope, IFunctionTree functionTree, int targetVariable, Dataset dataset) {
    4646      double errorsSquaredSum = 0.0;
    4747      double originalDeviationTotalSumOfSquares = 0.0;
    4848      double targetMean = dataset.GetMean(targetVariable);
    4949      for(int sample = 0; sample < dataset.Rows; sample++) {
    50         double estimated = function.Evaluate(dataset, sample);
     50        double estimated = functionTree.Evaluate(dataset, sample);
    5151        double original = dataset.GetValue(sample, targetVariable);
    5252        if(!double.IsNaN(original) && !double.IsInfinity(original)) {
  • trunk/sources/HeuristicLab.StructureIdentification/Evaluation/EarlyStoppingMeanSquaredErrorEvaluator.cs

    r136 r155  
    3434    public override string Description {
    3535      get {
    36         return @"Evaluates 'OperatorTree' for all samples of the dataset and calculates the mean-squared-error
     36        return @"Evaluates 'FunctionTree' for all samples of the dataset and calculates the mean-squared-error
    3737for the estimated values vs. the real values of 'TargetVariable'.
    3838This operator stops the computation as soon as an upper limit for the mean-squared-error is reached.";
     
    4545    }
    4646
    47     public override double Evaluate(IScope scope, IFunction function, int targetVariable, Dataset dataset) {
     47    public override double Evaluate(IScope scope, IFunctionTree functionTree, int targetVariable, Dataset dataset) {
    4848      double qualityLimit = GetVariableValue<DoubleData>("QualityLimit", scope, false).Data;
    4949      double errorsSquaredSum = 0;
    5050      double targetMean = dataset.GetMean(targetVariable);
    5151      for(int sample = 0; sample < dataset.Rows; sample++) {
    52         double estimated = function.Evaluate(dataset, sample);
     52        double estimated = functionTree.Evaluate(dataset, sample);
    5353        double original = dataset.GetValue(sample, targetVariable);
    5454        if(double.IsNaN(estimated) || double.IsInfinity(estimated)) {
  • trunk/sources/HeuristicLab.StructureIdentification/Evaluation/GPEvaluatorBase.cs

    r135 r155  
    3636    public GPEvaluatorBase()
    3737      : base() {
    38       AddVariableInfo(new VariableInfo("OperatorTree", "The function tree that should be evaluated", typeof(IFunction), VariableKind.In));
     38      AddVariableInfo(new VariableInfo("FunctionTree", "The function tree that should be evaluated", typeof(IFunctionTree), VariableKind.In));
    3939      AddVariableInfo(new VariableInfo("Dataset", "Dataset with all samples on which to apply the function", typeof(Dataset), VariableKind.In));
    4040      AddVariableInfo(new VariableInfo("TargetVariable", "Index of the column of the dataset that holds the target variable", typeof(IntData), VariableKind.In));
     
    4646      int targetVariable = GetVariableValue<IntData>("TargetVariable", scope, true).Data;
    4747      Dataset dataset = GetVariableValue<Dataset>("Dataset", scope, true);
    48       IFunction function = GetVariableValue<IFunction>("OperatorTree", scope, true);
     48      IFunctionTree functionTree = GetVariableValue<IFunctionTree>("FunctionTree", scope, true);
    4949      this.maximumPunishment = GetVariableValue<DoubleData>("PunishmentFactor", scope, true).Data * dataset.GetRange(targetVariable);
    5050
    51       double result = Evaluate(scope, function, targetVariable, dataset);
     51      double result = Evaluate(scope, functionTree, targetVariable, dataset);
    5252      scope.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("Quality"), new DoubleData(result)));
    5353      return null;
    5454    }
    5555
    56     public abstract double Evaluate(IScope scope, IFunction function, int targetVariable, Dataset dataset);
     56    public abstract double Evaluate(IScope scope, IFunctionTree functionTree, int targetVariable, Dataset dataset);
    5757  }
    5858}
  • trunk/sources/HeuristicLab.StructureIdentification/Evaluation/MeanSquaredErrorEvaluator.cs

    r128 r155  
    3434    public override string Description {
    3535      get {
    36         return @"Evaluates 'OperatorTree' for all samples of 'DataSet' and calculates the mean-squared-error
     36        return @"Evaluates 'FunctionTree' for all samples of 'DataSet' and calculates the mean-squared-error
    3737for the estimated values vs. the real values of 'TargetVariable'.";
    3838      }
     
    4343    }
    4444
    45     public override double Evaluate(IScope scope, IFunction function, int targetVariable, Dataset dataset) {
     45    public override double Evaluate(IScope scope, IFunctionTree functionTree, int targetVariable, Dataset dataset) {
    4646      double errorsSquaredSum = 0;
    4747      double targetMean = dataset.GetMean(targetVariable);
    4848      for(int sample = 0; sample < dataset.Rows; sample++) {
    49         double estimated = function.Evaluate(dataset, sample);
     49
     50        double estimated = functionTree.Evaluate(dataset, sample);
    5051        double original = dataset.GetValue(sample, targetVariable);
    5152        if(double.IsNaN(estimated) || double.IsInfinity(estimated)) {
  • trunk/sources/HeuristicLab.StructureIdentification/Evaluation/VarianceAccountedForEvaluator.cs

    r128 r155  
    3434    public override string Description {
    3535      get {
    36         return @"Evaluates 'OperatorTree' for all samples of 'DataSet' and calculates
     36        return @"Evaluates 'FunctionTree' for all samples of 'DataSet' and calculates
    3737the variance-accounted-for quality measure for the estimated values vs. the real values of 'TargetVariable'.
    3838
     
    5353
    5454
    55     public override double Evaluate(IScope scope, IFunction function, int targetVariable, Dataset dataset) {
     55    public override double Evaluate(IScope scope, IFunctionTree functionTree, int targetVariable, Dataset dataset) {
    5656      double[] errors = new double[dataset.Rows];
    5757      double[] originalTargetVariableValues = new double[dataset.Rows];
    5858      double targetMean = dataset.GetMean(targetVariable);
    5959      for(int sample = 0; sample < dataset.Rows; sample++) {
    60         double estimated = function.Evaluate(dataset, sample);
     60        double estimated = functionTree.Evaluate(dataset, sample);
    6161        double original = dataset.GetValue(sample, targetVariable);
    6262        if(!double.IsNaN(original) && !double.IsInfinity(original)) {
  • trunk/sources/HeuristicLab.StructureIdentification/GPOperatorGroup.cs

    r2 r155  
    3232namespace HeuristicLab.StructureIdentification {
    3333  public class GPOperatorGroup : OperatorGroup {
    34 
    3534    public GPOperatorGroup()
    3635      : base() {
     
    118117      int maxArity;
    119118      GetMinMaxArity(op, out minArity, out maxArity);
    120       ItemList slotsList = (ItemList)op.GetVariable(GPOperatorLibrary.ALLOWED_SUBOPERATORS).Value;
     119      var slotsList = (ItemList)op.GetVariable(GPOperatorLibrary.ALLOWED_SUBOPERATORS).Value;
    121120      slotsList.Clear();
    122121      for(int i = 0; i < maxArity; i++) {
     
    276275    }
    277276
    278 
    279277    public override void AddSubGroup(IOperatorGroup group) {
    280278      throw new NotSupportedException();
  • trunk/sources/HeuristicLab.StructureIdentification/HeuristicLab.StructureIdentification.csproj

    r128 r155  
    6767    <Compile Include="Manipulation\OnePointShaker.cs" />
    6868    <Compile Include="Manipulation\SubstituteSubTreeManipulation.cs" />
    69     <Compile Include="PopulationAnalyser.cs" />
    7069    <Compile Include="HeuristicLabStructureIdentificationPlugin.cs" />
    7170    <Compile Include="Properties\AssemblyInfo.cs" />
  • trunk/sources/HeuristicLab.StructureIdentification/Manipulation/ChangeNodeTypeManipulation.cs

    r23 r155  
    2929using HeuristicLab.Data;
    3030using HeuristicLab.Constraints;
     31using HeuristicLab.Functions;
    3132
    3233namespace HeuristicLab.StructureIdentification {
     
    3940      AddVariableInfo(new VariableInfo("MaxTreeSize", "The maximal allowed size (number of nodes) of the tree", typeof(IntData), VariableKind.In));
    4041      AddVariableInfo(new VariableInfo("BalancedTreesRate", "Determines how many trees should be balanced", typeof(DoubleData), VariableKind.In));
    41       AddVariableInfo(new VariableInfo("OperatorTree", "The tree to mutate", typeof(IOperator), VariableKind.In));
    42       AddVariableInfo(new VariableInfo("TreeSize", "The size (number of nodes) of the tree", typeof(IntData), VariableKind.In));
    43       AddVariableInfo(new VariableInfo("TreeHeight", "The height of the tree", typeof(IntData), VariableKind.In));
     42      AddVariableInfo(new VariableInfo("FunctionTree", "The tree to mutate", typeof(IFunctionTree), VariableKind.In | VariableKind.Out));
     43      AddVariableInfo(new VariableInfo("TreeSize", "The size (number of nodes) of the tree", typeof(IntData), VariableKind.In | VariableKind.Out));
     44      AddVariableInfo(new VariableInfo("TreeHeight", "The height of the tree", typeof(IntData), VariableKind.In | VariableKind.Out));
    4445    }
    4546
    4647
    4748    public override IOperation Apply(IScope scope) {
    48       IOperator rootOperator = GetVariableValue<IOperator>("OperatorTree", scope, false);
     49      IFunctionTree root = GetVariableValue<IFunctionTree>("FunctionTree", scope, false);
    4950      MersenneTwister random = GetVariableValue<MersenneTwister>("Random", scope, true);
    5051      GPOperatorLibrary library = GetVariableValue<GPOperatorLibrary>("OperatorLibrary", scope, true);
     
    5657
    5758      TreeGardener gardener = new TreeGardener(random, library);
    58 
    59       IOperator parent = gardener.GetRandomParentNode(rootOperator);
    60 
    61       IOperator selectedChild;
     59      IFunctionTree parent = gardener.GetRandomParentNode(root);
     60
     61      IFunctionTree selectedChild;
    6262      int selectedChildIndex;
    6363      if (parent == null) {
    6464        selectedChildIndex = 0;
    65         selectedChild = rootOperator;
     65        selectedChild = root;
    6666      } else {
    67         selectedChildIndex = random.Next(parent.SubOperators.Count);
    68         selectedChild = parent.SubOperators[selectedChildIndex];
    69       }
    70 
    71       if (selectedChild.SubOperators.Count == 0) {
    72         IOperator newTerminal = ChangeTerminalType(parent, selectedChild, selectedChildIndex, gardener, random);
     67        selectedChildIndex = random.Next(parent.SubTrees.Count);
     68        selectedChild = parent.SubTrees[selectedChildIndex];
     69      }
     70
     71      if (selectedChild.SubTrees.Count == 0) {
     72        IFunctionTree newTerminal = ChangeTerminalType(parent, selectedChild, selectedChildIndex, gardener, random);
    7373
    7474        if (parent == null) {
    7575          // no parent means the new child is the initial operator
    7676          // and we have to update the value in the variable
    77           scope.GetVariable("OperatorTree").Value = newTerminal;
     77          scope.GetVariable(scope.TranslateName("FunctionTree")).Value = newTerminal;
    7878        } else {
    79           parent.RemoveSubOperator(selectedChildIndex);
    80           parent.AddSubOperator(newTerminal, selectedChildIndex);
     79          parent.RemoveSubTree(selectedChildIndex);
     80          parent.InsertSubTree(selectedChildIndex, newTerminal);
    8181          // updating the variable is not necessary because it stays the same
    8282        }
     83        if(!gardener.IsValidTree(root)) throw new InvalidProgramException();
    8384
    8485        // size and height stays the same when changing a terminal so no need to update the variables
    8586        // schedule an operation to initialize the new terminal
    86         return gardener.CreateInitializationOperation(gardener.GetAllOperators(newTerminal), scope);
     87        return gardener.CreateInitializationOperation(gardener.GetAllSubTrees(newTerminal), scope);
    8788      } else {
    88         List<IOperator> uninitializedOperators;
    89         IOperator newFunction = ChangeFunctionType(parent, selectedChild, selectedChildIndex, gardener, random, balancedTreesRate, out uninitializedOperators);
     89        List<IFunctionTree> uninitializedBranches;
     90        IFunctionTree newFunction = ChangeFunctionType(parent, selectedChild, selectedChildIndex, gardener, random, balancedTreesRate, out uninitializedBranches);
    9091
    9192        if (parent == null) {
    9293          // no parent means the new function is the initial operator
    9394          // and we have to update the value in the variable
    94           scope.GetVariable("OperatorTree").Value = newFunction;
    95           rootOperator = newFunction;
     95          scope.GetVariable(scope.TranslateName("FunctionTree")).Value = newFunction;
     96          root = newFunction;
    9697        } else {
    9798          // remove the old child
    98           parent.RemoveSubOperator(selectedChildIndex);
     99          parent.RemoveSubTree(selectedChildIndex);
    99100          // add the new child as sub-tree of parent
    100           parent.AddSubOperator(newFunction, selectedChildIndex);
     101          parent.InsertSubTree(selectedChildIndex, newFunction);
    101102        }
    102103
    103104        // recalculate size and height
    104         treeSize.Data = gardener.GetTreeSize(rootOperator);
    105         treeHeight.Data = gardener.GetTreeHeight(rootOperator);
    106 
     105        treeSize.Data = gardener.GetTreeSize(root);
     106        treeHeight.Data = gardener.GetTreeHeight(root);
     107
     108        // check if whole tree is ok
    107109        // check if the size of the new tree is still in the allowed bounds
    108         if (treeHeight.Data > maxTreeHeight ||
     110        if (!gardener.IsValidTree(root) ||
     111          treeHeight.Data > maxTreeHeight ||
    109112          treeSize.Data > maxTreeSize) {
    110113          throw new InvalidProgramException();
    111114        }
    112115
    113         // check if whole tree is ok
    114         if (!gardener.IsValidTree(rootOperator)) {
    115           throw new InvalidProgramException();
    116         }
    117 
    118116        // return a composite operation that initializes all created sub-trees
    119         return gardener.CreateInitializationOperation(uninitializedOperators, scope);
    120       }
    121     }
    122 
    123 
    124     private IOperator ChangeTerminalType(IOperator parent, IOperator child, int childIndex, TreeGardener gardener, MersenneTwister random) {
    125 
    126       IList<IOperator> allowedChildren;
     117        return gardener.CreateInitializationOperation(uninitializedBranches, scope);
     118      }
     119    }
     120
     121    private IFunctionTree ChangeTerminalType(IFunctionTree parent, IFunctionTree child, int childIndex, TreeGardener gardener, MersenneTwister random) {
     122      IList<IFunction> allowedChildren;
    127123      if (parent == null) {
    128124        allowedChildren = gardener.Terminals;
    129125      } else {
    130         SubOperatorsConstraintAnalyser analyser = new SubOperatorsConstraintAnalyser();
    131         analyser.AllPossibleOperators = gardener.Terminals;
    132         allowedChildren = analyser.GetAllowedOperators(parent, childIndex);
     126        allowedChildren = new List<IFunction>();
     127        var allAllowedChildren = gardener.GetAllowedSubFunctions(parent.Function, childIndex);
     128        foreach(IFunction c in allAllowedChildren) {
     129          if(gardener.IsTerminal(c)) allowedChildren.Add(c);
     130        }
    133131      }
    134132
    135133      // selecting from the terminals should always work since the current child was also a terminal
    136134      // so in the worst case we will just create a new terminal of the same type again.
    137       return gardener.CreateRandomTree((IOperator)allowedChildren[random.Next(allowedChildren.Count)].Clone(), 1, 1, false);
    138     }
    139 
    140     private IOperator ChangeFunctionType(IOperator parent, IOperator child, int childIndex, TreeGardener gardener, MersenneTwister random,
    141       double balancedTreesRate, out List<IOperator> uninitializedOperators) {
    142       // since there are suboperators, we have to check which
    143       // and how many of the existing suboperators we can reuse
    144 
    145       // let's choose the operator we want to use instead of the old child. For this we have to determine the
    146       // pool of allowed operators based on constraints of the parent if there is one.
    147       IList<IOperator> allowedSubOperators;
    148       SubOperatorsConstraintAnalyser analyser = new SubOperatorsConstraintAnalyser();
    149       analyser.AllPossibleOperators = gardener.AllOperators;
    150       if (parent == null) {
    151         allowedSubOperators = gardener.AllOperators;
    152       } else {
    153         allowedSubOperators = analyser.GetAllowedOperators(parent, childIndex);
    154       }
     135      return gardener.CreateRandomTree(allowedChildren[random.Next(allowedChildren.Count)], 1, 1, false);
     136    }
     137
     138    private IFunctionTree ChangeFunctionType(IFunctionTree parent, IFunctionTree child, int childIndex, TreeGardener gardener, MersenneTwister random,
     139      double balancedTreesRate, out List<IFunctionTree> uninitializedBranches) {
     140      // since there are subtrees, we have to check which
     141      // and how many of the existing subtrees we can reuse
     142
     143      // let's choose the function we want to use instead of the old child. For this we have to determine the
     144      // pool of allowed functions based on constraints of the parent if there is one.
     145      IList<IFunction> allowedFunctions = gardener.GetAllowedSubFunctions(parent!=null?parent.Function:null, childIndex);
    155146
    156147      // try to make a tree with the same arity as the old child.
    157       int actualArity = child.SubOperators.Count;
     148      int actualArity = child.SubTrees.Count;
    158149      // arity of the selected operator
    159150      int minArity;
    160151      int maxArity;
    161 
    162       allowedSubOperators = allowedSubOperators.Where(f => {
     152      // only allow functions where we can keep all existing sub-trees
     153      // we don't want to create new sub-trees here
     154      // this restriction can be removed if we add code that creates sub-trees where necessary (gkronber 22.04.08)
     155      allowedFunctions = allowedFunctions.Where(f => {
    163156        gardener.GetMinMaxArity(f, out minArity, out maxArity);
    164157        return minArity <= actualArity;
    165158      }).ToList();
    166159
    167       IOperator newOperator = (IOperator)allowedSubOperators[random.Next(allowedSubOperators.Count)].Clone();
    168 
    169       gardener.GetMinMaxArity(newOperator, out minArity, out maxArity);
    170       // if the old child had too many sub-operators then make the new child with the maximal arity
     160      // create a new tree-node for a randomly selected function
     161      IFunctionTree newTree = new FunctionTree(allowedFunctions[random.Next(allowedFunctions.Count)]);
     162
     163      gardener.GetMinMaxArity(newTree.Function, out minArity, out maxArity);
     164      // if the old child had too many sub-trees then the new child should keep as many sub-trees as possible
    171165      if (actualArity > maxArity)
    172166        actualArity = maxArity;
     
    175169      // use the size of the smallest subtree as the maximal allowed size for new subtrees to
    176170      // prevent that we ever create trees over the MaxTreeSize limit
    177       int maxSubTreeSize = child.SubOperators.Select(subOp => gardener.GetTreeSize(subOp)).Min();
     171      int maxSubTreeSize = child.SubTrees.Select(subTree => gardener.GetTreeSize(subTree)).Min();
    178172      int maxSubTreeHeight = gardener.GetTreeHeight(child) - 1;
    179173
    180174      // create a list that holds old sub-trees that we can reuse in the new tree
    181       List<IOperator> availableSubOperators = new List<IOperator>(child.SubOperators);
    182       List<IOperator> freshSubTrees = new List<IOperator>() { newOperator };
    183 
    184       // randomly select the suboperators that we keep
     175      List<IFunctionTree> availableSubTrees = new List<IFunctionTree>(child.SubTrees);
     176      List<IFunctionTree> freshSubTrees = new List<IFunctionTree>() { newTree };
     177
     178      // randomly select the sub-trees that we keep
    185179      for (int i = 0; i < actualArity; i++) {
    186         // fill all sub-operator slots of the new operator
    187         // if for a given slot i there are existing sub-operators that can be used in that slot
    188         // then use a random existing sub-operator. When there are no existing sub-operators
     180        // fill all sub-tree slots of the new tree
     181        // if for a given slot i there are multiple existing sub-trees that can be used in that slot
     182        // then use a random existing sub-tree. When there are no existing sub-trees
    189183        // that fit in the given slot then create a new random tree and use it for the slot
    190         IList<IOperator> allowedOperators = analyser.GetAllowedOperators(newOperator, i);
    191         var matchingOperators = availableSubOperators.Where(subOp => allowedOperators.Contains(subOp, new TreeGardener.OperatorEqualityComparer()));
    192 
    193         if (matchingOperators.Count() > 0) {
    194           IOperator selectedSubOperator = matchingOperators.ElementAt(random.Next(matchingOperators.Count()));
    195           // we can just add it as suboperator
    196           newOperator.AddSubOperator(selectedSubOperator, i);
    197           availableSubOperators.Remove(selectedSubOperator); // the operator shouldn't be available for the following slots
     184        ICollection<IFunction> allowedSubFunctions = gardener.GetAllowedSubFunctions(newTree.Function, i);
     185        var matchingSubTrees = availableSubTrees.Where(subTree => allowedSubFunctions.Contains(subTree.Function));
     186
     187        if (matchingSubTrees.Count() > 0) {
     188          IFunctionTree selectedSubTree = matchingSubTrees.ElementAt(random.Next(matchingSubTrees.Count()));
     189          // we can just add it as subtree
     190          newTree.InsertSubTree(i, selectedSubTree);
     191          availableSubTrees.Remove(selectedSubTree); // the branch shouldn't be available for the following slots
    198192        } else {
    199           IOperator freshOperatorTree;
     193          // no existing matching tree found => create a new one
     194          IFunctionTree freshTree;
    200195          if(random.NextDouble() <= balancedTreesRate) {
    201             freshOperatorTree = gardener.CreateRandomTree(allowedOperators, maxSubTreeSize, maxSubTreeHeight, true);
     196            freshTree = gardener.CreateRandomTree(allowedSubFunctions, maxSubTreeSize, maxSubTreeHeight, true);
    202197          } else {
    203             freshOperatorTree = gardener.CreateRandomTree(allowedOperators, maxSubTreeSize, maxSubTreeHeight, false);
     198            freshTree = gardener.CreateRandomTree(allowedSubFunctions, maxSubTreeSize, maxSubTreeHeight, false);
    204199          }
    205           freshSubTrees.AddRange(gardener.GetAllOperators(freshOperatorTree));
    206 
    207           newOperator.AddSubOperator(freshOperatorTree, i);
    208         }
    209       }
    210 
    211       uninitializedOperators = freshSubTrees;
    212       return newOperator;
     200          freshSubTrees.AddRange(gardener.GetAllSubTrees(freshTree));
     201
     202          newTree.InsertSubTree(i, freshTree);
     203        }
     204      }
     205      uninitializedBranches = freshSubTrees;
     206      return newTree;
    213207    }
    214208  }
  • trunk/sources/HeuristicLab.StructureIdentification/Manipulation/CutOutNodeManipulation.cs

    r23 r155  
    2727using HeuristicLab.Random;
    2828using System;
     29using HeuristicLab.Functions;
    2930
    3031namespace HeuristicLab.StructureIdentification {
     
    3233    public override string Description {
    3334      get {
    34         return @"Takes a tree, selects a random node of the tree and then tries to replace a random child
     35        return @"Takes a tree, selects a random node of the tree and then tries to replace a random sub-tree
    3536of that node with one of the childs of the selected child.
    3637
     
    5354      AddVariableInfo(new VariableInfo("MaxTreeSize", "The maximal allowed size (number of nodes) of the tree", typeof(IntData), VariableKind.In));
    5455      AddVariableInfo(new VariableInfo("BalancedTreesRate", "Determines how many trees should be balanced", typeof(DoubleData), VariableKind.In));
    55       AddVariableInfo(new VariableInfo("OperatorTree", "The tree to mutate", typeof(IOperator), VariableKind.In));
    56       AddVariableInfo(new VariableInfo("TreeSize", "The size (number of nodes) of the tree", typeof(IntData), VariableKind.In));
    57       AddVariableInfo(new VariableInfo("TreeHeight", "The height of the tree", typeof(IntData), VariableKind.In));
     56      AddVariableInfo(new VariableInfo("FunctionTree", "The tree to mutate", typeof(IFunctionTree), VariableKind.In | VariableKind.Out));
     57      AddVariableInfo(new VariableInfo("TreeSize", "The size (number of nodes) of the tree", typeof(IntData), VariableKind.In | VariableKind.Out));
     58      AddVariableInfo(new VariableInfo("TreeHeight", "The height of the tree", typeof(IntData), VariableKind.In | VariableKind.Out));
    5859    }
    5960
    6061
    6162    public override IOperation Apply(IScope scope) {
    62       IOperator rootOperator = GetVariableValue<IOperator>("OperatorTree", scope, true);
     63      IFunctionTree root = GetVariableValue<IFunctionTree>("FunctionTree", scope, true);
    6364      MersenneTwister random = GetVariableValue<MersenneTwister>("Random", scope, true);
    6465      GPOperatorLibrary library = GetVariableValue<GPOperatorLibrary>("OperatorLibrary", scope, true);
     
    6869
    6970      TreeGardener gardener = new TreeGardener(random, library);
    70       IOperator parent = gardener.GetRandomParentNode(rootOperator);
     71      IFunctionTree parent = gardener.GetRandomParentNode(root);
    7172      // parent == null means we should cut out the root node
    72       // => return a random suboperator of the root
     73      // => return a random sub-tree of the root
    7374      if (parent == null) {
    74         // when there are suboperators then replace the old operator with a random suboperator
    75         if (rootOperator.SubOperators.Count > 0) {
    76           rootOperator = rootOperator.SubOperators[random.Next(rootOperator.SubOperators.Count)];
     75        // when there are sub-trees then replace the old tree with a random sub-tree
     76        if (root.SubTrees.Count > 0) {
     77          root = root.SubTrees[random.Next(root.SubTrees.Count)];
    7778
    78           GetVariableValue<IntData>("TreeSize", scope, true).Data = gardener.GetTreeSize(rootOperator);
    79           GetVariableValue<IntData>("TreeHeight", scope, true).Data = gardener.GetTreeHeight(rootOperator);
     79          GetVariableValue<IntData>("TreeSize", scope, true).Data = gardener.GetTreeSize(root);
     80          GetVariableValue<IntData>("TreeHeight", scope, true).Data = gardener.GetTreeHeight(root);
    8081
    81           // this is not really necessary (we can leave it in until the operator is stable)
    82           if (!gardener.IsValidTree(rootOperator)) {
     82          // update the variable
     83          scope.GetVariable(scope.TranslateName("FunctionTree")).Value = root;
     84          if (!gardener.IsValidTree(root)) {
    8385            throw new InvalidProgramException();
    8486          }
    85 
     87          // we reused a sub-tree so we don't have to schedule initialization operations
     88          return null;
     89        } else {
     90          // we want to cut the root node and there are no sub-trees => create a new random terminal
     91          IFunctionTree newTree;
     92          newTree = gardener.CreateRandomTree(gardener.Terminals, 1, 1, false);
     93          GetVariableValue<IntData>("TreeSize", scope, true).Data = gardener.GetTreeSize(newTree);
     94          GetVariableValue<IntData>("TreeHeight", scope, true).Data = gardener.GetTreeHeight(newTree);
    8695          // update the variable
    87           scope.GetVariable("OperatorTree").Value = rootOperator;
    88           if (!gardener.IsValidTree(rootOperator)) {
     96          scope.GetVariable(scope.TranslateName("FunctionTree")).Value = newTree;
     97          if (!gardener.IsValidTree(newTree)) {
    8998            throw new InvalidProgramException();
    9099          }
    91 
    92 
    93           // the tree is already initialized so we don't have to schedule initialization operations
    94           return null;
    95         } else {
    96           // create a new random tree
    97           IOperator newOperator;
    98           if(random.NextDouble() <= balancedTreesRate) {
    99             newOperator = gardener.CreateRandomTree(gardener.AllOperators, maxTreeSize, maxTreeHeight, true);
    100           } else {
    101             newOperator = gardener.CreateRandomTree(gardener.AllOperators, maxTreeSize, maxTreeHeight, false);
    102           }
    103 
    104           GetVariableValue<IntData>("TreeSize", scope, true).Data = gardener.GetTreeSize(newOperator);
    105           GetVariableValue<IntData>("TreeHeight", scope, true).Data = gardener.GetTreeHeight(newOperator);
    106 
    107           if (!gardener.IsValidTree(newOperator)) {
    108             throw new InvalidProgramException();
    109           }
    110 
    111           // update the variable
    112           scope.GetVariable("OperatorTree").Value = newOperator;
    113 
    114           if (!gardener.IsValidTree(newOperator)) {
    115             throw new InvalidProgramException();
    116           }
    117 
    118           // schedule an operation to initialize the whole operator graph
    119           return gardener.CreateInitializationOperation(gardener.GetAllOperators(newOperator), scope);
     100          // schedule an operation to initialize the whole tree
     101          return gardener.CreateInitializationOperation(gardener.GetAllSubTrees(newTree), scope);
    120102        }
    121103      }
    122104
    123       int childIndex = random.Next(parent.SubOperators.Count);
    124       IOperator child = parent.SubOperators[childIndex];
     105      // select a child to cut away
     106      int childIndex = random.Next(parent.SubTrees.Count);
     107      IFunctionTree child = parent.SubTrees[childIndex];
    125108
    126       // match the suboperators of the child with the allowed suboperators of the parent
    127       IOperator[] possibleChilds = gardener.GetAllowedSubOperators(parent, childIndex).SelectMany(allowedOp => child.SubOperators
    128         .Where(subOp => ((StringData)subOp.GetVariable(GPOperatorLibrary.TYPE_ID).Value).Data ==
    129           ((StringData)allowedOp.GetVariable(GPOperatorLibrary.TYPE_ID).Value).Data)).ToArray();
    130 
     109      // match the sub-trees of the child with the allowed sub-trees of the parent
     110      ICollection<IFunction> allowedFunctions = gardener.GetAllowedSubFunctions(parent.Function, childIndex);
     111      IFunctionTree[] possibleChilds = child.SubTrees.Where(t => allowedFunctions.Contains(t.Function)).ToArray();
    131112
    132113      if (possibleChilds.Length > 0) {
    133         // replace child with a random child of the child
    134         // make a clone to simplify removing obsolete operators from the operator-graph
    135         IOperator selectedChild = (IOperator)possibleChilds[random.Next(possibleChilds.Length)].Clone();       
    136         parent.RemoveSubOperator(childIndex);
    137         parent.AddSubOperator(selectedChild, childIndex);
     114        // replace child with a random child of that child
     115        IFunctionTree selectedChild = possibleChilds[random.Next(possibleChilds.Length)];       
     116        parent.RemoveSubTree(childIndex);
     117        parent.InsertSubTree(childIndex, selectedChild);
    138118
    139         if (!gardener.IsValidTree(rootOperator)) {
     119        if (!gardener.IsValidTree(root)) {
    140120          throw new InvalidProgramException();
    141121        }
    142122
    143123        // update the size and height of our tree
    144         GetVariableValue<IntData>("TreeSize", scope, true).Data = gardener.GetTreeSize(rootOperator);
    145         GetVariableValue<IntData>("TreeHeight", scope, true).Data = gardener.GetTreeHeight(rootOperator);
     124        GetVariableValue<IntData>("TreeSize", scope, true).Data = gardener.GetTreeSize(root);
     125        GetVariableValue<IntData>("TreeHeight", scope, true).Data = gardener.GetTreeHeight(root);
    146126        // don't need to schedule initialization operations
    147127        return null;
    148128      } else {
     129        // can't reuse an existing branch => create a new tree
    149130        // determine the level of the parent
    150         int parentLevel = gardener.GetNodeLevel(rootOperator, parent);
     131        int parentLevel = gardener.GetBranchLevel(root, parent);
    151132
    152133        // first remove the old child (first step essential!)
    153         parent.RemoveSubOperator(childIndex);
     134        parent.RemoveSubTree(childIndex);
    154135        // then determine the number of nodes left over after the child has been removed!
    155         int remainingNodes = gardener.GetTreeSize(rootOperator);
     136        int remainingNodes = gardener.GetTreeSize(root);
    156137
    157         IList<IOperator> allowedOperators = gardener.GetAllowedSubOperators(parent, childIndex);
    158         IOperator newOperatorTree = gardener.CreateRandomTree(allowedOperators, maxTreeSize - remainingNodes, maxTreeHeight - parentLevel, true);
     138        allowedFunctions = gardener.GetAllowedSubFunctions(parent.Function, childIndex);
     139        IFunctionTree newFunctionTree = gardener.CreateRandomTree(allowedFunctions, maxTreeSize - remainingNodes, maxTreeHeight - parentLevel, false);
    159140
    160         parent.AddSubOperator(newOperatorTree, childIndex);
     141        parent.InsertSubTree(childIndex, newFunctionTree);
    161142
    162         GetVariableValue<IntData>("TreeSize", scope, true).Data = gardener.GetTreeSize(rootOperator);
    163         GetVariableValue<IntData>("TreeHeight", scope, true).Data = gardener.GetTreeHeight(rootOperator);
     143        GetVariableValue<IntData>("TreeSize", scope, true).Data = gardener.GetTreeSize(root);
     144        GetVariableValue<IntData>("TreeHeight", scope, true).Data = gardener.GetTreeHeight(root);
    164145
    165         if (!gardener.IsValidTree(rootOperator)) {
     146        if (!gardener.IsValidTree(root)) {
    166147          throw new InvalidProgramException();
    167148        }
    168149
    169         // schedule an initialization operation for the new operator
    170         return gardener.CreateInitializationOperation(gardener.GetAllOperators(newOperatorTree), scope);
     150        // schedule an initialization operation for the new function-tree
     151        return gardener.CreateInitializationOperation(gardener.GetAllSubTrees(newFunctionTree), scope);
    171152      }
    172153    }
  • trunk/sources/HeuristicLab.StructureIdentification/Manipulation/DeleteSubTreeManipulation.cs

    r23 r155  
    2626using HeuristicLab.Operators;
    2727using HeuristicLab.Random;
     28using HeuristicLab.Functions;
    2829
    2930namespace HeuristicLab.StructureIdentification {
     
    4243      AddVariableInfo(new VariableInfo("MaxTreeHeight", "The maximal allowed height of the tree", typeof(IntData), VariableKind.In));
    4344      AddVariableInfo(new VariableInfo("MaxTreeSize", "The maximal allowed size (number of nodes) of the tree", typeof(IntData), VariableKind.In));
    44       AddVariableInfo(new VariableInfo("OperatorTree", "The tree to mutate", typeof(IOperator), VariableKind.In | VariableKind.Out));
     45      AddVariableInfo(new VariableInfo("FunctionTree", "The tree to mutate", typeof(IFunctionTree), VariableKind.In | VariableKind.Out));
    4546      AddVariableInfo(new VariableInfo("TreeSize", "The size (number of nodes) of the tree", typeof(IntData), VariableKind.In | VariableKind.Out));
    4647      AddVariableInfo(new VariableInfo("TreeHeight", "The height of the tree", typeof(IntData), VariableKind.In | VariableKind.Out));
     
    4950
    5051    public override IOperation Apply(IScope scope) {
    51       IOperator rootOperator = GetVariableValue<IOperator>("OperatorTree", scope, true);
     52      IFunctionTree root = GetVariableValue<IFunctionTree>("FunctionTree", scope, true);
    5253      MersenneTwister random = GetVariableValue<MersenneTwister>("Random", scope, true);
    5354      GPOperatorLibrary library = GetVariableValue<GPOperatorLibrary>("OperatorLibrary", scope, true);
    54 
    5555      TreeGardener gardener = new TreeGardener(random, library);
    56 
    57       IOperator parent = gardener.GetRandomParentNode(rootOperator);
     56      IFunctionTree parent = gardener.GetRandomParentNode(root);
    5857
    5958      // parent==null means the whole tree should be deleted.
    6059      // => return a new minimal random tree
    6160      if(parent == null) {
    62         IOperator newTree = gardener.CreateRandomTree(1, 1, true);
     61        IFunctionTree newTree = gardener.CreateRandomTree(1, 1, false);
    6362
    6463        // check if the tree is ok
     
    7069        GetVariableValue<IntData>("TreeSize", scope, true).Data = gardener.GetTreeSize(newTree);
    7170        GetVariableValue<IntData>("TreeHeight", scope, true).Data = gardener.GetTreeHeight(newTree);
    72         scope.GetVariable("OperatorTree").Value = newTree;
     71        scope.GetVariable(scope.TranslateName("FunctionTree")).Value = newTree;
    7372
    7473        // schedule an operation to initialize the newly created operator
    75         return gardener.CreateInitializationOperation(gardener.GetAllOperators(newTree), scope);
     74        return gardener.CreateInitializationOperation(gardener.GetAllSubTrees(newTree), scope);
    7675      }
    7776
    78       int childIndex = random.Next(parent.SubOperators.Count);
    79 
     77      // select a branch to prune
     78      int childIndex = random.Next(parent.SubTrees.Count);
    8079      int min;
    8180      int max;
    82       gardener.GetMinMaxArity(parent, out min, out max);
    83       if(parent.SubOperators.Count > min) {
    84         parent.RemoveSubOperator(childIndex);
    85         // actually since the next suboperators are shifted in the place of the removed operator
    86         // it might be possible that these suboperators are not allowed in the place of the old operator
     81      gardener.GetMinMaxArity(parent.Function, out min, out max);
     82      if(parent.SubTrees.Count > min) {
     83        parent.RemoveSubTree(childIndex);
     84        // actually since the next sub-trees are shifted in the place of the removed branch
     85        // it might be possible that these sub-trees are not allowed in the place of the old branch
    8786        // we ignore this problem for now.
    88         // when this starts to become a problem a possible solution is to go through the shifted operators from the place of the shifted
     87        // when this starts to become a problem a possible solution is to go through the shifted branches from the place of the shifted
    8988        // and find the first one that doesn't fit. At this position we insert a new randomly initialized subtree of matching type (gkronber 25.12.07)
    9089
    91         if(!gardener.IsValidTree(rootOperator)) {
     90        if(!gardener.IsValidTree(root)) {
    9291          throw new InvalidOperationException();
    9392        }
    9493
    95         GetVariableValue<IntData>("TreeSize", scope, true).Data = gardener.GetTreeSize(rootOperator);
    96         GetVariableValue<IntData>("TreeHeight", scope, true).Data = gardener.GetTreeHeight(rootOperator);
    97         // root hasn't changed so don't need to update 'OperatorTree' variable
    98 
     94        GetVariableValue<IntData>("TreeSize", scope, true).Data = gardener.GetTreeSize(root);
     95        GetVariableValue<IntData>("TreeHeight", scope, true).Data = gardener.GetTreeHeight(root);
     96        // root hasn't changed so don't need to update 'FunctionTree' variable
    9997        return null;
    10098      } else {
    10199        // replace with a minimal random seedling
    102         parent.RemoveSubOperator(childIndex);
     100        parent.RemoveSubTree(childIndex);
    103101
    104         IList<IOperator> allowedOperators = gardener.GetAllowedSubOperators(parent, childIndex);
    105         IOperator newOperatorTree = gardener.CreateRandomTree(allowedOperators, 1, 1, true);
     102        ICollection<IFunction> allowedFunctions = gardener.GetAllowedSubFunctions(parent.Function, childIndex);
     103        IFunctionTree newFunctionTree = gardener.CreateRandomTree(allowedFunctions, 1, 1, true);
    106104
    107         parent.AddSubOperator(newOperatorTree, childIndex);
     105        parent.InsertSubTree(childIndex, newFunctionTree);
    108106
    109         if(!gardener.IsValidTree(rootOperator)) {
     107        if(!gardener.IsValidTree(root)) {
    110108          throw new InvalidProgramException();
    111109        }
    112110
    113         GetVariableValue<IntData>("TreeSize", scope, true).Data = gardener.GetTreeSize(rootOperator);
    114         GetVariableValue<IntData>("TreeHeight", scope, true).Data = gardener.GetTreeHeight(rootOperator);
    115         // again the root hasn't changed so we don't need to update the 'OperatorTree' variable
    116 
    117         return gardener.CreateInitializationOperation(gardener.GetAllOperators(newOperatorTree), scope);
     111        GetVariableValue<IntData>("TreeSize", scope, true).Data = gardener.GetTreeSize(root);
     112        GetVariableValue<IntData>("TreeHeight", scope, true).Data = gardener.GetTreeHeight(root);
     113        // again the root hasn't changed so we don't need to update the 'FunctionTree' variable
     114        // but we have to return an initialization operation for the newly created tree
     115        return gardener.CreateInitializationOperation(gardener.GetAllSubTrees(newFunctionTree), scope);
    118116      }
    119117    }
  • trunk/sources/HeuristicLab.StructureIdentification/Manipulation/FullTreeShaker.cs

    r88 r155  
    2929using HeuristicLab.Data;
    3030using HeuristicLab.Selection;
     31using HeuristicLab.Functions;
    3132
    3233namespace HeuristicLab.StructureIdentification {
     
    3839    public FullTreeShaker()
    3940      : base() {
     41      AddVariableInfo(new VariableInfo("Random", "A random generator (uniform)", typeof(MersenneTwister), VariableKind.In));
    4042      AddVariableInfo(new VariableInfo("OperatorLibrary", "Operator library that defines operator mutations", typeof(GPOperatorLibrary), VariableKind.In));
    41       AddVariableInfo(new VariableInfo("OperatorTree", "The operator tree that should be mutated", typeof(IOperator), VariableKind.In));
    42       AddVariableInfo(new VariableInfo("Random", "A random generator (uniform)", typeof(MersenneTwister), VariableKind.In));
    43       AddVariableInfo(new VariableInfo("ShakingFactor", "Variable that determines the force of the shakeing operation", typeof(DoubleData), VariableKind.In));
     43      AddVariableInfo(new VariableInfo("ShakingFactor", "Variable that determines the force of the shaking operation", typeof(DoubleData), VariableKind.In));
     44      AddVariableInfo(new VariableInfo("FunctionTree", "The function tree that should be mutated", typeof(IFunctionTree), VariableKind.In | VariableKind.Out));
    4445    }
    4546
    4647    public override IOperation Apply(IScope scope) {
    4748      GPOperatorLibrary library = GetVariableValue<GPOperatorLibrary>("OperatorLibrary", scope, true);
    48       IOperator op = GetVariableValue<IOperator>("OperatorTree", scope, false);
     49      IFunctionTree tree = GetVariableValue<IFunctionTree>("FunctionTree", scope, false);
    4950      MersenneTwister mt = GetVariableValue<MersenneTwister>("Random", scope, true);
    5051
     
    5657
    5758      TreeGardener gardener = new TreeGardener(mt, library);
    58       var parametricNodes = gardener.GetAllOperators(op).Where(o => o.GetVariable(GPOperatorLibrary.MANIPULATION) != null);
    59       foreach(IOperator subOperator in parametricNodes) {
    60         IOperator mutation =(IOperator)subOperator.GetVariable(GPOperatorLibrary.MANIPULATION).Value;
     59      var parametricBranches = gardener.GetAllSubTrees(tree).Where(branch => branch.Function.GetVariable(GPOperatorLibrary.MANIPULATION) != null);
     60      foreach(IFunctionTree subTree in parametricBranches) {
     61        IOperator mutation =(IOperator)subTree.Function.GetVariable(GPOperatorLibrary.MANIPULATION).Value;
    6162
    6263        // store all local variables into a temporary scope
    6364        Scope mutationScope = new Scope();
    64         foreach(IVariableInfo info in subOperator.VariableInfos) {
    65           if(info.Local) {
    66             mutationScope.AddVariable(subOperator.GetVariable(info.FormalName));
    67           }
     65        foreach(IVariable variable in subTree.LocalVariables) {
     66          mutationScope.AddVariable(variable);
    6867        }
    6968
  • trunk/sources/HeuristicLab.StructureIdentification/Manipulation/OnePointShaker.cs

    r88 r155  
    2929using HeuristicLab.Data;
    3030using HeuristicLab.Selection;
     31using HeuristicLab.Functions;
    3132
    3233namespace HeuristicLab.StructureIdentification {
     
    3940      : base() {
    4041      AddVariableInfo(new VariableInfo("OperatorLibrary", "Operator library that defines mutation operations for operators", typeof(GPOperatorLibrary), VariableKind.In));
    41       AddVariableInfo(new VariableInfo("OperatorTree", "The operator tree that should be mutated", typeof(IOperator), VariableKind.In));
    4242      AddVariableInfo(new VariableInfo("Random", "A random generator (uniform)", typeof(MersenneTwister), VariableKind.In));
    4343      AddVariableInfo(new VariableInfo("ShakingFactor", "Factor that determines the force of the shaking operation", typeof(DoubleData), VariableKind.In));
     44      AddVariableInfo(new VariableInfo("FunctionTree", "The function tree that should be mutated", typeof(IFunctionTree), VariableKind.In | VariableKind.Out));
    4445    }
    4546
    4647    public override IOperation Apply(IScope scope) {
    4748      GPOperatorLibrary library = GetVariableValue<GPOperatorLibrary>("OperatorLibrary", scope, true);
    48       IOperator op = GetVariableValue<IOperator>("OperatorTree", scope, false);
     49      IFunctionTree tree = GetVariableValue<IFunctionTree>("FunctionTree", scope, false);
    4950      MersenneTwister mt = GetVariableValue<MersenneTwister>("Random", scope, true);
    5051      TreeGardener gardener = new TreeGardener(mt, library);
    5152
    5253      // get all nodes for which a manipulation is defined
    53       var parametricNodes = gardener.GetAllOperators(op).Where(o => o.GetVariable(GPOperatorLibrary.MANIPULATION) != null);
    54       IOperator selectedOp = parametricNodes.ElementAt(mt.Next(parametricNodes.Count()));
    55 
    56       IOperator mutation = (IOperator)selectedOp.GetVariable(GPOperatorLibrary.MANIPULATION).Value;
    57 
     54      var parametricBranches = gardener.GetAllSubTrees(tree).Where(branch => branch.Function.GetVariable(GPOperatorLibrary.MANIPULATION) != null);
     55      IFunctionTree selectedBranch = parametricBranches.ElementAt(mt.Next(parametricBranches.Count()));
     56      IOperator mutation = (IOperator)selectedBranch.Function.GetVariable(GPOperatorLibrary.MANIPULATION).Value;
    5857      CompositeOperation next = new CompositeOperation();
    5958
    6059      // store all local variables into a temporary scope
    6160      Scope tempScope = new Scope("Temp. manipulation scope");
    62       // add aliases
    63       foreach(IVariableInfo variableInfo in VariableInfos)
    64         tempScope.AddAlias(variableInfo.FormalName, variableInfo.ActualName);
    65 
    66       foreach(IVariableInfo info in selectedOp.VariableInfos) {
    67         if(info.Local) {
    68           tempScope.AddVariable(selectedOp.GetVariable(info.FormalName));
    69         }
     61      foreach(IVariable variable in selectedBranch.LocalVariables) {
     62        tempScope.AddVariable(variable);
    7063      }
    7164
  • trunk/sources/HeuristicLab.StructureIdentification/Manipulation/SubstituteSubTreeManipulation.cs

    r23 r155  
    2727using HeuristicLab.Operators;
    2828using HeuristicLab.Random;
     29using HeuristicLab.Functions;
    2930
    3031namespace HeuristicLab.StructureIdentification {
     
    4243      AddVariableInfo(new VariableInfo("MaxTreeSize", "The maximal allowed size (number of nodes) of the tree", typeof(IntData), VariableKind.In));
    4344      AddVariableInfo(new VariableInfo("BalancedTreesRate", "Determines how many trees should be balanced", typeof(DoubleData), VariableKind.In));
    44       AddVariableInfo(new VariableInfo("OperatorTree", "The tree to manipulate", typeof(IOperator), VariableKind.In));
    45       AddVariableInfo(new VariableInfo("TreeSize", "The size (number of nodes) of the tree", typeof(IntData), VariableKind.In));
    46       AddVariableInfo(new VariableInfo("TreeHeight", "The height of the tree", typeof(IntData), VariableKind.In));
     45      AddVariableInfo(new VariableInfo("FunctionTree", "The tree to manipulate", typeof(IFunctionTree), VariableKind.In | VariableKind.Out));
     46      AddVariableInfo(new VariableInfo("TreeSize", "The size (number of nodes) of the tree", typeof(IntData), VariableKind.In | VariableKind.Out));
     47      AddVariableInfo(new VariableInfo("TreeHeight", "The height of the tree", typeof(IntData), VariableKind.In | VariableKind.Out));
    4748    }
    4849
    4950    public override IOperation Apply(IScope scope) {
    50       IOperator rootOperator = GetVariableValue<IOperator>("OperatorTree", scope, true);
    51 
     51      IFunctionTree root = GetVariableValue<IFunctionTree>("FunctionTree", scope, true);
    5252      MersenneTwister random = GetVariableValue<MersenneTwister>("Random", scope, true);
    5353      GPOperatorLibrary library = GetVariableValue<GPOperatorLibrary>("OperatorLibrary", scope, true);
     
    6060      TreeGardener gardener = new TreeGardener(random, library);
    6161
    62       IOperator parent = gardener.GetRandomParentNode(rootOperator);
     62      IFunctionTree parent = gardener.GetRandomParentNode(root);
    6363      if(parent == null) {
    6464        // parent == null means we should subsitute the whole tree
    6565        // => create a new random tree
    6666
    67         // create a new random operator tree
    68 
    69         IOperator newOperatorTree;
     67        // create a new random function tree
     68        IFunctionTree newTree;
    7069        if(random.NextDouble() <= balancedTreesRate) {
    71           newOperatorTree = gardener.CreateRandomTree(gardener.AllOperators, maxTreeSize, maxTreeHeight, true);
     70          newTree = gardener.CreateRandomTree(gardener.AllFunctions, maxTreeSize, maxTreeHeight, true);
    7271        } else {
    73           newOperatorTree = gardener.CreateRandomTree(gardener.AllOperators, maxTreeSize, maxTreeHeight, false);
     72          newTree = gardener.CreateRandomTree(gardener.AllFunctions, maxTreeSize, maxTreeHeight, false);
    7473        }
    7574
    76         if(!gardener.IsValidTree(newOperatorTree)) {
     75        if(!gardener.IsValidTree(newTree)) {
    7776          throw new InvalidProgramException();
    7877        }
    7978
    8079        // update the variables in the scope with the new values
    81         GetVariableValue<IntData>("TreeSize", scope, true).Data = gardener.GetTreeSize(newOperatorTree);
    82         GetVariableValue<IntData>("TreeHeight", scope, true).Data = gardener.GetTreeHeight(newOperatorTree);
    83         scope.GetVariable("OperatorTree").Value = newOperatorTree;
     80        GetVariableValue<IntData>("TreeSize", scope, true).Data = gardener.GetTreeSize(newTree);
     81        GetVariableValue<IntData>("TreeHeight", scope, true).Data = gardener.GetTreeHeight(newTree);
     82        scope.GetVariable(scope.TranslateName("FunctionTree")).Value = newTree;
    8483       
    85         // return a CompositeOperation that randomly initializes the new operator
    86         return gardener.CreateInitializationOperation(gardener.GetAllOperators(newOperatorTree), scope);
     84        // return a CompositeOperation that randomly initializes the new tree
     85        return gardener.CreateInitializationOperation(gardener.GetAllSubTrees(newTree), scope);
    8786      } else {
    8887        // determine a random child of the parent to be replaced
    89         int childIndex = random.Next(parent.SubOperators.Count);
    90 
    91         // get the list of allowed suboperators as the new child
    92         IList<IOperator> allowedOperators = gardener.GetAllowedSubOperators(parent, childIndex);
    93 
    94         if(allowedOperators.Count == 0) {
     88        int childIndex = random.Next(parent.SubTrees.Count);
     89        // get the list of allowed functions for the new sub-tree
     90        ICollection<IFunction> allowedFunctions = gardener.GetAllowedSubFunctions(parent.Function, childIndex);
     91        if(allowedFunctions.Count == 0) {
    9592          // don't change anything
    9693          // this shouldn't happen
     
    10097        // calculate the maximum size and height of the new sub-tree based on the location where
    10198        // it will be inserted
    102         int parentLevel = gardener.GetNodeLevel(rootOperator, parent);
     99        int parentLevel = gardener.GetBranchLevel(root, parent);
    103100
    104101        int maxSubTreeHeight = maxTreeHeight - parentLevel;
    105         int maxSubTreeSize = maxTreeSize - (treeSize - gardener.GetTreeSize(parent.SubOperators[childIndex]));
     102        int maxSubTreeSize = maxTreeSize - (treeSize - gardener.GetTreeSize(parent.SubTrees[childIndex]));
    106103
    107         // get a random operatorTree
    108         IOperator newOperatorTree;
     104        // create a random function tree
     105        IFunctionTree newTree;
    109106        if(random.NextDouble() <= balancedTreesRate) {
    110           newOperatorTree = gardener.CreateRandomTree(allowedOperators, maxSubTreeSize, maxSubTreeHeight, true);
     107          newTree = gardener.CreateRandomTree(allowedFunctions, maxSubTreeSize, maxSubTreeHeight, true);
    111108        } else {
    112           newOperatorTree = gardener.CreateRandomTree(allowedOperators, maxSubTreeSize, maxSubTreeHeight, false);
     109          newTree = gardener.CreateRandomTree(allowedFunctions, maxSubTreeSize, maxSubTreeHeight, false);
    113110        }
    114111
    115         IOperator oldChild = parent.SubOperators[childIndex];
    116         parent.RemoveSubOperator(childIndex);
    117         parent.AddSubOperator(newOperatorTree, childIndex);
     112        parent.RemoveSubTree(childIndex);
     113        parent.InsertSubTree(childIndex, newTree);
    118114
    119         if(!gardener.IsValidTree(rootOperator)) {
     115        if(!gardener.IsValidTree(root)) {
    120116          throw new InvalidProgramException();
    121117        }
    122118
    123119        // update the values of treeSize and treeHeight
    124         GetVariableValue<IntData>("TreeSize", scope, true).Data = gardener.GetTreeSize(rootOperator);
    125         GetVariableValue<IntData>("TreeHeight", scope, true).Data = gardener.GetTreeHeight(rootOperator);
    126         // the root operator hasn't changed so we don't need to update
    127 
     120        GetVariableValue<IntData>("TreeSize", scope, true).Data = gardener.GetTreeSize(root);
     121        GetVariableValue<IntData>("TreeHeight", scope, true).Data = gardener.GetTreeHeight(root);
     122        // the root hasn't changed so we don't need to update
    128123        // return a CompositeOperation that randomly initializes all nodes of the new subtree
    129         return gardener.CreateInitializationOperation(gardener.GetAllOperators(newOperatorTree), scope);
     124        return gardener.CreateInitializationOperation(gardener.GetAllSubTrees(newTree), scope);
    130125      }
    131126    }
  • trunk/sources/HeuristicLab.StructureIdentification/RandomTreeCreator.cs

    r23 r155  
    2626using System;
    2727using HeuristicLab.Random;
     28using HeuristicLab.Functions;
    2829
    2930namespace HeuristicLab.StructureIdentification {
     
    4041      AddVariableInfo(new VariableInfo("MaxTreeSize", "The maximal allowed size (number of nodes) of the tree", typeof(IntData), VariableKind.In));
    4142      AddVariableInfo(new VariableInfo("BalancedTreesRate", "Determines how many trees should be balanced", typeof(DoubleData), VariableKind.In));
    42       AddVariableInfo(new VariableInfo("OperatorTree", "The tree to mutate", typeof(IOperator), VariableKind.In));
    43       AddVariableInfo(new VariableInfo("TreeSize", "The size (number of nodes) of the tree", typeof(IntData), VariableKind.In));
    44       AddVariableInfo(new VariableInfo("TreeHeight", "The height of the tree", typeof(IntData), VariableKind.In));
     43      AddVariableInfo(new VariableInfo("FunctionTree", "The created tree", typeof(IFunctionTree), VariableKind.New | VariableKind.Out));
     44      AddVariableInfo(new VariableInfo("TreeSize", "The size (number of nodes) of the tree", typeof(IntData), VariableKind.New | VariableKind.Out));
     45      AddVariableInfo(new VariableInfo("TreeHeight", "The height of the tree", typeof(IntData), VariableKind.New | VariableKind.Out));
    4546    }
    4647
     
    5657      int treeHeight = random.Next(1, maxTreeHeight + 1);
    5758      int treeSize = random.Next(1, maxTreeSize + 1);
    58       IOperator rootOperator;
     59      IFunctionTree root;
    5960      if(random.NextDouble() <= balancedTreesRate) {
    60         rootOperator = gardener.CreateRandomTree(treeSize, treeHeight, true);
     61        root = gardener.CreateRandomTree(treeSize, treeHeight, true);
    6162      } else {
    62         rootOperator = gardener.CreateRandomTree(treeSize, treeHeight, false);
     63        root = gardener.CreateRandomTree(treeSize, treeHeight, false);
    6364      }
    6465
    65       int actualTreeSize = gardener.GetTreeSize(rootOperator);
    66       int actualTreeHeight = gardener.GetTreeHeight(rootOperator);
     66      int actualTreeSize = gardener.GetTreeSize(root);
     67      int actualTreeHeight = gardener.GetTreeHeight(root);
    6768
    68       scope.AddVariable(new Variable("OperatorTree", rootOperator));
    69       scope.AddVariable(new Variable("TreeSize", new IntData(actualTreeSize)));
    70       scope.AddVariable(new Variable("TreeHeight", new IntData(actualTreeHeight)));
     69      scope.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("FunctionTree"), root));
     70      scope.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("TreeSize"), new IntData(actualTreeSize)));
     71      scope.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("TreeHeight"), new IntData(actualTreeHeight)));
    7172
    72       if(!gardener.IsValidTree(rootOperator)) { throw new InvalidProgramException(); }
     73      if(!gardener.IsValidTree(root)) { throw new InvalidProgramException(); }
    7374
    7475      if(actualTreeSize > maxTreeSize ||
     
    7778      }
    7879
    79       return gardener.CreateInitializationOperation(gardener.GetAllOperators(rootOperator), scope);
     80      return gardener.CreateInitializationOperation(gardener.GetAllSubTrees(root), scope);
    8081    }
    8182  }
  • trunk/sources/HeuristicLab.StructureIdentification/Recombination/SinglePointCrossOver.cs

    r23 r155  
    2929using HeuristicLab.Data;
    3030using HeuristicLab.Constraints;
     31using HeuristicLab.Functions;
    3132
    3233namespace HeuristicLab.StructureIdentification {
     
    4445      AddVariableInfo(new VariableInfo("MaxTreeHeight", "The maximal allowed height of the tree", typeof(IntData), VariableKind.In));
    4546      AddVariableInfo(new VariableInfo("MaxTreeSize", "The maximal allowed size (number of nodes) of the tree", typeof(IntData), VariableKind.In));
    46       AddVariableInfo(new VariableInfo("OperatorTree", "The tree to mutate", typeof(IOperator), VariableKind.In));
    47       AddVariableInfo(new VariableInfo("TreeSize", "The size (number of nodes) of the tree", typeof(IntData), VariableKind.In));
    48       AddVariableInfo(new VariableInfo("TreeHeight", "The height of the tree", typeof(IntData), VariableKind.In));
     47      AddVariableInfo(new VariableInfo("FunctionTree", "The tree to mutate", typeof(IFunctionTree), VariableKind.In | VariableKind.New));
     48      AddVariableInfo(new VariableInfo("TreeSize", "The size (number of nodes) of the tree", typeof(IntData), VariableKind.New));
     49      AddVariableInfo(new VariableInfo("TreeHeight", "The height of the tree", typeof(IntData), VariableKind.New));
    4950    }
    5051
     
    7778    }
    7879
    79 
    8080    private IOperation Cross(TreeGardener gardener, int maxTreeSize, int maxTreeHeight,
    8181      IScope scope, MersenneTwister random, IScope parent1, IScope parent2, IScope child) {
    82       List<IOperator> newOperators;
    83       IOperator newTree = Cross(gardener, parent1, parent2,
    84         random, maxTreeSize, maxTreeHeight, out newOperators);
    85 
    86       if(!gardener.IsValidTree(newTree)) {
    87         throw new InvalidProgramException();
    88       }
     82      List<IFunctionTree> newBranches;
     83      IFunctionTree newTree = Cross(gardener, parent1, parent2,
     84        random, maxTreeSize, maxTreeHeight, out newBranches);
     85
    8986
    9087      int newTreeSize = gardener.GetTreeSize(newTree);
    9188      int newTreeHeight = gardener.GetTreeHeight(newTree);
    92       child.AddVariable(new Variable("OperatorTree", newTree));
    93       child.AddVariable(new Variable("TreeSize", new IntData(newTreeSize)));
    94       child.AddVariable(new Variable("TreeHeight", new IntData(newTreeHeight)));
    95 
    96       // check if the size of the new tree is still in the allowed bounds
    97       if (newTreeHeight > maxTreeHeight ||
     89      child.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("FunctionTree"), newTree));
     90      child.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("TreeSize"), new IntData(newTreeSize)));
     91      child.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("TreeHeight"), new IntData(newTreeHeight)));
     92
     93      // check if the new tree is valid and if the size of is still in the allowed bounds
     94      if(!gardener.IsValidTree(newTree) ||
     95        newTreeHeight > maxTreeHeight ||
    9896        newTreeSize > maxTreeSize) {
    9997        throw new InvalidProgramException();
    10098      }
    101 
    102 
    103       return gardener.CreateInitializationOperation(newOperators, child);
    104     }
    105 
    106 
    107     private IOperator Cross(TreeGardener gardener, IScope f, IScope g, MersenneTwister random, int maxTreeSize, int maxTreeHeight, out List<IOperator> newOperators) {
    108       IOperator tree0 = f.GetVariableValue<IOperator>("OperatorTree", false);
     99      return gardener.CreateInitializationOperation(newBranches, child);
     100    }
     101
     102
     103    private IFunctionTree Cross(TreeGardener gardener, IScope f, IScope g, MersenneTwister random, int maxTreeSize, int maxTreeHeight, out List<IFunctionTree> newBranches) {
     104      IFunctionTree tree0 = f.GetVariableValue<IFunctionTree>("FunctionTree", false);
    109105      int tree0Height = f.GetVariableValue<IntData>("TreeHeight", false).Data;
    110106      int tree0Size = f.GetVariableValue<IntData>("TreeSize", false).Data;
    111107
    112       IOperator tree1 = g.GetVariableValue<IOperator>("OperatorTree", false);
     108      IFunctionTree tree1 = g.GetVariableValue<IFunctionTree>("FunctionTree", false);
    113109      int tree1Height = g.GetVariableValue<IntData>("TreeHeight", false).Data;
    114110      int tree1Size = g.GetVariableValue<IntData>("TreeSize", false).Data;
    115111
    116112      if(tree0Size == 1 && tree1Size == 1) {
    117         return CombineTerminals(gardener, tree0, tree1, random, maxTreeHeight, out newOperators);
     113        return CombineTerminals(gardener, tree0, tree1, random, maxTreeHeight, out newBranches);
    118114      } else {
    119115        // we are going to insert tree1 into tree0 at a random place so we have to make sure that tree0 is not a terminal
    120116        // in case both trees are higher than 1 we swap the trees with probability 50%
    121117        if(tree0Height == 1 || (tree1Height > 1 && random.Next(2) == 0)) {
    122           IOperator tmp = tree0; tree0 = tree1; tree1 = tmp;
     118          IFunctionTree tmp = tree0; tree0 = tree1; tree1 = tmp;
    123119          int tmpHeight = tree0Height; tree0Height = tree1Height; tree1Height = tmpHeight;
    124120          int tmpSize = tree0Size; tree0Size = tree1Size; tree1Size = tmpSize;
     
    126122
    127123        // save the root because later on we change tree0 and tree1 while searching a valid tree configuration
    128         IOperator root = tree0;
     124        IFunctionTree root = tree0;
    129125        int rootSize = tree0Size;
    130126
     
    132128        int tree0Level = random.Next(tree0Height - 1); // since we checked before that the height of tree0 is > 1 this is OK
    133129        int tree1Level = random.Next(tree1Height);
    134         tree0 = gardener.GetRandomNode(tree0, tree0Level);
    135         tree1 = gardener.GetRandomNode(tree1, tree1Level);
     130        tree0 = gardener.GetRandomBranch(tree0, tree0Level);
     131        tree1 = gardener.GetRandomBranch(tree1, tree1Level);
    136132
    137133        // recalculate the size and height of tree1 (the one that we want to insert) because we need to check constraints later on
     
    140136
    141137        List<int> possibleChildIndices = new List<int>();
    142         TreeGardener.OperatorEqualityComparer comparer = new TreeGardener.OperatorEqualityComparer();
    143138
    144139        // Now tree0 is supposed to take tree1 as one if its children. If this is not possible,
    145140        // then go down in either of the two trees as far as possible. If even then it is not possible
    146141        // to merge the trees then throw an exception
    147         // find the list of allowed indices (regarding allowed sub-operators, maxTreeSize and maxTreeHeight)
    148         for(int i = 0; i < tree0.SubOperators.Count; i++) {
    149           int subOperatorSize = gardener.GetTreeSize(tree0.SubOperators[i]);
    150 
    151           // the index is ok when the operator is allowed as sub-operator and we don't violate the maxSize and maxHeight constraints
    152           if(GetAllowedOperators(tree0, i).Contains(tree1, comparer) &&
    153             rootSize - subOperatorSize + tree1Size < maxTreeSize &&
     142        // find the list of allowed indices (regarding allowed sub-trees, maxTreeSize and maxTreeHeight)
     143        for(int i = 0; i < tree0.SubTrees.Count; i++) {
     144          int subTreeSize = gardener.GetTreeSize(tree0.SubTrees[i]);
     145
     146          // the index is ok when the function is allowed as sub-tree and we don't violate the maxSize and maxHeight constraints
     147          if(gardener.GetAllowedSubFunctions(tree0.Function, i).Contains(tree1.Function) &&
     148            rootSize - subTreeSize + tree1Size < maxTreeSize &&
    154149            tree0Level + tree1Height < maxTreeHeight) {
    155150            possibleChildIndices.Add(i);
     
    158153
    159154        while(possibleChildIndices.Count == 0) {
    160           // ok we couln't find a possible configuration given the current tree0 and tree1
     155          // we couln't find a possible configuration given the current tree0 and tree1
    161156          // possible reasons for this are:
    162           //  - tree1 is not allowed as sub-operator of tree0
     157          //  - tree1 is not allowed as sub-tree of tree0
    163158          //  - appending tree1 as child of tree0 would create a tree that exceedes the maxTreeHeight
    164159          //  - replacing any child of tree0 with tree1 woulde create a tree that exceedes the maxTeeSize
     
    166161          //  - go up in tree0 => the insert position allows larger trees
    167162          //  - go down in tree1 => the tree that is inserted becomes smaller
    168           //  - however we have to get lucky to solve the 'allowed sub-operators' problem
     163          //  - however we have to get lucky to solve the 'allowed sub-trees' problem
    169164          if(tree1Height == 1 || (tree0Level>0 && random.Next(2) == 0)) {
    170165            // go up in tree0
    171166            tree0Level--;
    172             tree0 = gardener.GetRandomNode(root, tree0Level);
    173           } else if(tree1.SubOperators.Count > 0) {
     167            tree0 = gardener.GetRandomBranch(root, tree0Level);
     168          } else if(tree1.SubTrees.Count > 0) {
    174169            // go down in node2:
    175             tree1 = tree1.SubOperators[random.Next(tree1.SubOperators.Count)];
     170            tree1 = tree1.SubTrees[random.Next(tree1.SubTrees.Count)];
    176171            tree1Size = gardener.GetTreeSize(tree1);
    177172            tree1Height = gardener.GetTreeHeight(tree1);
     
    183178          // recalculate the list of possible indices
    184179          possibleChildIndices.Clear();
    185           for(int i = 0; i < tree0.SubOperators.Count; i++) {
    186             int subOperatorSize = gardener.GetTreeSize(tree0.SubOperators[i]);
    187 
    188             // when the operator is allowed as sub-operator and we don't violate the maxSize and maxHeight constraints
     180          for(int i = 0; i < tree0.SubTrees.Count; i++) {
     181            int subTreeSize = gardener.GetTreeSize(tree0.SubTrees[i]);
     182
     183            // when the function is allowed as sub-tree and we don't violate the maxSize and maxHeight constraints
    189184            // the index is ok
    190             if(GetAllowedOperators(tree0, i).Contains(tree1, comparer) &&
    191               rootSize - subOperatorSize + tree1Size < maxTreeSize &&
     185            if(gardener.GetAllowedSubFunctions(tree0.Function, i).Contains(tree1.Function) &&
     186              rootSize - subTreeSize + tree1Size < maxTreeSize &&
    192187              tree0Level + tree1Height < maxTreeHeight) {
    193188              possibleChildIndices.Add(i);
     
    203198        // replace the existing sub-tree at a random index in tree0 with tree1
    204199        int selectedIndex = possibleChildIndices[random.Next(possibleChildIndices.Count)];
    205         tree0.RemoveSubOperator(selectedIndex);
    206         tree0.AddSubOperator(tree1, selectedIndex);
     200        tree0.RemoveSubTree(selectedIndex);
     201        tree0.InsertSubTree(selectedIndex, tree1);
    207202
    208203        // no new operators where needed
    209         newOperators = new List<IOperator>();
     204        newBranches = new List<IFunctionTree>();
    210205        return root;
    211206      }
    212207    }
    213208
    214     private ICollection<IOperator> GetAllowedOperators(IOperator tree0, int i) {
    215       ItemList slotList = (ItemList)tree0.GetVariable(GPOperatorLibrary.ALLOWED_SUBOPERATORS).Value;
    216       return ((ItemList)slotList[i]).OfType<IOperator>().ToArray();
    217     }
    218 
    219     private IOperator CombineTerminals(TreeGardener gardener, IOperator f, IOperator g, MersenneTwister random, int maxTreeHeight, out List<IOperator> newOperators) {
    220       newOperators = new List<IOperator>();
    221       ICollection<IOperator> possibleParents = gardener.GetPossibleParents(new List<IOperator>() { f, g });
     209
     210    // take f and g and create a tree that has f and g as sub-trees
     211    // example
     212    //       O
     213    //      /|\
     214    //     g 2 f
     215    //
     216    private IFunctionTree CombineTerminals(TreeGardener gardener, IFunctionTree f, IFunctionTree g, MersenneTwister random, int maxTreeHeight, out List<IFunctionTree> newBranches) {
     217      newBranches = new List<IFunctionTree>();
     218      // determine the set of possible parent functions
     219      ICollection<IFunction> possibleParents = gardener.GetPossibleParents(new List<IFunction>() { f.Function, g.Function });
    222220      if(possibleParents.Count == 0) throw new InvalidProgramException();
    223 
    224       IOperator parent = (IOperator)possibleParents.ElementAt(random.Next(possibleParents.Count())).Clone();
     221      // and select a random one
     222      IFunctionTree parent = new FunctionTree(possibleParents.ElementAt(random.Next(possibleParents.Count())));
    225223
    226224      int minArity;
    227225      int maxArity;
    228       gardener.GetMinMaxArity(parent, out minArity, out maxArity);
    229 
     226      gardener.GetMinMaxArity(parent.Function, out minArity, out maxArity);
    230227      int nSlots = Math.Max(2, minArity);
    231 
    232       HashSet<IOperator>[] slotSets = new HashSet<IOperator>[nSlots];
    233 
    234       SubOperatorsConstraintAnalyser analyser = new SubOperatorsConstraintAnalyser();
    235       analyser.AllPossibleOperators = new List<IOperator>() { g, f };
     228      // determine which slot can take which sub-trees
     229      List<IFunctionTree>[] slots = new List<IFunctionTree>[nSlots];
    236230      for(int slot = 0; slot < nSlots; slot++) {
    237         HashSet<IOperator> slotSet = new HashSet<IOperator>(analyser.GetAllowedOperators(parent, slot));
    238         slotSets[slot] = slotSet;
    239       }
    240 
    241       int[] slotSequence = Enumerable.Range(0, slotSets.Count()).OrderBy(slot => slotSets[slot].Count()).ToArray();
    242 
    243       IOperator[] selectedOperators = new IOperator[nSlots];
     231        ICollection<IFunction> allowedSubFunctions = gardener.GetAllowedSubFunctions(parent.Function, slot);
     232        List<IFunctionTree> allowedTrees = new List<IFunctionTree>();
     233        if(allowedSubFunctions.Contains(f.Function)) allowedTrees.Add(f);
     234        if(allowedSubFunctions.Contains(g.Function)) allowedTrees.Add(g);
     235        slots[slot] = allowedTrees;
     236      }
     237      // fill the slots in the order of degrees of freedom
     238      int[] slotSequence = Enumerable.Range(0, slots.Count()).OrderBy(slot => slots[slot].Count()).ToArray();
     239
     240      // tmp arry to store the tree for each sub-tree slot of the parent
     241      IFunctionTree[] selectedFunctionTrees = new IFunctionTree[nSlots];
     242
     243      // fill the sub-tree slots of the parent starting with the slots that can take potentially both functions (f and g)
    244244      for(int i = 0; i < slotSequence.Length; i++) {
    245245        int slot = slotSequence[i];
    246         HashSet<IOperator> slotSet = slotSets[slot];
    247         if(slotSet.Count() == 0) {
    248           var allowedOperators = GetAllowedOperators(parent, slot);
    249           selectedOperators[slot] = gardener.CreateRandomTree(allowedOperators, 1, 1, true);
    250           newOperators.AddRange(gardener.GetAllOperators(selectedOperators[slot]));
     246        List<IFunctionTree> allowedTrees = slots[slot];
     247        // when neither f nor g fit into the slot => create a new random tree
     248        if(allowedTrees.Count() == 0) {
     249          var allowedFunctions = gardener.GetAllowedSubFunctions(parent.Function, slot);
     250          selectedFunctionTrees[slot] = gardener.CreateRandomTree(allowedFunctions, 1, 1, true);
     251          newBranches.AddRange(gardener.GetAllSubTrees(selectedFunctionTrees[slot]));
    251252        } else {
    252           IOperator selectedOperator = slotSet.ElementAt(random.Next(slotSet.Count()));
    253           selectedOperators[slot] = selectedOperator;
     253          // select randomly which tree to insert into this slot
     254          IFunctionTree selectedTree = allowedTrees[random.Next(allowedTrees.Count())];
     255          selectedFunctionTrees[slot] = selectedTree;
     256          // remove the tree that we used in this slot from following function-sets
    254257          for(int j = i + 1; j < slotSequence.Length; j++) {
    255258            int otherSlot = slotSequence[j];
    256             slotSets[otherSlot].Remove(selectedOperator);
    257           }
    258         }
    259       }
    260 
    261       for(int i = 0; i < selectedOperators.Length; i++) {
    262         parent.AddSubOperator(selectedOperators[i], i);
     259            slots[otherSlot].Remove(selectedTree);
     260          }
     261        }
     262      }
     263      // actually append the sub-trees to the parent tree
     264      for(int i = 0; i < selectedFunctionTrees.Length; i++) {
     265        parent.InsertSubTree(i, selectedFunctionTrees[i]);
    263266      }
    264267
  • trunk/sources/HeuristicLab.StructureIdentification/TreeGardener.cs

    r23 r155  
    3131using HeuristicLab.Operators;
    3232using HeuristicLab.Selection;
     33using HeuristicLab.Functions;
     34using System.Collections;
    3335
    3436namespace HeuristicLab.StructureIdentification {
    3537  internal class TreeGardener {
    3638    private IRandom random;
    37     private IOperatorLibrary opLibrary;
    38     private List<IOperator> functions;
    39     private List<IOperator> terminals;
    40 
    41     internal IList<IOperator> Terminals {
     39    private GPOperatorLibrary funLibrary;
     40    private List<IFunction> functions;
     41    private List<IFunction> terminals;
     42
     43    internal IList<IFunction> Terminals {
    4244      get { return terminals.AsReadOnly(); }
    4345    }
    44     private List<IOperator> allOperators;
    45 
    46     internal IList<IOperator> AllOperators {
    47       get { return allOperators.AsReadOnly(); }
    48     }
    49 
    50     internal TreeGardener(IRandom random, IOperatorLibrary opLibrary) {
     46    private List<IFunction> allFunctions;
     47
     48    internal IList<IFunction> AllFunctions {
     49      get { return allFunctions.AsReadOnly(); }
     50    }
     51
     52    internal TreeGardener(IRandom random, GPOperatorLibrary funLibrary) {
    5153      this.random = random;
    52       this.opLibrary = opLibrary;
    53 
    54       this.allOperators = new List<IOperator>();
    55       terminals = new List<IOperator>();
    56       functions = new List<IOperator>();
     54      this.funLibrary = funLibrary;
     55
     56      this.allFunctions = new List<IFunction>();
     57      terminals = new List<IFunction>();
     58      functions = new List<IFunction>();
    5759
    5860      // init functions and terminals based on constraints
    59       foreach (IOperator op in opLibrary.Group.Operators) {
     61      foreach (IFunction fun in funLibrary.Group.Operators) {
    6062        int maxA, minA;
    61         GetMinMaxArity(op, out minA, out maxA);
     63        GetMinMaxArity(fun, out minA, out maxA);
    6264        if (maxA == 0) {
    63           terminals.Add(op);
     65          terminals.Add(fun);
    6466        } else {
    65           functions.Add(op);
    66         }
    67       }
    68 
    69       allOperators.AddRange(functions);
    70       allOperators.AddRange(terminals);
     67          functions.Add(fun);
     68        }
     69      }
     70
     71      allFunctions.AddRange(functions);
     72      allFunctions.AddRange(terminals);
    7173    }
    7274
    7375    #region random initialization
    74     internal IOperator CreateRandomTree(ICollection<IOperator> allowedOperators, int maxTreeSize, int maxTreeHeight, bool balanceTrees) {
    75 
    76       int minTreeHeight = allowedOperators.Select(op => ((IntData)op.GetVariable(GPOperatorLibrary.MIN_TREE_HEIGHT).Value).Data).Min();
     76    internal IFunctionTree CreateRandomTree(ICollection<IFunction> allowedFunctions, int maxTreeSize, int maxTreeHeight, bool balanceTrees) {
     77
     78      int minTreeHeight = allowedFunctions.Select(f => ((IntData)f.GetVariable(GPOperatorLibrary.MIN_TREE_HEIGHT).Value).Data).Min();
    7779      if (minTreeHeight > maxTreeHeight)
    7880        maxTreeHeight = minTreeHeight;
    7981
    80       int minTreeSize = allowedOperators.Select(op => ((IntData)op.GetVariable(GPOperatorLibrary.MIN_TREE_SIZE).Value).Data).Min();
     82      int minTreeSize = allowedFunctions.Select(f => ((IntData)f.GetVariable(GPOperatorLibrary.MIN_TREE_SIZE).Value).Data).Min();
    8183      if (minTreeSize > maxTreeSize)
    8284        maxTreeSize = minTreeSize;
     
    8587      int treeSize = random.Next(minTreeSize, maxTreeSize + 1);
    8688
    87       IOperator[] possibleOperators = allowedOperators.Where(op => ((IntData)op.GetVariable(GPOperatorLibrary.MIN_TREE_HEIGHT).Value).Data <= treeHeight &&
    88         ((IntData)op.GetVariable(GPOperatorLibrary.MIN_TREE_SIZE).Value).Data <= treeSize).ToArray();
    89       IOperator selectedOperator = (IOperator)possibleOperators[random.Next(possibleOperators.Length)].Clone();
    90 
    91       IOperator rootOperator = CreateRandomTree(selectedOperator, treeSize, treeHeight, balanceTrees);
    92 
    93       return rootOperator;
    94     }
    95 
    96     internal IOperator CreateRandomTree(int maxTreeSize, int maxTreeHeight, bool balanceTrees) {
     89      IFunction[] possibleFunctions = allowedFunctions.Where(f => ((IntData)f.GetVariable(GPOperatorLibrary.MIN_TREE_HEIGHT).Value).Data <= treeHeight &&
     90        ((IntData)f.GetVariable(GPOperatorLibrary.MIN_TREE_SIZE).Value).Data <= treeSize).ToArray();
     91      IFunction selectedFunction = possibleFunctions[random.Next(possibleFunctions.Length)];
     92
     93      return CreateRandomTree(selectedFunction, treeSize, treeHeight, balanceTrees);
     94    }
     95
     96    internal IFunctionTree CreateRandomTree(int maxTreeSize, int maxTreeHeight, bool balanceTrees) {
    9797      if (balanceTrees) {
    9898        if (maxTreeHeight == 1 || maxTreeSize==1) {
    99           IOperator selectedTerminal = (IOperator)terminals[random.Next(terminals.Count())].Clone();
    100           return selectedTerminal;
     99          IFunction selectedTerminal = terminals[random.Next(terminals.Count())];
     100          return new FunctionTree(selectedTerminal);
    101101        } else {
    102           IOperator[] possibleFunctions = functions.Where(f => GetMinimalTreeHeight(f) <= maxTreeHeight &&
     102          IFunction[] possibleFunctions = functions.Where(f => GetMinimalTreeHeight(f) <= maxTreeHeight &&
    103103            GetMinimalTreeSize(f) <= maxTreeSize).ToArray();
    104           IOperator selectedFunction = (IOperator)possibleFunctions[random.Next(possibleFunctions.Length)].Clone();
    105           MakeBalancedTree(selectedFunction, maxTreeSize - 1, maxTreeHeight - 1);
    106           return selectedFunction;
     104          IFunction selectedFunction = possibleFunctions[random.Next(possibleFunctions.Length)];
     105          FunctionTree root = new FunctionTree(selectedFunction);
     106          MakeBalancedTree(root, maxTreeSize - 1, maxTreeHeight - 1);
     107          return root;
    107108        }
    108109
    109110      } else {
    110         IOperator[] possibleOperators = allOperators.Where(op => GetMinimalTreeHeight(op) <= maxTreeHeight &&
    111           GetMinimalTreeSize(op) <= maxTreeSize).ToArray();
    112         IOperator selectedOperator = (IOperator)possibleOperators[random.Next(possibleOperators.Length)].Clone();
    113         MakeUnbalancedTree(selectedOperator, maxTreeSize - 1, maxTreeHeight - 1);
    114         return selectedOperator;
    115       }
    116     }
    117 
    118     internal IOperator CreateRandomTree(IOperator root, int maxTreeSize, int maxTreeHeight, bool balanceTrees) {
     111        IFunction[] possibleFunctions = allFunctions.Where(f => GetMinimalTreeHeight(f) <= maxTreeHeight &&
     112          GetMinimalTreeSize(f) <= maxTreeSize).ToArray();
     113        IFunction selectedFunction = possibleFunctions[random.Next(possibleFunctions.Length)];
     114        FunctionTree root = new FunctionTree(selectedFunction);
     115        MakeUnbalancedTree(root, maxTreeSize - 1, maxTreeHeight - 1);
     116        return root;
     117      }
     118    }
     119
     120    internal IFunctionTree CreateRandomTree(IFunction rootFunction, int maxTreeSize, int maxTreeHeight, bool balanceTrees) {
     121      IFunctionTree root = new FunctionTree(rootFunction);
    119122      if (balanceTrees) {
    120123        MakeBalancedTree(root, maxTreeSize - 1, maxTreeHeight - 1);
     
    130133
    131134
    132     private void MakeUnbalancedTree(IOperator parent, int maxTreeSize, int maxTreeHeight) {
     135    private void MakeUnbalancedTree(IFunctionTree parent, int maxTreeSize, int maxTreeHeight) {
    133136      if (maxTreeHeight == 0 || maxTreeSize == 0) return;
    134137      int minArity;
    135138      int maxArity;
    136       GetMinMaxArity(parent, out minArity, out maxArity);
     139      GetMinMaxArity(parent.Function, out minArity, out maxArity);
    137140      if (maxArity >= maxTreeSize) {
    138141        maxArity = maxTreeSize;
     
    142145        int maxSubTreeSize = maxTreeSize / actualArity;
    143146        for (int i = 0; i < actualArity; i++) {
    144           IOperator[] possibleOperators = GetAllowedSubOperators(parent, i).Where(op => GetMinimalTreeHeight(op) <= maxTreeHeight &&
    145             GetMinimalTreeSize(op) <= maxSubTreeSize).ToArray();
    146           IOperator selectedOperator = (IOperator)possibleOperators[random.Next(possibleOperators.Length)].Clone();
    147           parent.AddSubOperator(selectedOperator, i);
    148           MakeUnbalancedTree(selectedOperator, maxSubTreeSize - 1, maxTreeHeight - 1);
     147          IFunction[] possibleFunctions = GetAllowedSubFunctions(parent.Function, i).Where(f => GetMinimalTreeHeight(f) <= maxTreeHeight &&
     148            GetMinimalTreeSize(f) <= maxSubTreeSize).ToArray();
     149          IFunction selectedFunction = possibleFunctions[random.Next(possibleFunctions.Length)];
     150          FunctionTree newSubTree = new FunctionTree(selectedFunction);
     151          MakeUnbalancedTree(newSubTree, maxSubTreeSize - 1, maxTreeHeight - 1);
     152          parent.InsertSubTree(i, newSubTree);
    149153        }
    150154      }
     
    152156
    153157    // NOTE: this method doesn't build fully balanced trees because we have constraints on the
    154     // types of possible suboperators which can indirectly impose a limit for the depth of a given suboperator
    155     private void MakeBalancedTree(IOperator parent, int maxTreeSize, int maxTreeHeight) {
     158    // types of possible sub-functions which can indirectly impose a limit for the depth of a given sub-tree
     159    private void MakeBalancedTree(IFunctionTree parent, int maxTreeSize, int maxTreeHeight) {
    156160      if (maxTreeHeight == 0 || maxTreeSize == 0) return; // should never happen anyway
    157161      int minArity;
    158162      int maxArity;
    159       GetMinMaxArity(parent, out minArity, out maxArity);
     163      GetMinMaxArity(parent.Function, out minArity, out maxArity);
    160164      if (maxArity >= maxTreeSize) {
    161165        maxArity = maxTreeSize;
     
    166170        for (int i = 0; i < actualArity; i++) {
    167171          if (maxTreeHeight == 1 || maxSubTreeSize == 1) {
    168             IOperator[] possibleTerminals = GetAllowedSubOperators(parent, i).Where(
    169               op => GetMinimalTreeHeight(op) <= maxTreeHeight &&
    170               GetMinimalTreeSize(op) <= maxSubTreeSize &&
    171               IsTerminal(op)).ToArray();
    172             IOperator selectedTerminal = (IOperator)possibleTerminals[random.Next(possibleTerminals.Length)].Clone();
    173             parent.AddSubOperator(selectedTerminal, i);
     172            IFunction[] possibleTerminals = GetAllowedSubFunctions(parent.Function, i).Where(
     173              f => GetMinimalTreeHeight(f) <= maxTreeHeight &&
     174              GetMinimalTreeSize(f) <= maxSubTreeSize &&
     175              IsTerminal(f)).ToArray();
     176            IFunction selectedTerminal = possibleTerminals[random.Next(possibleTerminals.Length)];
     177            IFunctionTree newTree = new FunctionTree(selectedTerminal);
     178            parent.InsertSubTree(i, newTree);
    174179          } else {
    175             IOperator[] possibleFunctions = GetAllowedSubOperators(parent, i).Where(
    176               op => GetMinimalTreeHeight(op) <= maxTreeHeight &&
    177               GetMinimalTreeSize(op) <= maxSubTreeSize &&
    178               !IsTerminal(op)).ToArray();
    179             IOperator selectedFunction = (IOperator)possibleFunctions[random.Next(possibleFunctions.Length)].Clone();
    180             parent.AddSubOperator(selectedFunction, i);
    181             MakeBalancedTree(selectedFunction, maxSubTreeSize - 1, maxTreeHeight - 1);
     180            IFunction[] possibleFunctions = GetAllowedSubFunctions(parent.Function, i).Where(
     181              f => GetMinimalTreeHeight(f) <= maxTreeHeight &&
     182              GetMinimalTreeSize(f) <= maxSubTreeSize &&
     183              !IsTerminal(f)).ToArray();
     184            IFunction selectedFunction = possibleFunctions[random.Next(possibleFunctions.Length)];
     185            FunctionTree newTree = new FunctionTree(selectedFunction);
     186            parent.InsertSubTree(i, newTree);
     187            MakeBalancedTree(newTree, maxSubTreeSize - 1, maxTreeHeight - 1);
    182188          }
    183189        }
     
    185191    }
    186192
    187     internal CompositeOperation CreateInitializationOperation(ICollection<IOperator> operators, IScope scope) {
     193    internal CompositeOperation CreateInitializationOperation(ICollection<IFunctionTree> trees, IScope scope) {
    188194      // needed for the parameter shaking operation
    189195      CompositeOperation initializationOperation = new CompositeOperation();
    190196      Scope tempScope = new Scope("Temp. initialization scope");
    191197
    192       var parametricOperators = operators.Where(o => o.GetVariable(GPOperatorLibrary.INITIALIZATION) != null);
    193 
    194       foreach (IOperator op in parametricOperators) {
     198      var parametricTrees = trees.Where(t => t.Function.GetVariable(GPOperatorLibrary.INITIALIZATION) != null);
     199
     200      foreach (IFunctionTree tree in parametricTrees) {
    195201        // enqueue an initialization operation for each operator with local variables
    196         IOperator initialization = (IOperator)op.GetVariable(GPOperatorLibrary.INITIALIZATION).Value;
     202        IOperator initialization = (IOperator)tree.Function.GetVariable(GPOperatorLibrary.INITIALIZATION).Value;
    197203        Scope initScope = new Scope();
    198204
    199205        // copy the local variables into a temporary scope used for initialization
    200         foreach (VariableInfo info in op.VariableInfos) {
    201           if (info.Local) {
    202             initScope.AddVariable(op.GetVariable(info.FormalName));
    203           }
     206        foreach (IVariable variable in tree.LocalVariables) {
     207          initScope.AddVariable(variable);
    204208        }
    205209
     
    223227
    224228    #region tree information gathering
    225     internal int GetTreeSize(IOperator tree) {
    226       return 1 + tree.SubOperators.Sum(f => GetTreeSize(f));
    227     }
    228 
    229     internal int GetTreeHeight(IOperator tree) {
    230       if (tree.SubOperators.Count == 0) return 1;
    231       return 1 + tree.SubOperators.Max(f => GetTreeHeight(f));
    232     }
    233 
    234     internal IOperator GetRandomParentNode(IOperator tree) {
    235       List<IOperator> parentNodes = new List<IOperator>();
     229    internal int GetTreeSize(IFunctionTree tree) {
     230      return 1 + tree.SubTrees.Sum(f => GetTreeSize(f));
     231    }
     232
     233    internal int GetTreeHeight(IFunctionTree tree) {
     234      if (tree.SubTrees.Count == 0) return 1;
     235      return 1 + tree.SubTrees.Max(f => GetTreeHeight(f));
     236    }
     237
     238    internal IFunctionTree GetRandomParentNode(IFunctionTree tree) {
     239      List<IFunctionTree> parentNodes = new List<IFunctionTree>();
    236240
    237241      // add null for the parent of the root node
    238242      parentNodes.Add(null);
    239243
    240       TreeForEach(tree, delegate(IOperator op) {
    241         if (op.SubOperators.Count > 0) {
    242           parentNodes.Add(op);
     244      TreeForEach(tree, delegate(IFunctionTree possibleParentNode) {
     245        if (possibleParentNode.SubTrees.Count > 0) {
     246          parentNodes.Add(possibleParentNode);
    243247        }
    244248      });
     
    247251    }
    248252
    249     internal IList<IOperator> GetAllowedSubOperators(IOperator op, int index) {
    250       if (op == null) {
    251         return allOperators;
     253    internal IList<IFunction> GetAllowedSubFunctions(IFunction f, int index) {
     254      if (f == null) {
     255        return allFunctions;
    252256      } else {
    253 
    254         SubOperatorsConstraintAnalyser analyser = new SubOperatorsConstraintAnalyser();
    255         analyser.AllPossibleOperators = allOperators;
    256 
    257         return analyser.GetAllowedOperators(op, index);
    258       }
    259     }
    260     internal void GetMinMaxArity(IOperator root, out int minArity, out int maxArity) {
    261       foreach (IConstraint constraint in root.Constraints) {
     257        ItemList slotList = (ItemList)f.GetVariable(GPOperatorLibrary.ALLOWED_SUBOPERATORS).Value;
     258        List<IFunction> result = new List<IFunction>();
     259        foreach(IFunction function in (ItemList)slotList[index]) {
     260          result.Add(function);
     261        }
     262        return result;
     263      }
     264    }
     265    internal void GetMinMaxArity(IFunction f, out int minArity, out int maxArity) {
     266      foreach (IConstraint constraint in f.Constraints) {
    262267        NumberOfSubOperatorsConstraint theConstraint = constraint as NumberOfSubOperatorsConstraint;
    263268        if (theConstraint != null) {
     
    271276      maxArity = 2;
    272277    }
    273     internal bool IsTerminal(IOperator f) {
     278    internal bool IsTerminal(IFunction f) {
    274279      int minArity;
    275280      int maxArity;
     
    278283    }
    279284
    280     internal IList<IOperator> GetAllowedParents(IOperator child, int childIndex) {
    281       List<IOperator> parents = new List<IOperator>();
    282       foreach (IOperator function in functions) {
    283         IList<IOperator> allowedSubOperators = GetAllowedSubOperators(function, childIndex);
    284         if (allowedSubOperators.Contains(child, new OperatorEqualityComparer())) {
     285    internal IList<IFunction> GetAllowedParents(IFunction child, int childIndex) {
     286      List<IFunction> parents = new List<IFunction>();
     287      foreach (IFunction function in functions) {
     288        ICollection<IFunction> allowedSubFunctions = GetAllowedSubFunctions(function, childIndex);
     289        if (allowedSubFunctions.Contains(child)) {
    285290          parents.Add(function);
    286291        }
     
    289294    }
    290295
    291     internal ICollection<IOperator> GetAllOperators(IOperator root) {
    292       List<IOperator> allOps = new List<IOperator>();
    293       TreeForEach(root, t => { allOps.Add(t); });
    294       return allOps;
     296    internal ICollection<IFunctionTree> GetAllSubTrees(IFunctionTree root) {
     297      List<IFunctionTree> allTrees = new List<IFunctionTree>();
     298      TreeForEach(root, t => { allTrees.Add(t); });
     299      return allTrees;
    295300    }
    296301
    297302    /// <summary>
    298     /// returns the height level of op in the tree
    299     /// if the op == tree => 1
    300     /// if op is in the suboperators of tree => 2
     303    /// returns the height level of branch in the tree
     304    /// if the branch == tree => 1
     305    /// if branch is in the sub-trees of tree => 2
    301306    /// ...
    302     /// if op is not found => -1
     307    /// if branch is not found => -1
    303308    /// </summary>
    304     /// <param name="tree">operator tree to process</param>
    305     /// <param name="op">operater that is searched in the tree</param>
     309    /// <param name="tree">root of the function tree to process</param>
     310    /// <param name="branch">branch that is searched in the tree</param>
    306311    /// <returns></returns>
    307     internal int GetNodeLevel(IOperator tree, IOperator op) {
    308       return GetNodeLevelHelper(tree, op, 1);
    309     }
    310 
    311     private int GetNodeLevelHelper(IOperator tree, IOperator op, int level) {
    312       if (op == tree) return level;
    313 
    314       foreach (IOperator subTree in tree.SubOperators) {
    315         int result = GetNodeLevelHelper(subTree, op, level + 1);
     312    internal int GetBranchLevel(IFunctionTree tree, IFunctionTree branch) {
     313      return GetBranchLevelHelper(tree, branch, 1);
     314    }
     315
     316    // 'tail-recursive' helper
     317    private int GetBranchLevelHelper(IFunctionTree tree, IFunctionTree branch, int level) {
     318      if (branch == tree) return level;
     319
     320      foreach (IFunctionTree subTree in tree.SubTrees) {
     321        int result = GetBranchLevelHelper(subTree, branch, level + 1);
    316322        if (result != -1) return result;
    317323      }
     
    320326    }
    321327
    322     internal bool IsValidTree(IOperator tree) {
    323       if (!tree.IsValid())
    324         return false;
    325       foreach (IOperator subTree in tree.SubOperators) {
    326         if (!subTree.IsValid())
    327           return false;
    328       }
    329 
     328    internal bool IsValidTree(IFunctionTree tree) {
     329      foreach(IConstraint constraint in tree.Function.Constraints) {
     330        if(constraint is NumberOfSubOperatorsConstraint) {
     331          int max = ((NumberOfSubOperatorsConstraint)constraint).MaxOperators.Data;
     332          int min = ((NumberOfSubOperatorsConstraint)constraint).MinOperators.Data;
     333          if(tree.SubTrees.Count < min || tree.SubTrees.Count > max)
     334            return false;
     335        }
     336      }
     337      foreach(IFunctionTree subTree in tree.SubTrees) {
     338        if(!IsValidTree(subTree)) return false;
     339      }
    330340      return true;
    331341    }
    332342
    333     // returns a random node from the specified level in the tree
    334     internal IOperator GetRandomNode(IOperator tree, int level) {
     343    // returns a random branch from the specified level in the tree
     344    internal IFunctionTree GetRandomBranch(IFunctionTree tree, int level) {
    335345      if (level == 0) return tree;
    336       List<IOperator> nodes = GetOperatorsAtLevel(tree, level);
    337       return nodes[random.Next(nodes.Count)];
     346      List<IFunctionTree> branches = GetBranchesAtLevel(tree, level);
     347      return branches[random.Next(branches.Count)];
    338348    }
    339349    #endregion
     
    349359    }
    350360
    351     private void TreeForEach(IOperator tree, Action<IOperator> action) {
     361    private void TreeForEach(IFunctionTree tree, Action<IFunctionTree> action) {
    352362      action(tree);
    353       foreach (IOperator child in tree.SubOperators) {
    354         TreeForEach(child, action);
    355       }
    356     }
    357 
    358     private List<IOperator> GetOperatorsAtLevel(IOperator tree, int level) {
    359       if (level == 1) return new List<IOperator>(tree.SubOperators);
    360 
    361       List<IOperator> result = new List<IOperator>();
    362       foreach (IOperator subOperator in tree.SubOperators) {
    363         result.AddRange(GetOperatorsAtLevel(subOperator, level - 1));
     363      foreach (IFunctionTree subTree in tree.SubTrees) {
     364        TreeForEach(subTree, action);
     365      }
     366    }
     367
     368    private List<IFunctionTree> GetBranchesAtLevel(IFunctionTree tree, int level) {
     369      if (level == 1) return new List<IFunctionTree>(tree.SubTrees);
     370
     371      List<IFunctionTree> branches = new List<IFunctionTree>();
     372      foreach (IFunctionTree subTree in tree.SubTrees) {
     373        branches.AddRange(GetBranchesAtLevel(subTree, level - 1));
     374      }
     375      return branches;
     376    }
     377
     378
     379    #endregion
     380
     381    internal ICollection<IFunction> GetPossibleParents(List<IFunction> list) {
     382      List<IFunction> result = new List<IFunction>();
     383      foreach (IFunction f in functions) {
     384        if (IsPossibleParent(f, list)) {
     385          result.Add(f);
     386        }
    364387      }
    365388      return result;
    366389    }
    367390
    368 
    369     #endregion
    370 
    371     internal class OperatorEqualityComparer : IEqualityComparer<IOperator> {
    372       #region IEqualityComparer<IOperator> Members
    373 
    374       public bool Equals(IOperator x, IOperator y) {
    375         return ((StringData)x.GetVariable(GPOperatorLibrary.TYPE_ID).Value).Data ==
    376           ((StringData)y.GetVariable(GPOperatorLibrary.TYPE_ID).Value).Data;
    377       }
    378 
    379       public int GetHashCode(IOperator obj) {
    380         return ((StringData)obj.GetVariable(GPOperatorLibrary.TYPE_ID).Value).Data.GetHashCode();
    381       }
    382 
    383       #endregion
    384     }
    385 
    386     internal ICollection<IOperator> GetPossibleParents(List<IOperator> list) {
    387       List<IOperator> result = new List<IOperator>();
    388       foreach (IOperator op in functions) {
    389         if (IsPossibleParent(op, list)) {
    390           result.Add(op);
    391         }
    392       }
    393       return result;
    394     }
    395 
    396     private bool IsPossibleParent(IOperator op, List<IOperator> children) {
     391    private bool IsPossibleParent(IFunction f, List<IFunction> children) {
    397392      int minArity;
    398393      int maxArity;
    399       GetMinMaxArity(op, out minArity, out maxArity);
     394      GetMinMaxArity(f, out minArity, out maxArity);
    400395
    401396      // note: we can't assume that the operators in the children list have different types!
     
    409404
    410405      SubOperatorsConstraintAnalyser analyzer = new SubOperatorsConstraintAnalyser();
    411       analyzer.AllPossibleOperators = children;
    412 
    413       List<HashSet<IOperator>> slotSets = new List<HashSet<IOperator>>();
    414 
    415       // we iterate through all slots for sub-operators and calculate the set of
    416       // allowed sub-operators for this slot.
     406      analyzer.AllPossibleOperators = children.Cast<IOperator>().ToArray<IOperator>();
     407
     408      List<HashSet<IFunction>> slotSets = new List<HashSet<IFunction>>();
     409
     410      // we iterate through all slots for sub-trees and calculate the set of
     411      // allowed functions for this slot.
    417412      // we only count those slots that can hold at least one of the children that we should combine
    418413      for (int slot = 0; slot < nSlots; slot++) {
    419         HashSet<IOperator> operatorSet = new HashSet<IOperator>(analyzer.GetAllowedOperators(op, slot));
    420         if (operatorSet.Count() > 0) {
    421           slotSets.Add(operatorSet);
     414        HashSet<IFunction> functionSet = new HashSet<IFunction>(analyzer.GetAllowedOperators(f, slot).Cast<IFunction>());
     415        if (functionSet.Count() > 0) {
     416          slotSets.Add(functionSet);
    422417        }
    423418      }
     
    426421      // hold one of our children.
    427422      // if the number of slots is smaller than the number of children we can be sure that
    428       // we can never combine all children as sub-operators of the operator and thus the operator
     423      // we can never combine all children as sub-trees of the function and thus the function
    429424      // can't be a parent.
    430425      if (slotSets.Count() < children.Count()) {
     
    433428
    434429      // finally we sort the sets by size and beginning from the first set select one
    435       // operator for the slot and thus remove it as possible sub-operator from the remaining sets.
    436       // when we can successfully assign all available children to a slot the operator is a valid parent
    437       // when only a subset of all children can be assigned to slots the operator is no valid parent
     430      // function for the slot and thus remove it as possible sub-tree from the remaining sets.
     431      // when we can successfully assign all available children to a slot the function is a valid parent
     432      // when only a subset of all children can be assigned to slots the function is no valid parent
    438433      slotSets.Sort((p, q) => p.Count() - q.Count());
    439434
     
    441436      for (int i = 0; i < slotSets.Count() - 1; i++) {
    442437        if (slotSets[i].Count > 0) {
    443           IOperator selected = slotSets[i].ElementAt(0);
     438          IFunction selected = slotSets[i].ElementAt(0);
    444439          assignments++;
    445440          for (int j = i + 1; j < slotSets.Count(); j++) {
Note: See TracChangeset for help on using the changeset viewer.