- Timestamp:
- 04/22/08 18:05:14 (16 years ago)
- Location:
- trunk/sources
- Files:
-
- 1 deleted
- 44 edited
- 3 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/sources/HeuristicLab.Constraints/SubOperatorsConstraintAnalyser.cs
r2 r155 91 91 private static bool InSet(IOperator op, ICollection<IOperator> set) { 92 92 foreach(IOperator element in set) { 93 if(((StringData)element.GetVariable("TypeId").Value).Data == 93 if(element==op || 94 ((StringData)element.GetVariable("TypeId").Value).Data == 94 95 ((StringData)op.GetVariable("TypeId").Value).Data) { 95 96 return true; -
trunk/sources/HeuristicLab.Functions/Addition.cs
r2 r155 33 33 public override string Description { 34 34 get { 35 return @"Returns the sum of all sub- operatorresults.35 return @"Returns the sum of all sub-tree results. 36 36 (+ 3) => 3 37 37 (+ 2 3) => 5 … … 46 46 } 47 47 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) { 54 49 // (+ 3) => 3 55 50 // (+ 2 3) => 5 56 51 // (+ 3 4 5) => 12 57 52 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]; 60 55 } 61 56 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;68 57 } 69 58 -
trunk/sources/HeuristicLab.Functions/And.cs
r2 r155 31 31 public override string Description { 32 32 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. 34 AND is a special form, sub-trees are evaluated from the first to the last. Evaluation is 35 stopped as soon as one of the sub-trees evaluates to 0.0 (false)."; 34 36 } 35 37 } … … 40 42 } 41 43 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 51 49 else if(result != 1.0) return double.NaN; 52 50 } 51 // all sub-trees evaluated to 1.0 (true) => return 1.0 (true) 53 52 return 1.0; 54 53 } 55 54 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(); 60 57 } 61 58 -
trunk/sources/HeuristicLab.Functions/Average.cs
r2 r155 31 31 public override string Description { 32 32 get { 33 return @"Returns the average (arithmetic mean) of all sub- operatorresults.";33 return @"Returns the average (arithmetic mean) of all sub-tree results."; 34 34 } 35 35 } … … 40 40 } 41 41 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) { 48 43 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]; 51 46 } 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; 59 48 } 60 49 -
trunk/sources/HeuristicLab.Functions/Constant.cs
r2 r155 31 31 namespace HeuristicLab.Functions { 32 32 public class Constant : FunctionBase { 33 34 private IVariable value; 33 public static readonly string VALUE = "Value"; 35 34 36 35 public override string Description { … … 38 37 } 39 38 40 public ConstrainedDoubleData Value {41 get {42 return (ConstrainedDoubleData)value.Value;43 }44 }45 46 39 public Constant() 47 40 : 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; 50 43 51 44 ConstrainedDoubleData valueData = new ConstrainedDoubleData(); 52 45 // initialize a default range for the contant value 53 46 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); 58 49 59 50 // constant can't have suboperators … … 61 52 } 62 53 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; 66 57 } 67 58 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(); 83 62 } 84 63 -
trunk/sources/HeuristicLab.Functions/Cosinus.cs
r2 r155 31 31 public class Cosinus : FunctionBase { 32 32 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."; } 34 34 } 35 35 36 36 public Cosinus() 37 37 : base() { 38 39 38 // must have exactly one subfunction 40 39 AddConstraint(new NumberOfSubOperatorsConstraint(1, 1)); 41 40 } 42 41 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]); 45 44 } 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 57 45 58 46 public override void Accept(IFunctionVisitor visitor) { -
trunk/sources/HeuristicLab.Functions/Division.cs
r2 r155 36 36 get { 37 37 return @"Protected division 38 Divides the result of the first sub- operator by the results of the following sub-operators.38 Divides the result of the first sub-tree by the results of the following sub-tree. 39 39 In case one of the divisors is 0 returns 0. 40 40 (/ 3) => 1/3 … … 48 48 public Division() 49 49 : base() { 50 51 50 // 2 - 3 seems like an reasonable defaut (used for +,-,*,/) (discussion with swinkler and maffenze) 52 51 AddConstraint(new NumberOfSubOperatorsConstraint(2, 3)); 53 52 } 54 53 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) { 60 55 // (/ 3) => 1/3 61 56 // (/ 2 3) => 2/3 62 57 // (/ 3 4 5) => 3/20 63 58 64 if( SubFunctions.Count== 1) {65 double divisor = SubFunctions[0].Evaluate(dataset, sampleIndex);59 if(args.Length == 1) { 60 double divisor = args[0]; 66 61 if(Math.Abs(divisor) < EPSILON) return 0; 67 62 else return 1.0 / divisor; 68 63 } 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]; 72 67 if(Math.Abs(divisor) < EPSILON) return 0.0; 73 68 result /= divisor; … … 77 72 } 78 73 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 85 74 public override void Accept(IFunctionVisitor visitor) { 86 75 visitor.Visit(this); -
trunk/sources/HeuristicLab.Functions/Equal.cs
r2 r155 31 31 public override string Description { 32 32 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."; 34 34 } 35 35 } … … 40 40 } 41 41 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; 49 44 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;56 45 } 57 46 -
trunk/sources/HeuristicLab.Functions/Exponential.cs
r2 r155 31 31 public class Exponential : FunctionBase { 32 32 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))."; } 34 34 } 35 35 … … 39 39 AddConstraint(new NumberOfSubOperatorsConstraint(1, 1)); 40 40 } 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]); 43 44 } 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 56 45 57 46 public override void Accept(IFunctionVisitor visitor) { -
trunk/sources/HeuristicLab.Functions/FunctionBase.cs
r2 r155 29 29 30 30 namespace 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> 31 35 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); 37 46 } 38 47 } 39 48 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(); 44 54 } 45 46 // reference to the 'type' of the function47 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 85 55 public virtual void Accept(IFunctionVisitor visitor) { 86 56 visitor.Visit(this); 87 57 } 88 58 59 private static readonly List<IOperator> emptySubOperatorList = new List<IOperator>(); 60 public override IList<IOperator> SubOperators { 61 get { return emptySubOperatorList; } 62 } 63 89 64 public override void AddSubOperator(IOperator subOperator) { 90 subFunctions.Add((IFunction)subOperator);65 throw new NotSupportedException(); 91 66 } 92 67 93 68 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(); 101 70 } 102 71 103 72 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(); 110 74 } 111 75 112 76 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(); 119 78 } 120 79 121 80 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(); 129 82 } 130 83 131 84 public override void AddSubOperator(IOperator subOperator, int index) { 132 subFunctions.Insert(index, (IFunction)subOperator);85 throw new NotSupportedException(); 133 86 } 134 87 135 88 public override void RemoveSubOperator(int index) { 136 if (index >= subFunctions.Count) throw new InvalidOperationException(); 137 subFunctions.RemoveAt(index); 89 throw new NotSupportedException(); 138 90 } 139 91 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 172 92 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(); 181 94 } 182 95 183 96 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(); 332 98 } 333 99 } -
trunk/sources/HeuristicLab.Functions/FunctionView.Designer.cs
r2 r155 22 22 using System; 23 23 namespace HeuristicLab.Functions { 24 partial class Function View {24 partial class FunctionTreeView { 25 25 /// <summary> 26 26 /// Required designer variable. … … 167 167 this.copyToClipboardMenuItem}); 168 168 this.treeNodeContextMenu.Name = "treeNodeContextMenu"; 169 this.treeNodeContextMenu.Size = new System.Drawing.Size(2 59, 26);169 this.treeNodeContextMenu.Size = new System.Drawing.Size(248, 26); 170 170 // 171 171 // copyToClipboardMenuItem 172 172 // 173 173 this.copyToClipboardMenuItem.Name = "copyToClipboardMenuItem"; 174 this.copyToClipboardMenuItem.Size = new System.Drawing.Size(2 58, 22);174 this.copyToClipboardMenuItem.Size = new System.Drawing.Size(247, 22); 175 175 this.copyToClipboardMenuItem.Text = "Copy to clip-board (Model-Analyzer)"; 176 176 this.copyToClipboardMenuItem.Click += new System.EventHandler(this.copyToClipboardMenuItem_Click); -
trunk/sources/HeuristicLab.Functions/FunctionView.cs
r2 r155 30 30 using HeuristicLab.Core; 31 31 using HeuristicLab.PluginInfrastructure; 32 using HeuristicLab.Data; 32 33 33 34 namespace HeuristicLab.Functions { 34 public partial class Function View : 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; 38 39 private IVariable selectedVariable; 39 40 40 41 private FunctionNameVisitor functionNameVisitor; 41 public Function View() {42 public FunctionTreeView() { 42 43 InitializeComponent(); 43 44 functionNameVisitor = new FunctionNameVisitor(); 44 45 } 45 46 46 public Function View(IFunction function)47 public FunctionTreeView(IFunctionTree functionTree) 47 48 : this() { 48 this.function = function;49 this.functionTree = functionTree; 49 50 Refresh(); 50 51 } … … 52 53 protected override void UpdateControls() { 53 54 functionTreeView.Nodes.Clear(); 54 function .Accept(functionNameVisitor);55 functionNameVisitor.Visit(functionTree); 55 56 TreeNode rootNode = new TreeNode(); 56 rootNode.Name = function .Name;57 rootNode.Name = functionTree.Function.Name; 57 58 rootNode.Text = functionNameVisitor.Name; 58 rootNode.Tag = function ;59 rootNode.Tag = functionTree; 59 60 rootNode.ContextMenuStrip = treeNodeContextMenu; 60 61 functionTreeView.Nodes.Add(rootNode); 61 62 62 foreach(IFunction subFunction in function.SubFunctions) {63 CreateTree(rootNode, sub Function);63 foreach(IFunctionTree subTree in functionTree.SubTrees) { 64 CreateTree(rootNode, subTree); 64 65 } 65 66 functionTreeView.ExpandAll(); 66 67 } 67 68 68 private void CreateTree(TreeNode rootNode, IFunction function) {69 private void CreateTree(TreeNode rootNode, IFunctionTree functionTree) { 69 70 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; 73 73 node.Text = functionNameVisitor.Name; 74 node.Tag = functionTree; 74 75 node.ContextMenuStrip = treeNodeContextMenu; 75 76 rootNode.Nodes.Add(node); 76 foreach(IFunction subFunction in function.SubFunctions) {77 CreateTree(node, sub Function);77 foreach(IFunctionTree subTree in functionTree.SubTrees) { 78 CreateTree(node, subTree); 78 79 } 79 80 } … … 85 86 editButton.Enabled = false; 86 87 if(functionTreeView.SelectedNode != null && functionTreeView.SelectedNode.Tag != null) { 87 IFunction selectedFunction = (IFunction)functionTreeView.SelectedNode.Tag;88 UpdateVariablesList(selected Function);89 templateTextBox.Text = selected Function.MetaObject.Name;90 this.selected Function = selectedFunction;88 IFunctionTree selectedBranch = (IFunctionTree)functionTreeView.SelectedNode.Tag; 89 UpdateVariablesList(selectedBranch); 90 templateTextBox.Text = selectedBranch.Function.Name; 91 this.selectedBranch = selectedBranch; 91 92 editButton.Enabled = true; 92 93 } 93 94 } 94 95 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) { 97 98 variablesListBox.Items.Add(variable.Name); 98 99 } … … 106 107 if(variablesListBox.SelectedItem != null) { 107 108 string selectedVariableName = (string)variablesListBox.SelectedItem; 108 selectedVariable = selected Function.GetVariable(selectedVariableName);109 selectedVariable = selectedBranch.GetLocalVariable(selectedVariableName); 109 110 variablesSplitContainer.Panel2.Controls.Clear(); 110 111 Control editor = (Control)selectedVariable.CreateView(); … … 121 122 if(functionTreeView.SelectedNode != null && functionTreeView.SelectedNode.Tag != null) { 122 123 TreeNode node = functionTreeView.SelectedNode; 123 selectedFunction.Accept(functionNameVisitor);124 functionNameVisitor.Visit(selectedBranch); 124 125 node.Text = functionNameVisitor.Name; 125 126 } 126 127 } 127 128 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()); 131 131 } 132 132 … … 136 136 137 137 ModelAnalyzerExportVisitor visitor = new ModelAnalyzerExportVisitor(); 138 ((IFunction)node.Tag).Accept(visitor);138 visitor.Visit((IFunctionTree)node.Tag); 139 139 Clipboard.SetText(visitor.ModelAnalyzerPrefix); 140 140 } … … 142 142 private class FunctionNameVisitor : IFunctionVisitor { 143 143 string name; 144 IFunctionTree currentBranch; 144 145 145 146 public string Name { … … 147 148 } 148 149 150 public void Visit(IFunctionTree tree) { 151 currentBranch = tree; 152 tree.Function.Accept(this); 153 } 154 149 155 #region IFunctionVisitor Members 150 151 156 public void Visit(IFunction function) { 152 157 name = function.Name; … … 158 163 159 164 public void Visit(Constant constant) { 160 name = constant.Value+ "";165 name = ((ConstrainedDoubleData)(currentBranch.GetLocalVariable(HeuristicLab.Functions.Constant.VALUE).Value)).Data + ""; 161 166 } 162 167 … … 207 212 public void Visit(Variable variable) { 208 213 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 + ")"; 213 221 } else { 214 222 timeOffset = ""; 215 223 } 216 name = "Var" + variable .VariableIndex + timeOffset + " * " + variable.Weight;224 name = "Var" + variableIndex + timeOffset + " * " + weight; 217 225 } 218 226 … … 255 263 private string prefix; 256 264 private string currentIndend = ""; 265 private IFunctionTree currentBranch; 257 266 public string ModelAnalyzerPrefix { 258 267 get { return prefix; } … … 263 272 264 273 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); 266 380 currentIndend += " "; 267 foreach(IFunction subFunction in f.SubFunctions) {268 subFunction.Accept(this);381 foreach(IFunctionTree subTree in functionTree.SubTrees) { 382 Visit(subTree); 269 383 prefix += ";\n"; 270 384 } 271 prefix = prefix.TrimEnd(';', '\n');385 prefix = prefix.TrimEnd(';', '\n'); 272 386 prefix += ")"; 273 387 currentIndend = currentIndend.Remove(0, 2); 274 388 } 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 } 373 390 } 374 391 } -
trunk/sources/HeuristicLab.Functions/HeuristicLab.Functions.csproj
r30 r155 52 52 <Compile Include="Average.cs" /> 53 53 <Compile Include="Constant.cs" /> 54 <Compile Include="FunctionTree.cs" /> 55 <Compile Include="IFunctionTree.cs" /> 56 <Compile Include="ProgrammableFunction.cs" /> 54 57 <Compile Include="Equal.cs" /> 55 58 <Compile Include="FunctionView.cs"> … … 99 102 <Name>HeuristicLab.Data</Name> 100 103 </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> 101 108 <ProjectReference Include="..\HeuristicLab.PluginInfrastructure\HeuristicLab.PluginInfrastructure.csproj"> 102 109 <Project>{94186A6A-5176-4402-AE83-886557B53CCA}</Project> -
trunk/sources/HeuristicLab.Functions/IFunction.cs
r2 r155 28 28 namespace HeuristicLab.Functions { 29 29 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); 34 32 void Accept(IFunctionVisitor visitor); 35 33 } -
trunk/sources/HeuristicLab.Functions/IfThenElse.cs
r2 r155 31 31 public override string Description { 32 32 get { 33 return @"Returns the result of the second branch if the first branch evaluates to a value >=0.5 and the result34 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 34 of the third sub-tree if the first sub-tree evaluates to >= 0.5."; 35 35 } 36 36 } … … 41 41 } 42 42 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); 52 48 else return double.NaN; 53 49 } 54 50 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(); 59 53 } 60 54 -
trunk/sources/HeuristicLab.Functions/LessThan.cs
r2 r155 31 31 public override string Description { 32 32 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-functionand 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."; 34 34 } 35 35 } … … 40 40 } 41 41 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; 49 44 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;56 45 } 57 46 -
trunk/sources/HeuristicLab.Functions/Logarithm.cs
r2 r155 31 31 public class Logarithm : FunctionBase { 32 32 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."; } 34 34 } 35 35 … … 40 40 } 41 41 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]); 54 44 } 55 45 -
trunk/sources/HeuristicLab.Functions/Multiplication.cs
r2 r155 33 33 public override string Description { 34 34 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. 36 36 (* 3) => 3 37 37 (* 2 3) => 6 … … 46 46 } 47 47 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) { 54 49 // (* 3) => 3 55 50 // (* 2 3) => 6 56 51 // (* 3 4 5) => 60 57 52 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]; 60 55 } 61 56 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;68 57 } 69 58 -
trunk/sources/HeuristicLab.Functions/Not.cs
r2 r155 31 31 public override string Description { 32 32 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."; 34 34 } 35 35 } … … 40 40 } 41 41 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]); 49 44 if(result == 0.0) return 1.0; 50 45 else if(result == 1.0) return 0.0; 51 46 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;58 47 } 59 48 -
trunk/sources/HeuristicLab.Functions/Or.cs
r2 r155 31 31 public override string Description { 32 32 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. 34 Special form, evaluation stops at first sub-tree that evaluates to 1.0 (true)."; 34 35 } 35 36 } … … 40 41 } 41 42 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 51 47 else if(result != 0.0) return double.NaN; 52 48 } 49 // all sub-trees evaluated to 0.0 (false) return false 53 50 return 0.0; 54 51 } 55 52 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(); 60 55 } 61 62 56 public override void Accept(IFunctionVisitor visitor) { 63 57 visitor.Visit(this); -
trunk/sources/HeuristicLab.Functions/Power.cs
r2 r155 31 31 public class Power : FunctionBase { 32 32 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))."; } 34 34 } 35 35 … … 40 40 } 41 41 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]); 44 44 } 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 57 45 58 46 public override void Accept(IFunctionVisitor visitor) { -
trunk/sources/HeuristicLab.Functions/Signum.cs
r2 r155 31 31 public class Signum : FunctionBase { 32 32 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."; } 34 34 } 35 35 … … 40 40 } 41 41 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]; 49 44 if(value < 0) return -1; 50 45 if(value > 0) return 1; 51 46 return 0; 52 47 } 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 60 48 61 49 public override void Accept(IFunctionVisitor visitor) { -
trunk/sources/HeuristicLab.Functions/Sinus.cs
r2 r155 31 31 public class Sinus : FunctionBase { 32 32 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."; } 34 34 } 35 35 … … 40 40 } 41 41 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]); 44 44 } 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 57 45 58 46 public override void Accept(IFunctionVisitor visitor) { -
trunk/sources/HeuristicLab.Functions/Sqrt.cs
r2 r155 31 31 public class Sqrt : FunctionBase { 32 32 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."; } 34 34 } 35 35 … … 40 40 } 41 41 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]); 44 45 } 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 57 46 58 47 public override void Accept(IFunctionVisitor visitor) { -
trunk/sources/HeuristicLab.Functions/Substraction.cs
r2 r155 33 33 public override string Description { 34 34 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. 36 36 (- 3) => -3 37 37 (- 2 3) => -1 … … 46 46 } 47 47 48 public Substraction(Substraction source, IDictionary<Guid, object> clonedObjects)49 : base(source, clonedObjects) {50 }51 48 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]; 57 52 } 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]; 61 56 } 62 57 return result; 63 58 } 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;70 59 } 71 60 -
trunk/sources/HeuristicLab.Functions/Tangens.cs
r2 r155 31 31 public class Tangens : FunctionBase { 32 32 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."; } 34 34 } 35 35 … … 40 40 } 41 41 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]); 44 44 } 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 56 45 57 46 public override void Accept(IFunctionVisitor visitor) { -
trunk/sources/HeuristicLab.Functions/Variable.cs
r133 r155 32 32 public class Variable : FunctionBase { 33 33 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"; 49 37 50 38 public override string Description { … … 56 44 public Variable() 57 45 : 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; 64 52 65 variable = new ConstrainedIntData(); 66 AddLocalVariable(new HeuristicLab.Core.Variable("Variable", variable)); 67 68 weight = new ConstrainedDoubleData(); 53 ConstrainedDoubleData weight = new ConstrainedDoubleData(); 69 54 // initialize a totally arbitrary range for the weight = [-20.0, 20.0] 70 55 weight.AddConstraint(new DoubleBoundedConstraint(-20.0, 20.0)); 71 Add LocalVariable(new HeuristicLab.Core.Variable("Weight", weight));56 AddVariable(new HeuristicLab.Core.Variable(WEIGHT, weight)); 72 57 73 sampleOffset = new ConstrainedIntData(); 58 ConstrainedIntData variable = new ConstrainedIntData(); 59 AddVariable(new HeuristicLab.Core.Variable(INDEX, variable)); 60 61 ConstrainedIntData sampleOffset = new ConstrainedIntData(); 74 62 // initialize a totally arbitrary default range for sampleoffset = [-10, 10] 75 63 sampleOffset.AddConstraint(new IntBoundedConstraint(0, 0)); 76 Add LocalVariable(new HeuristicLab.Core.Variable("SampleOffset", sampleOffset));64 AddVariable(new HeuristicLab.Core.Variable(OFFSET, sampleOffset)); 77 65 78 // samplefeature can't have suboperators66 // variable can't have suboperators 79 67 AddConstraint(new NumberOfSubOperatorsConstraint(0, 0)); 80 68 } 81 69 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; 84 76 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); 88 79 } 89 80 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(); 113 84 } 114 85 -
trunk/sources/HeuristicLab.Functions/Xor.cs
r2 r155 31 31 public override string Description { 32 32 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."; 34 34 } 35 35 } … … 40 40 } 41 41 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; 61 46 } 62 47 -
trunk/sources/HeuristicLab.StructureIdentification/Evaluation/CoefficientOfDeterminationEvaluator.cs
r128 r155 34 34 public override string Description { 35 35 get { 36 return @" Applies 'OperatorTree' toall samples of 'Dataset' and calculates36 return @"Evaluates 'FunctionTree' for all samples of 'Dataset' and calculates 37 37 the 'coefficient of determination' of estimated values vs. real values of 'TargetVariable'."; 38 38 } … … 43 43 } 44 44 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) { 46 46 double errorsSquaredSum = 0.0; 47 47 double originalDeviationTotalSumOfSquares = 0.0; 48 48 double targetMean = dataset.GetMean(targetVariable); 49 49 for(int sample = 0; sample < dataset.Rows; sample++) { 50 double estimated = function .Evaluate(dataset, sample);50 double estimated = functionTree.Evaluate(dataset, sample); 51 51 double original = dataset.GetValue(sample, targetVariable); 52 52 if(!double.IsNaN(original) && !double.IsInfinity(original)) { -
trunk/sources/HeuristicLab.StructureIdentification/Evaluation/EarlyStoppingMeanSquaredErrorEvaluator.cs
r136 r155 34 34 public override string Description { 35 35 get { 36 return @"Evaluates ' OperatorTree' for all samples of the dataset and calculates the mean-squared-error36 return @"Evaluates 'FunctionTree' for all samples of the dataset and calculates the mean-squared-error 37 37 for the estimated values vs. the real values of 'TargetVariable'. 38 38 This operator stops the computation as soon as an upper limit for the mean-squared-error is reached."; … … 45 45 } 46 46 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) { 48 48 double qualityLimit = GetVariableValue<DoubleData>("QualityLimit", scope, false).Data; 49 49 double errorsSquaredSum = 0; 50 50 double targetMean = dataset.GetMean(targetVariable); 51 51 for(int sample = 0; sample < dataset.Rows; sample++) { 52 double estimated = function .Evaluate(dataset, sample);52 double estimated = functionTree.Evaluate(dataset, sample); 53 53 double original = dataset.GetValue(sample, targetVariable); 54 54 if(double.IsNaN(estimated) || double.IsInfinity(estimated)) { -
trunk/sources/HeuristicLab.StructureIdentification/Evaluation/GPEvaluatorBase.cs
r135 r155 36 36 public GPEvaluatorBase() 37 37 : 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)); 39 39 AddVariableInfo(new VariableInfo("Dataset", "Dataset with all samples on which to apply the function", typeof(Dataset), VariableKind.In)); 40 40 AddVariableInfo(new VariableInfo("TargetVariable", "Index of the column of the dataset that holds the target variable", typeof(IntData), VariableKind.In)); … … 46 46 int targetVariable = GetVariableValue<IntData>("TargetVariable", scope, true).Data; 47 47 Dataset dataset = GetVariableValue<Dataset>("Dataset", scope, true); 48 IFunction function = GetVariableValue<IFunction>("OperatorTree", scope, true);48 IFunctionTree functionTree = GetVariableValue<IFunctionTree>("FunctionTree", scope, true); 49 49 this.maximumPunishment = GetVariableValue<DoubleData>("PunishmentFactor", scope, true).Data * dataset.GetRange(targetVariable); 50 50 51 double result = Evaluate(scope, function , targetVariable, dataset);51 double result = Evaluate(scope, functionTree, targetVariable, dataset); 52 52 scope.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("Quality"), new DoubleData(result))); 53 53 return null; 54 54 } 55 55 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); 57 57 } 58 58 } -
trunk/sources/HeuristicLab.StructureIdentification/Evaluation/MeanSquaredErrorEvaluator.cs
r128 r155 34 34 public override string Description { 35 35 get { 36 return @"Evaluates ' OperatorTree' for all samples of 'DataSet' and calculates the mean-squared-error36 return @"Evaluates 'FunctionTree' for all samples of 'DataSet' and calculates the mean-squared-error 37 37 for the estimated values vs. the real values of 'TargetVariable'."; 38 38 } … … 43 43 } 44 44 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) { 46 46 double errorsSquaredSum = 0; 47 47 double targetMean = dataset.GetMean(targetVariable); 48 48 for(int sample = 0; sample < dataset.Rows; sample++) { 49 double estimated = function.Evaluate(dataset, sample); 49 50 double estimated = functionTree.Evaluate(dataset, sample); 50 51 double original = dataset.GetValue(sample, targetVariable); 51 52 if(double.IsNaN(estimated) || double.IsInfinity(estimated)) { -
trunk/sources/HeuristicLab.StructureIdentification/Evaluation/VarianceAccountedForEvaluator.cs
r128 r155 34 34 public override string Description { 35 35 get { 36 return @"Evaluates ' OperatorTree' for all samples of 'DataSet' and calculates36 return @"Evaluates 'FunctionTree' for all samples of 'DataSet' and calculates 37 37 the variance-accounted-for quality measure for the estimated values vs. the real values of 'TargetVariable'. 38 38 … … 53 53 54 54 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) { 56 56 double[] errors = new double[dataset.Rows]; 57 57 double[] originalTargetVariableValues = new double[dataset.Rows]; 58 58 double targetMean = dataset.GetMean(targetVariable); 59 59 for(int sample = 0; sample < dataset.Rows; sample++) { 60 double estimated = function .Evaluate(dataset, sample);60 double estimated = functionTree.Evaluate(dataset, sample); 61 61 double original = dataset.GetValue(sample, targetVariable); 62 62 if(!double.IsNaN(original) && !double.IsInfinity(original)) { -
trunk/sources/HeuristicLab.StructureIdentification/GPOperatorGroup.cs
r2 r155 32 32 namespace HeuristicLab.StructureIdentification { 33 33 public class GPOperatorGroup : OperatorGroup { 34 35 34 public GPOperatorGroup() 36 35 : base() { … … 118 117 int maxArity; 119 118 GetMinMaxArity(op, out minArity, out maxArity); 120 ItemListslotsList = (ItemList)op.GetVariable(GPOperatorLibrary.ALLOWED_SUBOPERATORS).Value;119 var slotsList = (ItemList)op.GetVariable(GPOperatorLibrary.ALLOWED_SUBOPERATORS).Value; 121 120 slotsList.Clear(); 122 121 for(int i = 0; i < maxArity; i++) { … … 276 275 } 277 276 278 279 277 public override void AddSubGroup(IOperatorGroup group) { 280 278 throw new NotSupportedException(); -
trunk/sources/HeuristicLab.StructureIdentification/HeuristicLab.StructureIdentification.csproj
r128 r155 67 67 <Compile Include="Manipulation\OnePointShaker.cs" /> 68 68 <Compile Include="Manipulation\SubstituteSubTreeManipulation.cs" /> 69 <Compile Include="PopulationAnalyser.cs" />70 69 <Compile Include="HeuristicLabStructureIdentificationPlugin.cs" /> 71 70 <Compile Include="Properties\AssemblyInfo.cs" /> -
trunk/sources/HeuristicLab.StructureIdentification/Manipulation/ChangeNodeTypeManipulation.cs
r23 r155 29 29 using HeuristicLab.Data; 30 30 using HeuristicLab.Constraints; 31 using HeuristicLab.Functions; 31 32 32 33 namespace HeuristicLab.StructureIdentification { … … 39 40 AddVariableInfo(new VariableInfo("MaxTreeSize", "The maximal allowed size (number of nodes) of the tree", typeof(IntData), VariableKind.In)); 40 41 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)); 44 45 } 45 46 46 47 47 48 public override IOperation Apply(IScope scope) { 48 I Operator rootOperator = GetVariableValue<IOperator>("OperatorTree", scope, false);49 IFunctionTree root = GetVariableValue<IFunctionTree>("FunctionTree", scope, false); 49 50 MersenneTwister random = GetVariableValue<MersenneTwister>("Random", scope, true); 50 51 GPOperatorLibrary library = GetVariableValue<GPOperatorLibrary>("OperatorLibrary", scope, true); … … 56 57 57 58 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; 62 62 int selectedChildIndex; 63 63 if (parent == null) { 64 64 selectedChildIndex = 0; 65 selectedChild = root Operator;65 selectedChild = root; 66 66 } else { 67 selectedChildIndex = random.Next(parent.Sub Operators.Count);68 selectedChild = parent.Sub Operators[selectedChildIndex];69 } 70 71 if (selectedChild.Sub Operators.Count == 0) {72 I OperatornewTerminal = 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); 73 73 74 74 if (parent == null) { 75 75 // no parent means the new child is the initial operator 76 76 // and we have to update the value in the variable 77 scope.GetVariable( "OperatorTree").Value = newTerminal;77 scope.GetVariable(scope.TranslateName("FunctionTree")).Value = newTerminal; 78 78 } else { 79 parent.RemoveSub Operator(selectedChildIndex);80 parent. AddSubOperator(newTerminal, selectedChildIndex);79 parent.RemoveSubTree(selectedChildIndex); 80 parent.InsertSubTree(selectedChildIndex, newTerminal); 81 81 // updating the variable is not necessary because it stays the same 82 82 } 83 if(!gardener.IsValidTree(root)) throw new InvalidProgramException(); 83 84 84 85 // size and height stays the same when changing a terminal so no need to update the variables 85 86 // schedule an operation to initialize the new terminal 86 return gardener.CreateInitializationOperation(gardener.GetAll Operators(newTerminal), scope);87 return gardener.CreateInitializationOperation(gardener.GetAllSubTrees(newTerminal), scope); 87 88 } else { 88 List<I Operator> uninitializedOperators;89 I Operator 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); 90 91 91 92 if (parent == null) { 92 93 // no parent means the new function is the initial operator 93 94 // and we have to update the value in the variable 94 scope.GetVariable( "OperatorTree").Value = newFunction;95 root Operator= newFunction;95 scope.GetVariable(scope.TranslateName("FunctionTree")).Value = newFunction; 96 root = newFunction; 96 97 } else { 97 98 // remove the old child 98 parent.RemoveSub Operator(selectedChildIndex);99 parent.RemoveSubTree(selectedChildIndex); 99 100 // add the new child as sub-tree of parent 100 parent. AddSubOperator(newFunction, selectedChildIndex);101 parent.InsertSubTree(selectedChildIndex, newFunction); 101 102 } 102 103 103 104 // 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 107 109 // 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 || 109 112 treeSize.Data > maxTreeSize) { 110 113 throw new InvalidProgramException(); 111 114 } 112 115 113 // check if whole tree is ok114 if (!gardener.IsValidTree(rootOperator)) {115 throw new InvalidProgramException();116 }117 118 116 // 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; 127 123 if (parent == null) { 128 124 allowedChildren = gardener.Terminals; 129 125 } 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 } 133 131 } 134 132 135 133 // selecting from the terminals should always work since the current child was also a terminal 136 134 // 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); 155 146 156 147 // try to make a tree with the same arity as the old child. 157 int actualArity = child.Sub Operators.Count;148 int actualArity = child.SubTrees.Count; 158 149 // arity of the selected operator 159 150 int minArity; 160 151 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 => { 163 156 gardener.GetMinMaxArity(f, out minArity, out maxArity); 164 157 return minArity <= actualArity; 165 158 }).ToList(); 166 159 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 171 165 if (actualArity > maxArity) 172 166 actualArity = maxArity; … … 175 169 // use the size of the smallest subtree as the maximal allowed size for new subtrees to 176 170 // prevent that we ever create trees over the MaxTreeSize limit 177 int maxSubTreeSize = child.Sub Operators.Select(subOp => gardener.GetTreeSize(subOp)).Min();171 int maxSubTreeSize = child.SubTrees.Select(subTree => gardener.GetTreeSize(subTree)).Min(); 178 172 int maxSubTreeHeight = gardener.GetTreeHeight(child) - 1; 179 173 180 174 // create a list that holds old sub-trees that we can reuse in the new tree 181 List<I Operator> availableSubOperators = new List<IOperator>(child.SubOperators);182 List<I Operator> freshSubTrees = new List<IOperator>() { newOperator};183 184 // randomly select the sub operators that we keep175 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 185 179 for (int i = 0; i < actualArity; i++) { 186 // fill all sub- operator slots of the new operator187 // if for a given slot i there are existing sub-operators that can be used in that slot188 // then use a random existing sub- operator. When there are no existing sub-operators180 // 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 189 183 // that fit in the given slot then create a new random tree and use it for the slot 190 I List<IOperator> allowedOperators = analyser.GetAllowedOperators(newOperator, i);191 var matching Operators = availableSubOperators.Where(subOp => allowedOperators.Contains(subOp, new TreeGardener.OperatorEqualityComparer()));192 193 if (matching Operators.Count() > 0) {194 I Operator selectedSubOperator = matchingOperators.ElementAt(random.Next(matchingOperators.Count()));195 // we can just add it as sub operator196 new Operator.AddSubOperator(selectedSubOperator, i);197 availableSub Operators.Remove(selectedSubOperator); // the operatorshouldn't be available for the following slots184 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 198 192 } else { 199 IOperator freshOperatorTree; 193 // no existing matching tree found => create a new one 194 IFunctionTree freshTree; 200 195 if(random.NextDouble() <= balancedTreesRate) { 201 fresh OperatorTree = gardener.CreateRandomTree(allowedOperators, maxSubTreeSize, maxSubTreeHeight, true);196 freshTree = gardener.CreateRandomTree(allowedSubFunctions, maxSubTreeSize, maxSubTreeHeight, true); 202 197 } else { 203 fresh OperatorTree = gardener.CreateRandomTree(allowedOperators, maxSubTreeSize, maxSubTreeHeight, false);198 freshTree = gardener.CreateRandomTree(allowedSubFunctions, maxSubTreeSize, maxSubTreeHeight, false); 204 199 } 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; 213 207 } 214 208 } -
trunk/sources/HeuristicLab.StructureIdentification/Manipulation/CutOutNodeManipulation.cs
r23 r155 27 27 using HeuristicLab.Random; 28 28 using System; 29 using HeuristicLab.Functions; 29 30 30 31 namespace HeuristicLab.StructureIdentification { … … 32 33 public override string Description { 33 34 get { 34 return @"Takes a tree, selects a random node of the tree and then tries to replace a random child35 return @"Takes a tree, selects a random node of the tree and then tries to replace a random sub-tree 35 36 of that node with one of the childs of the selected child. 36 37 … … 53 54 AddVariableInfo(new VariableInfo("MaxTreeSize", "The maximal allowed size (number of nodes) of the tree", typeof(IntData), VariableKind.In)); 54 55 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)); 58 59 } 59 60 60 61 61 62 public override IOperation Apply(IScope scope) { 62 I Operator rootOperator = GetVariableValue<IOperator>("OperatorTree", scope, true);63 IFunctionTree root = GetVariableValue<IFunctionTree>("FunctionTree", scope, true); 63 64 MersenneTwister random = GetVariableValue<MersenneTwister>("Random", scope, true); 64 65 GPOperatorLibrary library = GetVariableValue<GPOperatorLibrary>("OperatorLibrary", scope, true); … … 68 69 69 70 TreeGardener gardener = new TreeGardener(random, library); 70 I Operator parent = gardener.GetRandomParentNode(rootOperator);71 IFunctionTree parent = gardener.GetRandomParentNode(root); 71 72 // parent == null means we should cut out the root node 72 // => return a random sub operatorof the root73 // => return a random sub-tree of the root 73 74 if (parent == null) { 74 // when there are sub operators then replace the old operator with a random suboperator75 if (root Operator.SubOperators.Count > 0) {76 root Operator = 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)]; 77 78 78 GetVariableValue<IntData>("TreeSize", scope, true).Data = gardener.GetTreeSize(root Operator);79 GetVariableValue<IntData>("TreeHeight", scope, true).Data = gardener.GetTreeHeight(root Operator);79 GetVariableValue<IntData>("TreeSize", scope, true).Data = gardener.GetTreeSize(root); 80 GetVariableValue<IntData>("TreeHeight", scope, true).Data = gardener.GetTreeHeight(root); 80 81 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)) { 83 85 throw new InvalidProgramException(); 84 86 } 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); 86 95 // 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)) { 89 98 throw new InvalidProgramException(); 90 99 } 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); 120 102 } 121 103 } 122 104 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]; 125 108 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(); 131 112 132 113 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); 138 118 139 if (!gardener.IsValidTree(root Operator)) {119 if (!gardener.IsValidTree(root)) { 140 120 throw new InvalidProgramException(); 141 121 } 142 122 143 123 // update the size and height of our tree 144 GetVariableValue<IntData>("TreeSize", scope, true).Data = gardener.GetTreeSize(root Operator);145 GetVariableValue<IntData>("TreeHeight", scope, true).Data = gardener.GetTreeHeight(root Operator);124 GetVariableValue<IntData>("TreeSize", scope, true).Data = gardener.GetTreeSize(root); 125 GetVariableValue<IntData>("TreeHeight", scope, true).Data = gardener.GetTreeHeight(root); 146 126 // don't need to schedule initialization operations 147 127 return null; 148 128 } else { 129 // can't reuse an existing branch => create a new tree 149 130 // determine the level of the parent 150 int parentLevel = gardener.Get NodeLevel(rootOperator, parent);131 int parentLevel = gardener.GetBranchLevel(root, parent); 151 132 152 133 // first remove the old child (first step essential!) 153 parent.RemoveSub Operator(childIndex);134 parent.RemoveSubTree(childIndex); 154 135 // then determine the number of nodes left over after the child has been removed! 155 int remainingNodes = gardener.GetTreeSize(root Operator);136 int remainingNodes = gardener.GetTreeSize(root); 156 137 157 IList<IOperator> allowedOperators = gardener.GetAllowedSubOperators(parent, childIndex);158 I Operator 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); 159 140 160 parent. AddSubOperator(newOperatorTree, childIndex);141 parent.InsertSubTree(childIndex, newFunctionTree); 161 142 162 GetVariableValue<IntData>("TreeSize", scope, true).Data = gardener.GetTreeSize(root Operator);163 GetVariableValue<IntData>("TreeHeight", scope, true).Data = gardener.GetTreeHeight(root Operator);143 GetVariableValue<IntData>("TreeSize", scope, true).Data = gardener.GetTreeSize(root); 144 GetVariableValue<IntData>("TreeHeight", scope, true).Data = gardener.GetTreeHeight(root); 164 145 165 if (!gardener.IsValidTree(root Operator)) {146 if (!gardener.IsValidTree(root)) { 166 147 throw new InvalidProgramException(); 167 148 } 168 149 169 // schedule an initialization operation for the new operator170 return gardener.CreateInitializationOperation(gardener.GetAll Operators(newOperatorTree), scope);150 // schedule an initialization operation for the new function-tree 151 return gardener.CreateInitializationOperation(gardener.GetAllSubTrees(newFunctionTree), scope); 171 152 } 172 153 } -
trunk/sources/HeuristicLab.StructureIdentification/Manipulation/DeleteSubTreeManipulation.cs
r23 r155 26 26 using HeuristicLab.Operators; 27 27 using HeuristicLab.Random; 28 using HeuristicLab.Functions; 28 29 29 30 namespace HeuristicLab.StructureIdentification { … … 42 43 AddVariableInfo(new VariableInfo("MaxTreeHeight", "The maximal allowed height of the tree", typeof(IntData), VariableKind.In)); 43 44 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)); 45 46 AddVariableInfo(new VariableInfo("TreeSize", "The size (number of nodes) of the tree", typeof(IntData), VariableKind.In | VariableKind.Out)); 46 47 AddVariableInfo(new VariableInfo("TreeHeight", "The height of the tree", typeof(IntData), VariableKind.In | VariableKind.Out)); … … 49 50 50 51 public override IOperation Apply(IScope scope) { 51 I Operator rootOperator = GetVariableValue<IOperator>("OperatorTree", scope, true);52 IFunctionTree root = GetVariableValue<IFunctionTree>("FunctionTree", scope, true); 52 53 MersenneTwister random = GetVariableValue<MersenneTwister>("Random", scope, true); 53 54 GPOperatorLibrary library = GetVariableValue<GPOperatorLibrary>("OperatorLibrary", scope, true); 54 55 55 TreeGardener gardener = new TreeGardener(random, library); 56 57 IOperator parent = gardener.GetRandomParentNode(rootOperator); 56 IFunctionTree parent = gardener.GetRandomParentNode(root); 58 57 59 58 // parent==null means the whole tree should be deleted. 60 59 // => return a new minimal random tree 61 60 if(parent == null) { 62 I Operator newTree = gardener.CreateRandomTree(1, 1, true);61 IFunctionTree newTree = gardener.CreateRandomTree(1, 1, false); 63 62 64 63 // check if the tree is ok … … 70 69 GetVariableValue<IntData>("TreeSize", scope, true).Data = gardener.GetTreeSize(newTree); 71 70 GetVariableValue<IntData>("TreeHeight", scope, true).Data = gardener.GetTreeHeight(newTree); 72 scope.GetVariable( "OperatorTree").Value = newTree;71 scope.GetVariable(scope.TranslateName("FunctionTree")).Value = newTree; 73 72 74 73 // schedule an operation to initialize the newly created operator 75 return gardener.CreateInitializationOperation(gardener.GetAll Operators(newTree), scope);74 return gardener.CreateInitializationOperation(gardener.GetAllSubTrees(newTree), scope); 76 75 } 77 76 78 int childIndex = random.Next(parent.SubOperators.Count);79 77 // select a branch to prune 78 int childIndex = random.Next(parent.SubTrees.Count); 80 79 int min; 81 80 int max; 82 gardener.GetMinMaxArity(parent , out min, out max);83 if(parent.Sub Operators.Count > min) {84 parent.RemoveSub Operator(childIndex);85 // actually since the next sub operators are shifted in the place of the removed operator86 // it might be possible that these sub operators are not allowed in the place of the old operator81 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 87 86 // 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 shifted87 // when this starts to become a problem a possible solution is to go through the shifted branches from the place of the shifted 89 88 // 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) 90 89 91 if(!gardener.IsValidTree(root Operator)) {90 if(!gardener.IsValidTree(root)) { 92 91 throw new InvalidOperationException(); 93 92 } 94 93 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 99 97 return null; 100 98 } else { 101 99 // replace with a minimal random seedling 102 parent.RemoveSub Operator(childIndex);100 parent.RemoveSubTree(childIndex); 103 101 104 I List<IOperator> allowedOperators = gardener.GetAllowedSubOperators(parent, childIndex);105 I Operator 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); 106 104 107 parent. AddSubOperator(newOperatorTree, childIndex);105 parent.InsertSubTree(childIndex, newFunctionTree); 108 106 109 if(!gardener.IsValidTree(root Operator)) {107 if(!gardener.IsValidTree(root)) { 110 108 throw new InvalidProgramException(); 111 109 } 112 110 113 GetVariableValue<IntData>("TreeSize", scope, true).Data = gardener.GetTreeSize(root Operator);114 GetVariableValue<IntData>("TreeHeight", scope, true).Data = gardener.GetTreeHeight(root Operator);115 // again the root hasn't changed so we don't need to update the ' OperatorTree' variable116 117 return gardener.CreateInitializationOperation(gardener.GetAll Operators(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); 118 116 } 119 117 } -
trunk/sources/HeuristicLab.StructureIdentification/Manipulation/FullTreeShaker.cs
r88 r155 29 29 using HeuristicLab.Data; 30 30 using HeuristicLab.Selection; 31 using HeuristicLab.Functions; 31 32 32 33 namespace HeuristicLab.StructureIdentification { … … 38 39 public FullTreeShaker() 39 40 : base() { 41 AddVariableInfo(new VariableInfo("Random", "A random generator (uniform)", typeof(MersenneTwister), VariableKind.In)); 40 42 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)); 44 45 } 45 46 46 47 public override IOperation Apply(IScope scope) { 47 48 GPOperatorLibrary library = GetVariableValue<GPOperatorLibrary>("OperatorLibrary", scope, true); 48 I Operator op = GetVariableValue<IOperator>("OperatorTree", scope, false);49 IFunctionTree tree = GetVariableValue<IFunctionTree>("FunctionTree", scope, false); 49 50 MersenneTwister mt = GetVariableValue<MersenneTwister>("Random", scope, true); 50 51 … … 56 57 57 58 TreeGardener gardener = new TreeGardener(mt, library); 58 var parametric Nodes = gardener.GetAllOperators(op).Where(o => o.GetVariable(GPOperatorLibrary.MANIPULATION) != null);59 foreach(I Operator subOperator in parametricNodes) {60 IOperator mutation =(IOperator)sub Operator.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; 61 62 62 63 // store all local variables into a temporary scope 63 64 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); 68 67 } 69 68 -
trunk/sources/HeuristicLab.StructureIdentification/Manipulation/OnePointShaker.cs
r88 r155 29 29 using HeuristicLab.Data; 30 30 using HeuristicLab.Selection; 31 using HeuristicLab.Functions; 31 32 32 33 namespace HeuristicLab.StructureIdentification { … … 39 40 : base() { 40 41 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));42 42 AddVariableInfo(new VariableInfo("Random", "A random generator (uniform)", typeof(MersenneTwister), VariableKind.In)); 43 43 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)); 44 45 } 45 46 46 47 public override IOperation Apply(IScope scope) { 47 48 GPOperatorLibrary library = GetVariableValue<GPOperatorLibrary>("OperatorLibrary", scope, true); 48 I Operator op = GetVariableValue<IOperator>("OperatorTree", scope, false);49 IFunctionTree tree = GetVariableValue<IFunctionTree>("FunctionTree", scope, false); 49 50 MersenneTwister mt = GetVariableValue<MersenneTwister>("Random", scope, true); 50 51 TreeGardener gardener = new TreeGardener(mt, library); 51 52 52 53 // 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; 58 57 CompositeOperation next = new CompositeOperation(); 59 58 60 59 // store all local variables into a temporary scope 61 60 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); 70 63 } 71 64 -
trunk/sources/HeuristicLab.StructureIdentification/Manipulation/SubstituteSubTreeManipulation.cs
r23 r155 27 27 using HeuristicLab.Operators; 28 28 using HeuristicLab.Random; 29 using HeuristicLab.Functions; 29 30 30 31 namespace HeuristicLab.StructureIdentification { … … 42 43 AddVariableInfo(new VariableInfo("MaxTreeSize", "The maximal allowed size (number of nodes) of the tree", typeof(IntData), VariableKind.In)); 43 44 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)); 47 48 } 48 49 49 50 public override IOperation Apply(IScope scope) { 50 IOperator rootOperator = GetVariableValue<IOperator>("OperatorTree", scope, true); 51 51 IFunctionTree root = GetVariableValue<IFunctionTree>("FunctionTree", scope, true); 52 52 MersenneTwister random = GetVariableValue<MersenneTwister>("Random", scope, true); 53 53 GPOperatorLibrary library = GetVariableValue<GPOperatorLibrary>("OperatorLibrary", scope, true); … … 60 60 TreeGardener gardener = new TreeGardener(random, library); 61 61 62 I Operator parent = gardener.GetRandomParentNode(rootOperator);62 IFunctionTree parent = gardener.GetRandomParentNode(root); 63 63 if(parent == null) { 64 64 // parent == null means we should subsitute the whole tree 65 65 // => create a new random tree 66 66 67 // create a new random operator tree 68 69 IOperator newOperatorTree; 67 // create a new random function tree 68 IFunctionTree newTree; 70 69 if(random.NextDouble() <= balancedTreesRate) { 71 new OperatorTree = gardener.CreateRandomTree(gardener.AllOperators, maxTreeSize, maxTreeHeight, true);70 newTree = gardener.CreateRandomTree(gardener.AllFunctions, maxTreeSize, maxTreeHeight, true); 72 71 } else { 73 new OperatorTree = gardener.CreateRandomTree(gardener.AllOperators, maxTreeSize, maxTreeHeight, false);72 newTree = gardener.CreateRandomTree(gardener.AllFunctions, maxTreeSize, maxTreeHeight, false); 74 73 } 75 74 76 if(!gardener.IsValidTree(new OperatorTree)) {75 if(!gardener.IsValidTree(newTree)) { 77 76 throw new InvalidProgramException(); 78 77 } 79 78 80 79 // update the variables in the scope with the new values 81 GetVariableValue<IntData>("TreeSize", scope, true).Data = gardener.GetTreeSize(new OperatorTree);82 GetVariableValue<IntData>("TreeHeight", scope, true).Data = gardener.GetTreeHeight(new OperatorTree);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; 84 83 85 // return a CompositeOperation that randomly initializes the new operator86 return gardener.CreateInitializationOperation(gardener.GetAll Operators(newOperatorTree), scope);84 // return a CompositeOperation that randomly initializes the new tree 85 return gardener.CreateInitializationOperation(gardener.GetAllSubTrees(newTree), scope); 87 86 } else { 88 87 // 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) { 95 92 // don't change anything 96 93 // this shouldn't happen … … 100 97 // calculate the maximum size and height of the new sub-tree based on the location where 101 98 // it will be inserted 102 int parentLevel = gardener.Get NodeLevel(rootOperator, parent);99 int parentLevel = gardener.GetBranchLevel(root, parent); 103 100 104 101 int maxSubTreeHeight = maxTreeHeight - parentLevel; 105 int maxSubTreeSize = maxTreeSize - (treeSize - gardener.GetTreeSize(parent.Sub Operators[childIndex]));102 int maxSubTreeSize = maxTreeSize - (treeSize - gardener.GetTreeSize(parent.SubTrees[childIndex])); 106 103 107 // get a random operatorTree108 I Operator newOperatorTree;104 // create a random function tree 105 IFunctionTree newTree; 109 106 if(random.NextDouble() <= balancedTreesRate) { 110 new OperatorTree = gardener.CreateRandomTree(allowedOperators, maxSubTreeSize, maxSubTreeHeight, true);107 newTree = gardener.CreateRandomTree(allowedFunctions, maxSubTreeSize, maxSubTreeHeight, true); 111 108 } else { 112 new OperatorTree = gardener.CreateRandomTree(allowedOperators, maxSubTreeSize, maxSubTreeHeight, false);109 newTree = gardener.CreateRandomTree(allowedFunctions, maxSubTreeSize, maxSubTreeHeight, false); 113 110 } 114 111 115 IOperator oldChild = parent.SubOperators[childIndex]; 116 parent.RemoveSubOperator(childIndex); 117 parent.AddSubOperator(newOperatorTree, childIndex); 112 parent.RemoveSubTree(childIndex); 113 parent.InsertSubTree(childIndex, newTree); 118 114 119 if(!gardener.IsValidTree(root Operator)) {115 if(!gardener.IsValidTree(root)) { 120 116 throw new InvalidProgramException(); 121 117 } 122 118 123 119 // 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 128 123 // return a CompositeOperation that randomly initializes all nodes of the new subtree 129 return gardener.CreateInitializationOperation(gardener.GetAll Operators(newOperatorTree), scope);124 return gardener.CreateInitializationOperation(gardener.GetAllSubTrees(newTree), scope); 130 125 } 131 126 } -
trunk/sources/HeuristicLab.StructureIdentification/RandomTreeCreator.cs
r23 r155 26 26 using System; 27 27 using HeuristicLab.Random; 28 using HeuristicLab.Functions; 28 29 29 30 namespace HeuristicLab.StructureIdentification { … … 40 41 AddVariableInfo(new VariableInfo("MaxTreeSize", "The maximal allowed size (number of nodes) of the tree", typeof(IntData), VariableKind.In)); 41 42 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)); 45 46 } 46 47 … … 56 57 int treeHeight = random.Next(1, maxTreeHeight + 1); 57 58 int treeSize = random.Next(1, maxTreeSize + 1); 58 I Operator rootOperator;59 IFunctionTree root; 59 60 if(random.NextDouble() <= balancedTreesRate) { 60 root Operator= gardener.CreateRandomTree(treeSize, treeHeight, true);61 root = gardener.CreateRandomTree(treeSize, treeHeight, true); 61 62 } else { 62 root Operator= gardener.CreateRandomTree(treeSize, treeHeight, false);63 root = gardener.CreateRandomTree(treeSize, treeHeight, false); 63 64 } 64 65 65 int actualTreeSize = gardener.GetTreeSize(root Operator);66 int actualTreeHeight = gardener.GetTreeHeight(root Operator);66 int actualTreeSize = gardener.GetTreeSize(root); 67 int actualTreeHeight = gardener.GetTreeHeight(root); 67 68 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))); 71 72 72 if(!gardener.IsValidTree(root Operator)) { throw new InvalidProgramException(); }73 if(!gardener.IsValidTree(root)) { throw new InvalidProgramException(); } 73 74 74 75 if(actualTreeSize > maxTreeSize || … … 77 78 } 78 79 79 return gardener.CreateInitializationOperation(gardener.GetAll Operators(rootOperator), scope);80 return gardener.CreateInitializationOperation(gardener.GetAllSubTrees(root), scope); 80 81 } 81 82 } -
trunk/sources/HeuristicLab.StructureIdentification/Recombination/SinglePointCrossOver.cs
r23 r155 29 29 using HeuristicLab.Data; 30 30 using HeuristicLab.Constraints; 31 using HeuristicLab.Functions; 31 32 32 33 namespace HeuristicLab.StructureIdentification { … … 44 45 AddVariableInfo(new VariableInfo("MaxTreeHeight", "The maximal allowed height of the tree", typeof(IntData), VariableKind.In)); 45 46 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)); 49 50 } 50 51 … … 77 78 } 78 79 79 80 80 private IOperation Cross(TreeGardener gardener, int maxTreeSize, int maxTreeHeight, 81 81 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 89 86 90 87 int newTreeSize = gardener.GetTreeSize(newTree); 91 88 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 || 98 96 newTreeSize > maxTreeSize) { 99 97 throw new InvalidProgramException(); 100 98 } 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); 109 105 int tree0Height = f.GetVariableValue<IntData>("TreeHeight", false).Data; 110 106 int tree0Size = f.GetVariableValue<IntData>("TreeSize", false).Data; 111 107 112 I Operator tree1 = g.GetVariableValue<IOperator>("OperatorTree", false);108 IFunctionTree tree1 = g.GetVariableValue<IFunctionTree>("FunctionTree", false); 113 109 int tree1Height = g.GetVariableValue<IntData>("TreeHeight", false).Data; 114 110 int tree1Size = g.GetVariableValue<IntData>("TreeSize", false).Data; 115 111 116 112 if(tree0Size == 1 && tree1Size == 1) { 117 return CombineTerminals(gardener, tree0, tree1, random, maxTreeHeight, out new Operators);113 return CombineTerminals(gardener, tree0, tree1, random, maxTreeHeight, out newBranches); 118 114 } else { 119 115 // we are going to insert tree1 into tree0 at a random place so we have to make sure that tree0 is not a terminal 120 116 // in case both trees are higher than 1 we swap the trees with probability 50% 121 117 if(tree0Height == 1 || (tree1Height > 1 && random.Next(2) == 0)) { 122 I Operatortmp = tree0; tree0 = tree1; tree1 = tmp;118 IFunctionTree tmp = tree0; tree0 = tree1; tree1 = tmp; 123 119 int tmpHeight = tree0Height; tree0Height = tree1Height; tree1Height = tmpHeight; 124 120 int tmpSize = tree0Size; tree0Size = tree1Size; tree1Size = tmpSize; … … 126 122 127 123 // save the root because later on we change tree0 and tree1 while searching a valid tree configuration 128 I Operatorroot = tree0;124 IFunctionTree root = tree0; 129 125 int rootSize = tree0Size; 130 126 … … 132 128 int tree0Level = random.Next(tree0Height - 1); // since we checked before that the height of tree0 is > 1 this is OK 133 129 int tree1Level = random.Next(tree1Height); 134 tree0 = gardener.GetRandom Node(tree0, tree0Level);135 tree1 = gardener.GetRandom Node(tree1, tree1Level);130 tree0 = gardener.GetRandomBranch(tree0, tree0Level); 131 tree1 = gardener.GetRandomBranch(tree1, tree1Level); 136 132 137 133 // recalculate the size and height of tree1 (the one that we want to insert) because we need to check constraints later on … … 140 136 141 137 List<int> possibleChildIndices = new List<int>(); 142 TreeGardener.OperatorEqualityComparer comparer = new TreeGardener.OperatorEqualityComparer();143 138 144 139 // Now tree0 is supposed to take tree1 as one if its children. If this is not possible, 145 140 // then go down in either of the two trees as far as possible. If even then it is not possible 146 141 // 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.Sub Operators.Count; i++) {149 int sub OperatorSize = gardener.GetTreeSize(tree0.SubOperators[i]);150 151 // the index is ok when the operator is allowed as sub-operatorand we don't violate the maxSize and maxHeight constraints152 if( GetAllowedOperators(tree0, i).Contains(tree1, comparer) &&153 rootSize - sub OperatorSize + 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 && 154 149 tree0Level + tree1Height < maxTreeHeight) { 155 150 possibleChildIndices.Add(i); … … 158 153 159 154 while(possibleChildIndices.Count == 0) { 160 // okwe couln't find a possible configuration given the current tree0 and tree1155 // we couln't find a possible configuration given the current tree0 and tree1 161 156 // possible reasons for this are: 162 // - tree1 is not allowed as sub- operatorof tree0157 // - tree1 is not allowed as sub-tree of tree0 163 158 // - appending tree1 as child of tree0 would create a tree that exceedes the maxTreeHeight 164 159 // - replacing any child of tree0 with tree1 woulde create a tree that exceedes the maxTeeSize … … 166 161 // - go up in tree0 => the insert position allows larger trees 167 162 // - go down in tree1 => the tree that is inserted becomes smaller 168 // - however we have to get lucky to solve the 'allowed sub- operators' problem163 // - however we have to get lucky to solve the 'allowed sub-trees' problem 169 164 if(tree1Height == 1 || (tree0Level>0 && random.Next(2) == 0)) { 170 165 // go up in tree0 171 166 tree0Level--; 172 tree0 = gardener.GetRandom Node(root, tree0Level);173 } else if(tree1.Sub Operators.Count > 0) {167 tree0 = gardener.GetRandomBranch(root, tree0Level); 168 } else if(tree1.SubTrees.Count > 0) { 174 169 // go down in node2: 175 tree1 = tree1.Sub Operators[random.Next(tree1.SubOperators.Count)];170 tree1 = tree1.SubTrees[random.Next(tree1.SubTrees.Count)]; 176 171 tree1Size = gardener.GetTreeSize(tree1); 177 172 tree1Height = gardener.GetTreeHeight(tree1); … … 183 178 // recalculate the list of possible indices 184 179 possibleChildIndices.Clear(); 185 for(int i = 0; i < tree0.Sub Operators.Count; i++) {186 int sub OperatorSize = gardener.GetTreeSize(tree0.SubOperators[i]);187 188 // when the operator is allowed as sub-operatorand we don't violate the maxSize and maxHeight constraints180 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 189 184 // the index is ok 190 if( GetAllowedOperators(tree0, i).Contains(tree1, comparer) &&191 rootSize - sub OperatorSize + tree1Size < maxTreeSize &&185 if(gardener.GetAllowedSubFunctions(tree0.Function, i).Contains(tree1.Function) && 186 rootSize - subTreeSize + tree1Size < maxTreeSize && 192 187 tree0Level + tree1Height < maxTreeHeight) { 193 188 possibleChildIndices.Add(i); … … 203 198 // replace the existing sub-tree at a random index in tree0 with tree1 204 199 int selectedIndex = possibleChildIndices[random.Next(possibleChildIndices.Count)]; 205 tree0.RemoveSub Operator(selectedIndex);206 tree0. AddSubOperator(tree1, selectedIndex);200 tree0.RemoveSubTree(selectedIndex); 201 tree0.InsertSubTree(selectedIndex, tree1); 207 202 208 203 // no new operators where needed 209 new Operators = new List<IOperator>();204 newBranches = new List<IFunctionTree>(); 210 205 return root; 211 206 } 212 207 } 213 208 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 }); 222 220 if(possibleParents.Count == 0) throw new InvalidProgramException(); 223 224 I Operator 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()))); 225 223 226 224 int minArity; 227 225 int maxArity; 228 gardener.GetMinMaxArity(parent, out minArity, out maxArity); 229 226 gardener.GetMinMaxArity(parent.Function, out minArity, out maxArity); 230 227 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]; 236 230 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) 244 244 for(int i = 0; i < slotSequence.Length; i++) { 245 245 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])); 251 252 } 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 254 257 for(int j = i + 1; j < slotSequence.Length; j++) { 255 258 int otherSlot = slotSequence[j]; 256 slot Sets[otherSlot].Remove(selectedOperator);257 } 258 } 259 } 260 261 for(int i = 0; i < selected Operators.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]); 263 266 } 264 267 -
trunk/sources/HeuristicLab.StructureIdentification/TreeGardener.cs
r23 r155 31 31 using HeuristicLab.Operators; 32 32 using HeuristicLab.Selection; 33 using HeuristicLab.Functions; 34 using System.Collections; 33 35 34 36 namespace HeuristicLab.StructureIdentification { 35 37 internal class TreeGardener { 36 38 private IRandom random; 37 private IOperatorLibrary opLibrary;38 private List<I Operator> functions;39 private List<I Operator> terminals;40 41 internal IList<I Operator> Terminals {39 private GPOperatorLibrary funLibrary; 40 private List<IFunction> functions; 41 private List<IFunction> terminals; 42 43 internal IList<IFunction> Terminals { 42 44 get { return terminals.AsReadOnly(); } 43 45 } 44 private List<I Operator> allOperators;45 46 internal IList<I Operator> AllOperators {47 get { return all Operators.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) { 51 53 this.random = random; 52 this. opLibrary = opLibrary;53 54 this.all Operators = new List<IOperator>();55 terminals = new List<I Operator>();56 functions = new List<I Operator>();54 this.funLibrary = funLibrary; 55 56 this.allFunctions = new List<IFunction>(); 57 terminals = new List<IFunction>(); 58 functions = new List<IFunction>(); 57 59 58 60 // init functions and terminals based on constraints 59 foreach (I Operator op in opLibrary.Group.Operators) {61 foreach (IFunction fun in funLibrary.Group.Operators) { 60 62 int maxA, minA; 61 GetMinMaxArity( op, out minA, out maxA);63 GetMinMaxArity(fun, out minA, out maxA); 62 64 if (maxA == 0) { 63 terminals.Add( op);65 terminals.Add(fun); 64 66 } else { 65 functions.Add( op);66 } 67 } 68 69 all Operators.AddRange(functions);70 all Operators.AddRange(terminals);67 functions.Add(fun); 68 } 69 } 70 71 allFunctions.AddRange(functions); 72 allFunctions.AddRange(terminals); 71 73 } 72 74 73 75 #region random initialization 74 internal I Operator CreateRandomTree(ICollection<IOperator> allowedOperators, int maxTreeSize, int maxTreeHeight, bool balanceTrees) {75 76 int minTreeHeight = allowed Operators.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(); 77 79 if (minTreeHeight > maxTreeHeight) 78 80 maxTreeHeight = minTreeHeight; 79 81 80 int minTreeSize = allowed Operators.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(); 81 83 if (minTreeSize > maxTreeSize) 82 84 maxTreeSize = minTreeSize; … … 85 87 int treeSize = random.Next(minTreeSize, maxTreeSize + 1); 86 88 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) { 97 97 if (balanceTrees) { 98 98 if (maxTreeHeight == 1 || maxTreeSize==1) { 99 I Operator selectedTerminal = (IOperator)terminals[random.Next(terminals.Count())].Clone();100 return selectedTerminal;99 IFunction selectedTerminal = terminals[random.Next(terminals.Count())]; 100 return new FunctionTree(selectedTerminal); 101 101 } else { 102 I Operator[] possibleFunctions = functions.Where(f => GetMinimalTreeHeight(f) <= maxTreeHeight &&102 IFunction[] possibleFunctions = functions.Where(f => GetMinimalTreeHeight(f) <= maxTreeHeight && 103 103 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; 107 108 } 108 109 109 110 } 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); 119 122 if (balanceTrees) { 120 123 MakeBalancedTree(root, maxTreeSize - 1, maxTreeHeight - 1); … … 130 133 131 134 132 private void MakeUnbalancedTree(I Operatorparent, int maxTreeSize, int maxTreeHeight) {135 private void MakeUnbalancedTree(IFunctionTree parent, int maxTreeSize, int maxTreeHeight) { 133 136 if (maxTreeHeight == 0 || maxTreeSize == 0) return; 134 137 int minArity; 135 138 int maxArity; 136 GetMinMaxArity(parent , out minArity, out maxArity);139 GetMinMaxArity(parent.Function, out minArity, out maxArity); 137 140 if (maxArity >= maxTreeSize) { 138 141 maxArity = maxTreeSize; … … 142 145 int maxSubTreeSize = maxTreeSize / actualArity; 143 146 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); 149 153 } 150 154 } … … 152 156 153 157 // NOTE: this method doesn't build fully balanced trees because we have constraints on the 154 // types of possible sub operators which can indirectly impose a limit for the depth of a given suboperator155 private void MakeBalancedTree(I Operatorparent, 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) { 156 160 if (maxTreeHeight == 0 || maxTreeSize == 0) return; // should never happen anyway 157 161 int minArity; 158 162 int maxArity; 159 GetMinMaxArity(parent , out minArity, out maxArity);163 GetMinMaxArity(parent.Function, out minArity, out maxArity); 160 164 if (maxArity >= maxTreeSize) { 161 165 maxArity = maxTreeSize; … … 166 170 for (int i = 0; i < actualArity; i++) { 167 171 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); 174 179 } 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); 182 188 } 183 189 } … … 185 191 } 186 192 187 internal CompositeOperation CreateInitializationOperation(ICollection<I Operator> operators, IScope scope) {193 internal CompositeOperation CreateInitializationOperation(ICollection<IFunctionTree> trees, IScope scope) { 188 194 // needed for the parameter shaking operation 189 195 CompositeOperation initializationOperation = new CompositeOperation(); 190 196 Scope tempScope = new Scope("Temp. initialization scope"); 191 197 192 var parametric Operators = operators.Where(o => o.GetVariable(GPOperatorLibrary.INITIALIZATION) != null);193 194 foreach (I Operator op in parametricOperators) {198 var parametricTrees = trees.Where(t => t.Function.GetVariable(GPOperatorLibrary.INITIALIZATION) != null); 199 200 foreach (IFunctionTree tree in parametricTrees) { 195 201 // 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; 197 203 Scope initScope = new Scope(); 198 204 199 205 // 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); 204 208 } 205 209 … … 223 227 224 228 #region tree information gathering 225 internal int GetTreeSize(I Operatortree) {226 return 1 + tree.Sub Operators.Sum(f => GetTreeSize(f));227 } 228 229 internal int GetTreeHeight(I Operatortree) {230 if (tree.Sub Operators.Count == 0) return 1;231 return 1 + tree.Sub Operators.Max(f => GetTreeHeight(f));232 } 233 234 internal I Operator GetRandomParentNode(IOperatortree) {235 List<I Operator> 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>(); 236 240 237 241 // add null for the parent of the root node 238 242 parentNodes.Add(null); 239 243 240 TreeForEach(tree, delegate(I Operator 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); 243 247 } 244 248 }); … … 247 251 } 248 252 249 internal IList<I Operator> GetAllowedSubOperators(IOperator op, int index) {250 if ( op== null) {251 return all Operators;253 internal IList<IFunction> GetAllowedSubFunctions(IFunction f, int index) { 254 if (f == null) { 255 return allFunctions; 252 256 } 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) { 262 267 NumberOfSubOperatorsConstraint theConstraint = constraint as NumberOfSubOperatorsConstraint; 263 268 if (theConstraint != null) { … … 271 276 maxArity = 2; 272 277 } 273 internal bool IsTerminal(I Operatorf) {278 internal bool IsTerminal(IFunction f) { 274 279 int minArity; 275 280 int maxArity; … … 278 283 } 279 284 280 internal IList<I Operator> GetAllowedParents(IOperatorchild, int childIndex) {281 List<I Operator> parents = new List<IOperator>();282 foreach (I Operatorfunction in functions) {283 I List<IOperator> allowedSubOperators = GetAllowedSubOperators(function, childIndex);284 if (allowedSub Operators.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)) { 285 290 parents.Add(function); 286 291 } … … 289 294 } 290 295 291 internal ICollection<I Operator> GetAllOperators(IOperatorroot) {292 List<I Operator> allOps = new List<IOperator>();293 TreeForEach(root, t => { all Ops.Add(t); });294 return all Ops;296 internal ICollection<IFunctionTree> GetAllSubTrees(IFunctionTree root) { 297 List<IFunctionTree> allTrees = new List<IFunctionTree>(); 298 TreeForEach(root, t => { allTrees.Add(t); }); 299 return allTrees; 295 300 } 296 301 297 302 /// <summary> 298 /// returns the height level of opin the tree299 /// if the op== tree => 1300 /// if op is in the suboperators of tree => 2303 /// 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 301 306 /// ... 302 /// if opis not found => -1307 /// if branch is not found => -1 303 308 /// </summary> 304 /// <param name="tree"> operatortree to process</param>305 /// <param name=" op">operaterthat 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> 306 311 /// <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); 316 322 if (result != -1) return result; 317 323 } … … 320 326 } 321 327 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 } 330 340 return true; 331 341 } 332 342 333 // returns a random nodefrom the specified level in the tree334 internal I Operator GetRandomNode(IOperatortree, int level) {343 // returns a random branch from the specified level in the tree 344 internal IFunctionTree GetRandomBranch(IFunctionTree tree, int level) { 335 345 if (level == 0) return tree; 336 List<I Operator> 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)]; 338 348 } 339 349 #endregion … … 349 359 } 350 360 351 private void TreeForEach(I Operator tree, Action<IOperator> action) {361 private void TreeForEach(IFunctionTree tree, Action<IFunctionTree> action) { 352 362 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 } 364 387 } 365 388 return result; 366 389 } 367 390 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) { 397 392 int minArity; 398 393 int maxArity; 399 GetMinMaxArity( op, out minArity, out maxArity);394 GetMinMaxArity(f, out minArity, out maxArity); 400 395 401 396 // note: we can't assume that the operators in the children list have different types! … … 409 404 410 405 SubOperatorsConstraintAnalyser analyzer = new SubOperatorsConstraintAnalyser(); 411 analyzer.AllPossibleOperators = children ;412 413 List<HashSet<I Operator>> slotSets = new List<HashSet<IOperator>>();414 415 // we iterate through all slots for sub- operators and calculate the set of416 // 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. 417 412 // we only count those slots that can hold at least one of the children that we should combine 418 413 for (int slot = 0; slot < nSlots; slot++) { 419 HashSet<I Operator> 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); 422 417 } 423 418 } … … 426 421 // hold one of our children. 427 422 // 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 operator423 // we can never combine all children as sub-trees of the function and thus the function 429 424 // can't be a parent. 430 425 if (slotSets.Count() < children.Count()) { … … 433 428 434 429 // 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-operatorfrom the remaining sets.436 // when we can successfully assign all available children to a slot the operatoris a valid parent437 // when only a subset of all children can be assigned to slots the operatoris no valid parent430 // 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 438 433 slotSets.Sort((p, q) => p.Count() - q.Count()); 439 434 … … 441 436 for (int i = 0; i < slotSets.Count() - 1; i++) { 442 437 if (slotSets[i].Count > 0) { 443 I Operatorselected = slotSets[i].ElementAt(0);438 IFunction selected = slotSets[i].ElementAt(0); 444 439 assignments++; 445 440 for (int j = i + 1; j < slotSets.Count(); j++) {
Note: See TracChangeset
for help on using the changeset viewer.