- Timestamp:
- 04/22/08 18:05:14 (17 years ago)
- Location:
- trunk/sources/HeuristicLab.StructureIdentification/Manipulation
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
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 }
Note: See TracChangeset
for help on using the changeset viewer.