- Timestamp:
- 04/22/08 18:05:14 (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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
Note: See TracChangeset
for help on using the changeset viewer.