Changeset 2222 for trunk/sources/HeuristicLab.GP/3.3/TreeGardener.cs
- Timestamp:
- 08/03/09 12:26:42 (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/sources/HeuristicLab.GP/3.3/TreeGardener.cs
r1529 r2222 22 22 using System; 23 23 using System.Collections.Generic; 24 using System.Text;25 24 using HeuristicLab.Core; 26 using HeuristicLab.Constraints;27 using System.Diagnostics;28 using HeuristicLab.Data;29 25 using System.Linq; 30 using HeuristicLab.Random;31 using HeuristicLab.Operators;32 26 using System.Collections; 33 using HeuristicLab. Selection;27 using HeuristicLab.GP.Interfaces; 34 28 35 29 namespace HeuristicLab.GP { 36 internalclass TreeGardener {30 public class TreeGardener { 37 31 private IRandom random; 38 private GPOperatorLibrary funLibrary;32 private FunctionLibrary funLibrary; 39 33 private List<IFunction> functions; 40 34 41 35 private List<IFunction> terminals; 42 internalIList<IFunction> Terminals {36 public IList<IFunction> Terminals { 43 37 get { return terminals; } 44 38 } 45 39 46 40 private List<IFunction> allFunctions; 47 internalIList<IFunction> AllFunctions {41 public IList<IFunction> AllFunctions { 48 42 get { return allFunctions; } 49 43 } 50 44 51 45 #region constructors 52 internal TreeGardener(IRandom random, GPOperatorLibrary funLibrary) {46 public TreeGardener(IRandom random, FunctionLibrary funLibrary) { 53 47 this.random = random; 54 48 this.funLibrary = funLibrary; … … 57 51 functions = new List<IFunction>(); 58 52 // init functions and terminals based on constraints 59 foreach(IFunction fun in funLibrary. Group.Operators) {60 if(fun.Max Arity== 0) {53 foreach(IFunction fun in funLibrary.Functions) { 54 if(fun.MaxSubTrees == 0) { 61 55 terminals.Add(fun); 62 56 allFunctions.Add(fun); … … 77 71 /// <param name="maxTreeHeight">Maximal height of the tree.</param> 78 72 /// <returns></returns> 79 internalIFunctionTree CreateBalancedRandomTree(int maxTreeSize, int maxTreeHeight) {73 public IFunctionTree CreateBalancedRandomTree(int maxTreeSize, int maxTreeHeight) { 80 74 IFunction rootFunction = GetRandomRoot(maxTreeSize, maxTreeHeight); 81 75 IFunctionTree tree = MakeBalancedTree(rootFunction, maxTreeHeight - 1); … … 90 84 /// <param name="maxTreeHeight">Maximal height of the tree.</param> 91 85 /// <returns></returns> 92 internalIFunctionTree CreateUnbalancedRandomTree(int maxTreeSize, int maxTreeHeight) {86 public IFunctionTree CreateUnbalancedRandomTree(int maxTreeSize, int maxTreeHeight) { 93 87 IFunction rootFunction = GetRandomRoot(maxTreeSize, maxTreeHeight); 94 88 IFunctionTree tree = MakeUnbalancedTree(rootFunction, maxTreeHeight - 1); … … 96 90 } 97 91 98 internal IFunctionTree PTC2(IRandom random,int size, int maxDepth) {99 return PTC2( random,GetRandomRoot(size, maxDepth), size, maxDepth);100 } 101 102 internal IFunctionTree PTC2(IRandom random, IFunction rootF, int size, int maxDepth) {103 IFunctionTree root = rootF .GetTreeNode();104 if (size <= 1 || maxDepth <= 1) return root;92 public IFunctionTree PTC2(int size, int maxDepth) { 93 return PTC2(GetRandomRoot(size, maxDepth), size, maxDepth); 94 } 95 96 private IFunctionTree PTC2(IFunction rootFunction, int size, int maxDepth) { 97 IFunctionTree root = rootFunction.GetTreeNode(); 98 if (size <= 1 || maxDepth <= 1) return root; 105 99 List<object[]> list = new List<object[]>(); 106 100 int currentSize = 1; 107 101 int totalListMinSize = 0; 108 int minArity = root.Function.Min Arity;109 int maxArity = root.Function.Max Arity;110 if (maxArity >= size) {102 int minArity = root.Function.MinSubTrees; 103 int maxArity = root.Function.MaxSubTrees; 104 if (maxArity >= size) { 111 105 maxArity = size; 112 106 } 113 107 int actualArity = random.Next(minArity, maxArity + 1); 114 totalListMinSize += GetMinimalTreeSize(root.Function)- 1;115 for (int i = 0; i < actualArity; i++) {108 totalListMinSize += root.Function.MinTreeSize - 1; 109 for (int i = 0; i < actualArity; i++) { 116 110 // insert a dummy sub-tree and add the pending extension to the list 117 111 root.AddSubTree(null); … … 119 113 } 120 114 121 while (list.Count > 0 && totalListMinSize + currentSize < size) {115 while (list.Count > 0 && totalListMinSize + currentSize < size) { 122 116 int randomIndex = random.Next(list.Count); 123 117 object[] nextExtension = list[randomIndex]; … … 126 120 int a = (int)nextExtension[1]; 127 121 int d = (int)nextExtension[2]; 128 if (d == maxDepth) {122 if (d == maxDepth) { 129 123 parent.RemoveSubTree(a); 130 124 IFunctionTree branch = CreateRandomTree(GetAllowedSubFunctions(parent.Function, a), 1, 1); 131 125 parent.InsertSubTree(a, branch); // insert a smallest possible tree 132 currentSize += branch. Size;133 totalListMinSize -= branch. Size;126 currentSize += branch.GetSize(); 127 totalListMinSize -= branch.GetSize(); 134 128 } else { 135 IFunction selectedFunction = RandomSelect(GetAllowedSubFunctions(parent.Function, a).Where(136 f => ! IsTerminal(f) && GetMinimalTreeHeight(f)+ (d - 1) <= maxDepth).ToArray());129 IFunction selectedFunction = TreeGardener.RandomSelect(random, GetAllowedSubFunctions(parent.Function, a).Where( 130 f => !TreeGardener.IsTerminal(f) && f.MinTreeHeight + (d - 1) <= maxDepth).ToArray()); 137 131 IFunctionTree newTree = selectedFunction.GetTreeNode(); 138 132 parent.RemoveSubTree(a); … … 141 135 totalListMinSize--; 142 136 143 minArity = selectedFunction.Min Arity;144 maxArity = selectedFunction.Max Arity;145 if (maxArity >= size) {137 minArity = selectedFunction.MinSubTrees; 138 maxArity = selectedFunction.MaxSubTrees; 139 if (maxArity >= size) { 146 140 maxArity = size; 147 141 } 148 142 actualArity = random.Next(minArity, maxArity + 1); 149 for (int i = 0; i < actualArity; i++) {143 for (int i = 0; i < actualArity; i++) { 150 144 // insert a dummy sub-tree and add the pending extension to the list 151 145 newTree.AddSubTree(null); 152 146 list.Add(new object[] { newTree, i, d + 1 }); 153 147 } 154 totalListMinSize += GetMinimalTreeSize(newTree.Function)- 1;155 } 156 } 157 while (list.Count > 0) {148 totalListMinSize += newTree.Function.MinTreeSize - 1; 149 } 150 } 151 while (list.Count > 0) { 158 152 int randomIndex = random.Next(list.Count); 159 153 object[] nextExtension = list[randomIndex]; … … 168 162 return root; 169 163 } 170 164 171 165 /// <summary> 172 166 /// selects a random function from allowedFunctions and creates a random (unbalanced) tree with maximal size and height. … … 176 170 /// <param name="maxTreeHeight">Maximal height of the tree.</param> 177 171 /// <returns>New random unbalanced tree</returns> 178 internalIFunctionTree CreateRandomTree(ICollection<IFunction> allowedFunctions, int maxTreeSize, int maxTreeHeight) {172 public IFunctionTree CreateRandomTree(ICollection<IFunction> allowedFunctions, int maxTreeSize, int maxTreeHeight) { 179 173 // get the minimal needed height based on allowed functions and extend the max-height if necessary 180 int minTreeHeight = allowedFunctions.Select(f => GetMinimalTreeHeight(f)).Min();174 int minTreeHeight = allowedFunctions.Select(f => f.MinTreeHeight).Min(); 181 175 if(minTreeHeight > maxTreeHeight) 182 176 maxTreeHeight = minTreeHeight; 183 177 // get the minimal needed size based on allowed functions and extend the max-size if necessary 184 int minTreeSize = allowedFunctions.Select(f => GetMinimalTreeSize(f)).Min();178 int minTreeSize = allowedFunctions.Select(f => f.MinTreeSize).Min(); 185 179 if(minTreeSize > maxTreeSize) 186 180 maxTreeSize = minTreeSize; … … 191 185 192 186 // filter the set of allowed functions and select only from those that fit into the given maximal size and height limits 193 IFunction[] possibleFunctions = allowedFunctions.Where(f => GetMinimalTreeHeight(f)<= treeHeight &&194 GetMinimalTreeSize(f)<= treeSize).ToArray();187 IFunction[] possibleFunctions = allowedFunctions.Where(f => f.MinTreeHeight <= treeHeight && 188 f.MinTreeSize <= treeSize).ToArray(); 195 189 IFunction selectedFunction = RandomSelect(possibleFunctions); 196 190 197 191 // build the tree 198 192 IFunctionTree root; 199 root = PTC2( random,selectedFunction, maxTreeSize, maxTreeHeight);193 root = PTC2(selectedFunction, maxTreeSize, maxTreeHeight); 200 194 return root; 201 195 } 202 203 internal CompositeOperation CreateInitializationOperation(ICollection<IFunctionTree> trees, IScope scope) {204 // needed for the parameter shaking operation205 CompositeOperation initializationOperation = new CompositeOperation();206 Scope tempScope = new Scope("Temp. initialization scope");207 208 var parametricTrees = trees.Where(t => t.Function.GetVariable(FunctionBase.INITIALIZATION) != null);209 foreach(IFunctionTree tree in parametricTrees) {210 // enqueue an initialization operation for each operator with local variables211 IOperator initialization = (IOperator)tree.Function.GetVariable(FunctionBase.INITIALIZATION).Value;212 Scope initScope = new Scope();213 // copy the local variables into a temporary scope used for initialization214 foreach(IVariable variable in tree.LocalVariables) {215 initScope.AddVariable(variable);216 }217 tempScope.AddSubScope(initScope);218 initializationOperation.AddOperation(new AtomicOperation(initialization, initScope));219 }220 Scope backupScope = new Scope("backup");221 foreach(Scope subScope in scope.SubScopes) {222 backupScope.AddSubScope(subScope);223 }224 scope.AddSubScope(tempScope);225 scope.AddSubScope(backupScope);226 // add an operation to remove the temporary scopes227 initializationOperation.AddOperation(new AtomicOperation(new RightReducer(), scope));228 return initializationOperation;229 }230 196 #endregion 231 197 232 198 #region tree information gathering 233 internalIFunctionTree GetRandomParentNode(IFunctionTree tree) {199 public IFunctionTree GetRandomParentNode(IFunctionTree tree) { 234 200 List<IFunctionTree> parentNodes = new List<IFunctionTree>(); 235 201 … … 246 212 } 247 213 248 internalICollection<IFunctionTree> GetAllSubTrees(IFunctionTree root) {214 public static ICollection<IFunctionTree> GetAllSubTrees(IFunctionTree root) { 249 215 List<IFunctionTree> allTrees = new List<IFunctionTree>(); 250 216 TreeForEach(root, t => { allTrees.Add(t); }); … … 262 228 /// <param name="branch">branch that is searched in the tree</param> 263 229 /// <returns></returns> 264 internalint GetBranchLevel(IFunctionTree tree, IFunctionTree branch) {230 public int GetBranchLevel(IFunctionTree tree, IFunctionTree branch) { 265 231 return GetBranchLevelHelper(tree, branch, 1); 266 232 } … … 278 244 } 279 245 280 internalbool IsValidTree(IFunctionTree tree) {246 public bool IsValidTree(IFunctionTree tree) { 281 247 for(int i = 0; i < tree.SubTrees.Count; i++) { 282 if(!tree.Function. AllowedSubFunctions(i).Contains(tree.SubTrees[i].Function)) return false;283 } 284 285 if(tree.SubTrees.Count < tree.Function.Min Arity || tree.SubTrees.Count > tree.Function.MaxArity)248 if(!tree.Function.GetAllowedSubFunctions(i).Contains(tree.SubTrees[i].Function)) return false; 249 } 250 251 if(tree.SubTrees.Count < tree.Function.MinSubTrees || tree.SubTrees.Count > tree.Function.MaxSubTrees) 286 252 return false; 287 253 foreach(IFunctionTree subTree in tree.SubTrees) { … … 292 258 293 259 // returns a random branch from the specified level in the tree 294 internalIFunctionTree GetRandomBranch(IFunctionTree tree, int level) {260 public IFunctionTree GetRandomBranch(IFunctionTree tree, int level) { 295 261 if(level == 0) return tree; 296 262 List<IFunctionTree> branches = new List<IFunctionTree>(); … … 312 278 313 279 private bool IsPossibleParent(IFunction f, List<IFunction> children) { 314 int minArity = f.Min Arity;315 int maxArity = f.Max Arity;280 int minArity = f.MinSubTrees; 281 int maxArity = f.MaxSubTrees; 316 282 // note: we can't assume that the operators in the children list have different types! 317 283 … … 329 295 // we only count those slots that can hold at least one of the children that we should combine 330 296 for(int slot = 0; slot < nSlots; slot++) { 331 HashSet<IFunction> functionSet = new HashSet<IFunction>(f. AllowedSubFunctions(slot));297 HashSet<IFunction> functionSet = new HashSet<IFunction>(f.GetAllowedSubFunctions(slot)); 332 298 if(functionSet.Count() > 0) { 333 299 slotSets.Add(functionSet); … … 365 331 return assignments == children.Count - 1; 366 332 } 367 internalIList<IFunction> GetAllowedParents(IFunction child, int childIndex) {333 public IList<IFunction> GetAllowedParents(IFunction child, int childIndex) { 368 334 List<IFunction> parents = new List<IFunction>(); 369 335 foreach(IFunction function in functions) { … … 375 341 return parents; 376 342 } 377 internalbool IsTerminal(IFunction f) {378 return f.Min Arity == 0 && f.MaxArity== 0;379 } 380 internal IList<IFunction> GetAllowedSubFunctions(IFunction f, int index) {343 public static bool IsTerminal(IFunction f) { 344 return f.MinSubTrees == 0 && f.MaxSubTrees == 0; 345 } 346 public ICollection<IFunction> GetAllowedSubFunctions(IFunction f, int index) { 381 347 if(f == null) { 382 348 return allFunctions; 383 349 } else { 384 return f. AllowedSubFunctions(index);350 return f.GetAllowedSubFunctions(index); 385 351 } 386 352 } … … 388 354 389 355 #region private utility methods 390 p rivateIFunction GetRandomRoot(int maxTreeSize, int maxTreeHeight) {356 public IFunction GetRandomRoot(int maxTreeSize, int maxTreeHeight) { 391 357 if(maxTreeHeight == 1 || maxTreeSize == 1) { 392 358 IFunction selectedTerminal = RandomSelect(terminals); 393 359 return selectedTerminal; 394 360 } else { 395 IFunction[] possibleFunctions = functions.Where(f => GetMinimalTreeHeight(f)<= maxTreeHeight &&396 GetMinimalTreeSize(f)<= maxTreeSize).ToArray();361 IFunction[] possibleFunctions = functions.Where(f => f.MinTreeHeight <= maxTreeHeight && 362 f.MinTreeSize <= maxTreeSize).ToArray(); 397 363 IFunction selectedFunction = RandomSelect(possibleFunctions); 398 364 return selectedFunction; … … 403 369 private IFunctionTree MakeUnbalancedTree(IFunction parent, int maxTreeHeight) { 404 370 if(maxTreeHeight == 0) return parent.GetTreeNode(); 405 int minArity = parent.Min Arity;406 int maxArity = parent.Max Arity;371 int minArity = parent.MinSubTrees; 372 int maxArity = parent.MaxSubTrees; 407 373 int actualArity = random.Next(minArity, maxArity + 1); 408 374 if(actualArity > 0) { 409 375 IFunctionTree parentTree = parent.GetTreeNode(); 410 376 for(int i = 0; i < actualArity; i++) { 411 IFunction[] possibleFunctions = GetAllowedSubFunctions(parent, i).Where(f => GetMinimalTreeHeight(f)<= maxTreeHeight).ToArray();377 IFunction[] possibleFunctions = GetAllowedSubFunctions(parent, i).Where(f => f.MinTreeHeight <= maxTreeHeight).ToArray(); 412 378 IFunction selectedFunction = RandomSelect(possibleFunctions); 413 379 IFunctionTree newSubTree = MakeUnbalancedTree(selectedFunction, maxTreeHeight - 1); … … 424 390 private IFunctionTree MakeBalancedTree(IFunction parent, int maxTreeHeight) { 425 391 if(maxTreeHeight == 0) return parent.GetTreeNode(); 426 int minArity = parent.Min Arity;427 int maxArity = parent.Max Arity;392 int minArity = parent.MinSubTrees; 393 int maxArity = parent.MaxSubTrees; 428 394 int actualArity = random.Next(minArity, maxArity + 1); 429 395 if(actualArity > 0) { … … 431 397 for(int i = 0; i < actualArity; i++) { 432 398 // first try to find a function that fits into the maxHeight limit 433 IFunction[] possibleFunctions = GetAllowedSubFunctions(parent, i).Where(f => GetMinimalTreeHeight(f)<= maxTreeHeight &&399 IFunction[] possibleFunctions = GetAllowedSubFunctions(parent, i).Where(f => f.MinTreeHeight <= maxTreeHeight && 434 400 !IsTerminal(f)).ToArray(); 435 401 // no possible function found => extend function set to terminals … … 450 416 } 451 417 452 private int GetMinimalTreeHeight(IOperator op) { 453 return ((IntData)op.GetVariable(GPOperatorLibrary.MIN_TREE_HEIGHT).Value).Data; 454 } 455 456 private int GetMinimalTreeSize(IOperator op) { 457 return ((IntData)op.GetVariable(GPOperatorLibrary.MIN_TREE_SIZE).Value).Data; 458 } 459 460 private void TreeForEach(IFunctionTree tree, Action<IFunctionTree> action) { 418 private static void TreeForEach(IFunctionTree tree, Action<IFunctionTree> action) { 461 419 action(tree); 462 420 foreach(IFunctionTree subTree in tree.SubTrees) { … … 465 423 } 466 424 467 private void GetBranchesAtLevel(IFunctionTree tree, int level, List<IFunctionTree> result) {425 private static void GetBranchesAtLevel(IFunctionTree tree, int level, List<IFunctionTree> result) { 468 426 if(level == 1) result.AddRange(tree.SubTrees); 469 427 foreach(IFunctionTree subTree in tree.SubTrees) { 470 if(subTree. Height>= level - 1)428 if(subTree.GetHeight() >= level - 1) 471 429 GetBranchesAtLevel(subTree, level - 1, result); 472 430 } … … 474 432 475 433 private IFunction RandomSelect(IList<IFunction> functionSet) { 434 return RandomSelect(random, functionSet); 435 } 436 437 public static IFunction RandomSelect(IRandom random, IList<IFunction> functionSet) { 476 438 double[] accumulatedTickets = new double[functionSet.Count]; 477 439 double ticketAccumulator = 0; 478 440 int i = 0; 479 441 // precalculate the slot-sizes 480 foreach (IFunction function in functionSet) {481 ticketAccumulator += ((DoubleData)function.GetVariable(GPOperatorLibrary.TICKETS).Value).Data;442 foreach (IFunction function in functionSet) { 443 ticketAccumulator += function.Tickets; 482 444 accumulatedTickets[i] = ticketAccumulator; 483 445 i++; … … 486 448 double r = random.NextDouble() * ticketAccumulator; 487 449 // find the slot that has been hit 488 for (i = 0; i < accumulatedTickets.Length; i++) {489 if (r < accumulatedTickets[i]) return functionSet[i];450 for (i = 0; i < accumulatedTickets.Length; i++) { 451 if (r < accumulatedTickets[i]) return functionSet[i]; 490 452 } 491 453 // sanity check
Note: See TracChangeset
for help on using the changeset viewer.