Changeset 814 for trunk/sources/HeuristicLab.GP/Recombination
- Timestamp:
- 11/24/08 23:59:29 (16 years ago)
- Location:
- trunk/sources/HeuristicLab.GP/Recombination
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/sources/HeuristicLab.GP/Recombination/LangdonHomologousCrossOver.cs
r656 r814 64 64 TreeGardener gardener = new TreeGardener(random, opLibrary); 65 65 66 if ((scope.SubScopes.Count % 2) != 0)66 if ((scope.SubScopes.Count % 2) != 0) 67 67 throw new InvalidOperationException("Number of parents is not even"); 68 68 69 CompositeOperation initOperations = new CompositeOperation();70 71 69 int children = scope.SubScopes.Count / 2; 72 for (int i = 0; i < children; i++) {70 for (int i = 0; i < children; i++) { 73 71 IScope parent1 = scope.SubScopes[0]; 74 72 scope.RemoveSubScope(parent1); … … 76 74 scope.RemoveSubScope(parent2); 77 75 IScope child = new Scope(i.ToString()); 78 IOperation childInitOperation = Cross(gardener, maxTreeSize, maxTreeHeight, scope, random, parent1, parent2, child); 79 initOperations.AddOperation(childInitOperation); 76 Cross(gardener, maxTreeSize, maxTreeHeight, scope, random, parent1, parent2, child); 80 77 scope.AddSubScope(child); 81 78 } 82 79 83 return initOperations;84 } 85 86 private IOperationCross(TreeGardener gardener, int maxTreeSize, int maxTreeHeight,80 return null; 81 } 82 83 private void Cross(TreeGardener gardener, int maxTreeSize, int maxTreeHeight, 87 84 IScope scope, MersenneTwister random, IScope parent1, IScope parent2, IScope child) { 88 List<IFunctionTree> newBranches;89 85 IFunctionTree newTree = Cross(gardener, parent1, parent2, 90 random, maxTreeSize, maxTreeHeight, out newBranches); 91 92 93 int newTreeSize = newTree.Size; 94 int newTreeHeight = newTree.Height; 86 random, maxTreeSize, maxTreeHeight); 87 95 88 child.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("FunctionTree"), newTree)); 96 child.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("TreeSize"), new IntData(newTreeSize))); 97 child.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("TreeHeight"), new IntData(newTreeHeight))); 98 99 // check if the new tree is valid and if the height of is still in the allowed bounds (we are not so strict for the max-size) 100 Debug.Assert(gardener.IsValidTree(newTree) && newTreeHeight <= maxTreeHeight && newTreeSize <= maxTreeSize); 101 return gardener.CreateInitializationOperation(newBranches, child); 102 } 103 104 105 private IFunctionTree Cross(TreeGardener gardener, IScope f, IScope g, MersenneTwister random, int maxTreeSize, int maxTreeHeight, out List<IFunctionTree> newBranches) { 89 child.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("TreeSize"), new IntData(newTree.Size))); 90 child.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("TreeHeight"), new IntData(newTree.Height))); 91 92 // check if the new tree is valid and if the size and height are still in the allowed bounds 93 Debug.Assert(gardener.IsValidTree(newTree) && newTree.Height <= maxTreeHeight && newTree.Size <= maxTreeSize); 94 } 95 96 private IFunctionTree Cross(TreeGardener gardener, IScope f, IScope g, MersenneTwister random, int maxTreeSize, int maxTreeHeight) { 106 97 IFunctionTree tree0 = f.GetVariableValue<IFunctionTree>("FunctionTree", false); 107 98 int tree0Height = f.GetVariableValue<IntData>("TreeHeight", false).Data; … … 112 103 int tree1Size = g.GetVariableValue<IntData>("TreeSize", false).Data; 113 104 114 if(tree0Size == 1 && tree1Size == 1) { 115 return CombineTerminals(gardener, tree0, tree1, random, maxTreeHeight, out newBranches); 105 // we are going to insert tree1 into tree0 at a random place so we have to make sure that tree0 is not a terminal 106 // in case both trees are higher than 1 we swap the trees with probability 50% 107 if (tree0Height == 1 || (tree1Height > 1 && random.Next(2) == 0)) { 108 IFunctionTree tmp = tree0; tree0 = tree1; tree1 = tmp; 109 int tmpHeight = tree0Height; tree0Height = tree1Height; tree1Height = tmpHeight; 110 int tmpSize = tree0Size; tree0Size = tree1Size; tree1Size = tmpSize; 111 } 112 113 // select a random suboperator of the 'receiving' tree 114 IFunctionTree crossoverPoint = gardener.GetRandomParentNode(tree0); 115 int removedBranchIndex; 116 IFunctionTree removedBranch; 117 IList<IFunction> allowedFunctions; 118 if (crossoverPoint == null) { 119 removedBranchIndex = 0; 120 removedBranch = tree0; 121 allowedFunctions = gardener.GetAllowedSubFunctions(null, 0); 116 122 } else { 117 newBranches = new List<IFunctionTree>(); 118 119 // 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 // in case both trees are higher than 1 we swap the trees with probability 50% 121 if(tree0Height == 1 || (tree1Height > 1 && random.Next(2) == 0)) { 122 IFunctionTree tmp = tree0; tree0 = tree1; tree1 = tmp; 123 int tmpHeight = tree0Height; tree0Height = tree1Height; tree1Height = tmpHeight; 124 int tmpSize = tree0Size; tree0Size = tree1Size; tree1Size = tmpSize; 125 } 126 127 // select a random suboperator of the 'receiving' tree 128 IFunctionTree crossoverPoint = gardener.GetRandomParentNode(tree0); 129 int removedBranchIndex; 130 IFunctionTree removedBranch; 131 IList<IFunction> allowedFunctions; 132 if(crossoverPoint == null) { 123 removedBranchIndex = random.Next(crossoverPoint.SubTrees.Count); 124 removedBranch = crossoverPoint.SubTrees[removedBranchIndex]; 125 allowedFunctions = gardener.GetAllowedSubFunctions(crossoverPoint.Function, removedBranchIndex); 126 } 127 int removedBranchSize = removedBranch.Size; 128 int maxBranchSize = maxTreeSize - (tree0.Size - removedBranchSize); 129 int maxBranchHeight = maxTreeHeight - gardener.GetBranchLevel(tree0, removedBranch) + 1; 130 List<int> removedBranchThread = GetThread(removedBranch, tree0); 131 IFunctionTree insertedBranch = GetReplacementBranch(random, gardener, allowedFunctions, tree1, removedBranchThread, removedBranchSize, maxBranchSize, maxBranchHeight); 132 133 int tries = 0; 134 while (insertedBranch == null) { 135 if (tries++ > MAX_RECOMBINATION_TRIES) { 136 if (random.Next() > 0.5) return tree1; 137 else return tree0; 138 } 139 140 // retry with a different crossoverPoint 141 crossoverPoint = gardener.GetRandomParentNode(tree0); 142 if (crossoverPoint == null) { 133 143 removedBranchIndex = 0; 134 144 removedBranch = tree0; … … 139 149 allowedFunctions = gardener.GetAllowedSubFunctions(crossoverPoint.Function, removedBranchIndex); 140 150 } 141 int removedBranchSize = removedBranch.Size; 142 int maxBranchSize = maxTreeSize - (tree0.Size - removedBranchSize); 143 int maxBranchHeight = maxTreeHeight - gardener.GetBranchLevel(tree0, removedBranch); 144 List<int> removedBranchThread = GetThread(removedBranch, tree0); 145 IFunctionTree insertedBranch = GetReplacementBranch(random, gardener, allowedFunctions, tree1, removedBranchThread, removedBranchSize, maxBranchSize, maxBranchHeight); 146 147 int tries = 0; 148 while(insertedBranch == null) { 149 if(tries++ > MAX_RECOMBINATION_TRIES) { 150 if(random.Next() > 0.5) return tree1; 151 else return tree0; 152 } 153 154 // retry with a different crossoverPoint 155 crossoverPoint = gardener.GetRandomParentNode(tree0); 156 if(crossoverPoint == null) { 157 removedBranchIndex = 0; 158 removedBranch = tree0; 159 allowedFunctions = gardener.GetAllowedSubFunctions(null, 0); 160 } else { 161 removedBranchIndex = random.Next(crossoverPoint.SubTrees.Count); 162 removedBranch = crossoverPoint.SubTrees[removedBranchIndex]; 163 allowedFunctions = gardener.GetAllowedSubFunctions(crossoverPoint.Function, removedBranchIndex); 164 } 165 removedBranchSize = removedBranch.Size; 166 maxBranchSize = maxTreeSize - (tree0.Size - removedBranchSize); 167 maxBranchHeight = maxTreeHeight - gardener.GetBranchLevel(tree0, removedBranch) + 1; 168 removedBranchThread = GetThread(removedBranch, tree0); 169 insertedBranch = GetReplacementBranch(random, gardener, allowedFunctions, tree1, removedBranchThread, removedBranchSize, maxBranchSize, maxBranchHeight); 170 } 171 if(crossoverPoint != null) { 172 // replace the branch below the crossoverpoint with the selected branch from root1 173 crossoverPoint.RemoveSubTree(removedBranchIndex); 174 crossoverPoint.InsertSubTree(removedBranchIndex, insertedBranch); 175 return tree0; 176 } else { 177 return insertedBranch; 178 } 151 removedBranchSize = removedBranch.Size; 152 maxBranchSize = maxTreeSize - (tree0.Size - removedBranchSize); 153 maxBranchHeight = maxTreeHeight - gardener.GetBranchLevel(tree0, removedBranch) + 1; 154 removedBranchThread = GetThread(removedBranch, tree0); 155 insertedBranch = GetReplacementBranch(random, gardener, allowedFunctions, tree1, removedBranchThread, removedBranchSize, maxBranchSize, maxBranchHeight); 156 } 157 if (crossoverPoint != null) { 158 // replace the branch below the crossoverpoint with the selected branch from root1 159 crossoverPoint.RemoveSubTree(removedBranchIndex); 160 crossoverPoint.InsertSubTree(removedBranchIndex, insertedBranch); 161 return tree0; 162 } else { 163 return insertedBranch; 179 164 } 180 165 } … … 188 173 var equalLengthBranches = branches.Where(t => t.Size == removedBranchSize); 189 174 190 if (shorterBranches.Count() == 0 || longerBranches.Count() == 0) {191 if (equalLengthBranches.Count() == 0) {175 if (shorterBranches.Count() == 0 || longerBranches.Count() == 0) { 176 if (equalLengthBranches.Count() == 0) { 192 177 return null; 193 178 } else { … … 201 186 202 187 double r = random.NextDouble(); 203 if (r < pLonger) {188 if (r < pLonger) { 204 189 return longerBranches.OrderBy(t => MatchingSteps(removedBranchThread, t.Thread)).Last().Tree; 205 } else if (r < pLonger + pShorter) {190 } else if (r < pLonger + pShorter) { 206 191 return shorterBranches.OrderBy(t => MatchingSteps(removedBranchThread, t.Thread)).Last().Tree; 207 192 } else { … … 213 198 private int MatchingSteps(List<int> removedBranchThread, List<int> list) { 214 199 int n = Math.Min(removedBranchThread.Count, list.Count); 215 for (int i = 0; i < n; i++) if(removedBranchThread[i] != list[i]) return i;200 for (int i = 0; i < n; i++) if (removedBranchThread[i] != list[i]) return i; 216 201 return n; 217 202 } … … 219 204 private List<int> GetThread(IFunctionTree t, IFunctionTree tree) { 220 205 List<int> thread = new List<int>(); 221 for (int i = 0; i < tree.SubTrees.Count; i++) {222 if (t == tree.SubTrees[i]) {206 for (int i = 0; i < tree.SubTrees.Count; i++) { 207 if (t == tree.SubTrees[i]) { 223 208 thread.Add(i); 224 209 return thread; 225 210 } else { 226 211 thread.AddRange(GetThread(t, tree.SubTrees[i])); 227 if (thread.Count > 0) {212 if (thread.Count > 0) { 228 213 thread.Insert(0, i); 229 214 return thread; … … 233 218 return thread; 234 219 } 235 236 237 // take f and g and create a tree that has f and g as sub-trees238 // example239 // O240 // /|\241 // g 2 f242 //243 private IFunctionTree CombineTerminals(TreeGardener gardener, IFunctionTree f, IFunctionTree g, MersenneTwister random, int maxTreeHeight, out List<IFunctionTree> newBranches) {244 newBranches = new List<IFunctionTree>();245 // determine the set of possible parent functions246 ICollection<IFunction> possibleParents = gardener.GetPossibleParents(new List<IFunction>() { f.Function, g.Function });247 if(possibleParents.Count == 0) throw new InvalidProgramException();248 // and select a random one249 IFunctionTree parent = possibleParents.ElementAt(random.Next(possibleParents.Count())).GetTreeNode();250 251 int nSlots = Math.Max(2, parent.Function.MinArity);252 // determine which slot can take which sub-trees253 List<IFunctionTree>[] slots = new List<IFunctionTree>[nSlots];254 for(int slot = 0; slot < nSlots; slot++) {255 ICollection<IFunction> allowedSubFunctions = gardener.GetAllowedSubFunctions(parent.Function, slot);256 List<IFunctionTree> allowedTrees = new List<IFunctionTree>();257 if(allowedSubFunctions.Contains(f.Function)) allowedTrees.Add(f);258 if(allowedSubFunctions.Contains(g.Function)) allowedTrees.Add(g);259 slots[slot] = allowedTrees;260 }261 // fill the slots in the order of degrees of freedom262 int[] slotSequence = Enumerable.Range(0, slots.Count()).OrderBy(slot => slots[slot].Count()).ToArray();263 264 // tmp arry to store the tree for each sub-tree slot of the parent265 IFunctionTree[] selectedFunctionTrees = new IFunctionTree[nSlots];266 267 // fill the sub-tree slots of the parent starting with the slots that can take potentially both functions (f and g)268 for(int i = 0; i < slotSequence.Length; i++) {269 int slot = slotSequence[i];270 List<IFunctionTree> allowedTrees = slots[slot];271 // when neither f nor g fit into the slot => create a new random tree272 if(allowedTrees.Count() == 0) {273 var allowedFunctions = gardener.GetAllowedSubFunctions(parent.Function, slot);274 selectedFunctionTrees[slot] = gardener.CreateRandomTree(allowedFunctions, 1, 1);275 newBranches.AddRange(gardener.GetAllSubTrees(selectedFunctionTrees[slot]));276 } else {277 // select randomly which tree to insert into this slot278 IFunctionTree selectedTree = allowedTrees[random.Next(allowedTrees.Count())];279 selectedFunctionTrees[slot] = selectedTree;280 // remove the tree that we used in this slot from following function-sets281 for(int j = i + 1; j < slotSequence.Length; j++) {282 int otherSlot = slotSequence[j];283 slots[otherSlot].Remove(selectedTree);284 }285 }286 }287 // actually append the sub-trees to the parent tree288 for(int i = 0; i < selectedFunctionTrees.Length; i++) {289 parent.InsertSubTree(i, selectedFunctionTrees[i]);290 }291 292 return parent;293 }294 220 } 295 221 } -
trunk/sources/HeuristicLab.GP/Recombination/SizeFairCrossOver.cs
r656 r814 64 64 TreeGardener gardener = new TreeGardener(random, opLibrary); 65 65 66 if ((scope.SubScopes.Count % 2) != 0)66 if ((scope.SubScopes.Count % 2) != 0) 67 67 throw new InvalidOperationException("Number of parents is not even"); 68 68 69 CompositeOperation initOperations = new CompositeOperation();70 71 69 int children = scope.SubScopes.Count / 2; 72 for (int i = 0; i < children; i++) {70 for (int i = 0; i < children; i++) { 73 71 IScope parent1 = scope.SubScopes[0]; 74 72 scope.RemoveSubScope(parent1); … … 76 74 scope.RemoveSubScope(parent2); 77 75 IScope child = new Scope(i.ToString()); 78 IOperation childInitOperation = Cross(gardener, maxTreeSize, maxTreeHeight, scope, random, parent1, parent2, child); 79 initOperations.AddOperation(childInitOperation); 76 Cross(gardener, maxTreeSize, maxTreeHeight, scope, random, parent1, parent2, child); 80 77 scope.AddSubScope(child); 81 78 } 82 79 83 return initOperations;80 return null; 84 81 } 85 82 86 private IOperationCross(TreeGardener gardener, int maxTreeSize, int maxTreeHeight,83 private void Cross(TreeGardener gardener, int maxTreeSize, int maxTreeHeight, 87 84 IScope scope, MersenneTwister random, IScope parent1, IScope parent2, IScope child) { 88 List<IFunctionTree> newBranches;89 85 IFunctionTree newTree = Cross(gardener, parent1, parent2, 90 random, maxTreeSize, maxTreeHeight , out newBranches);86 random, maxTreeSize, maxTreeHeight); 91 87 88 child.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("FunctionTree"), newTree)); 89 child.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("TreeSize"), new IntData(newTree.Size))); 90 child.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("TreeHeight"), new IntData(newTree.Height))); 92 91 93 int newTreeSize = newTree.Size; 94 int newTreeHeight = newTree.Height; 95 child.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("FunctionTree"), newTree)); 96 child.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("TreeSize"), new IntData(newTreeSize))); 97 child.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("TreeHeight"), new IntData(newTreeHeight))); 98 99 // check if the new tree is valid and if the height of is still in the allowed bounds (we are not so strict for the max-size) 100 Debug.Assert(gardener.IsValidTree(newTree) && newTreeHeight <= maxTreeHeight && newTreeSize <= maxTreeSize); 101 return gardener.CreateInitializationOperation(newBranches, child); 92 // check if the new tree is valid and the height and size are still in the allowed bounds 93 Debug.Assert(gardener.IsValidTree(newTree) && newTree.Height <= maxTreeHeight && newTree.Size <= maxTreeSize); 102 94 } 103 95 104 96 105 private IFunctionTree Cross(TreeGardener gardener, IScope f, IScope g, MersenneTwister random, int maxTreeSize, int maxTreeHeight , out List<IFunctionTree> newBranches) {97 private IFunctionTree Cross(TreeGardener gardener, IScope f, IScope g, MersenneTwister random, int maxTreeSize, int maxTreeHeight) { 106 98 IFunctionTree tree0 = f.GetVariableValue<IFunctionTree>("FunctionTree", false); 107 99 int tree0Height = f.GetVariableValue<IntData>("TreeHeight", false).Data; … … 112 104 int tree1Size = g.GetVariableValue<IntData>("TreeSize", false).Data; 113 105 114 if(tree0Size == 1 && tree1Size == 1) { 115 return CombineTerminals(gardener, tree0, tree1, random, maxTreeHeight, out newBranches); 106 // we are going to insert tree1 into tree0 at a random place so we have to make sure that tree0 is not a terminal 107 // in case both trees are higher than 1 we swap the trees with probability 50% 108 if (tree0Height == 1 || (tree1Height > 1 && random.Next(2) == 0)) { 109 IFunctionTree tmp = tree0; tree0 = tree1; tree1 = tmp; 110 int tmpHeight = tree0Height; tree0Height = tree1Height; tree1Height = tmpHeight; 111 int tmpSize = tree0Size; tree0Size = tree1Size; tree1Size = tmpSize; 112 } 113 114 // select a random suboperator of the 'receiving' tree 115 IFunctionTree crossoverPoint = gardener.GetRandomParentNode(tree0); 116 int removedBranchIndex; 117 IFunctionTree removedBranch; 118 IList<IFunction> allowedFunctions; 119 if (crossoverPoint == null) { 120 removedBranchIndex = 0; 121 removedBranch = tree0; 122 allowedFunctions = gardener.GetAllowedSubFunctions(null, 0); 116 123 } else { 117 newBranches = new List<IFunctionTree>(); 124 removedBranchIndex = random.Next(crossoverPoint.SubTrees.Count); 125 removedBranch = crossoverPoint.SubTrees[removedBranchIndex]; 126 allowedFunctions = gardener.GetAllowedSubFunctions(crossoverPoint.Function, removedBranchIndex); 127 } 128 int removedBranchSize = removedBranch.Size; 129 int maxBranchSize = maxTreeSize - (tree0.Size - removedBranchSize); 130 int maxBranchHeight = maxTreeHeight - gardener.GetBranchLevel(tree0, removedBranch) + 1; 131 IFunctionTree insertedBranch = GetReplacementBranch(random, gardener, allowedFunctions, tree1, removedBranchSize, maxBranchSize, maxBranchHeight); 118 132 119 // 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 // in case both trees are higher than 1 we swap the trees with probability 50% 121 if(tree0Height == 1 || (tree1Height > 1 && random.Next(2) == 0)) { 122 IFunctionTree tmp = tree0; tree0 = tree1; tree1 = tmp; 123 int tmpHeight = tree0Height; tree0Height = tree1Height; tree1Height = tmpHeight; 124 int tmpSize = tree0Size; tree0Size = tree1Size; tree1Size = tmpSize; 133 int tries = 0; 134 while (insertedBranch == null) { 135 if (tries++ > MAX_RECOMBINATION_TRIES) { 136 if (random.Next() > 0.5) return tree1; 137 else return tree0; 125 138 } 126 139 127 // select a random suboperator of the 'receiving' tree 128 IFunctionTree crossoverPoint = gardener.GetRandomParentNode(tree0); 129 int removedBranchIndex; 130 IFunctionTree removedBranch; 131 IList<IFunction> allowedFunctions; 132 if(crossoverPoint == null) { 140 // retry with a different crossoverPoint 141 crossoverPoint = gardener.GetRandomParentNode(tree0); 142 if (crossoverPoint == null) { 133 143 removedBranchIndex = 0; 134 144 removedBranch = tree0; … … 139 149 allowedFunctions = gardener.GetAllowedSubFunctions(crossoverPoint.Function, removedBranchIndex); 140 150 } 141 int removedBranchSize = removedBranch.Size; 142 int maxBranchSize = maxTreeSize - (tree0.Size - removedBranchSize); 143 int maxBranchHeight = maxTreeHeight - gardener.GetBranchLevel(tree0, removedBranch); 144 IFunctionTree insertedBranch = GetReplacementBranch(random, gardener, allowedFunctions, tree1, removedBranchSize, maxBranchSize, maxBranchHeight); 145 146 int tries = 0; 147 while(insertedBranch == null) { 148 if(tries++ > MAX_RECOMBINATION_TRIES) { 149 if(random.Next() > 0.5) return tree1; 150 else return tree0; 151 } 152 153 // retry with a different crossoverPoint 154 crossoverPoint = gardener.GetRandomParentNode(tree0); 155 if(crossoverPoint == null) { 156 removedBranchIndex = 0; 157 removedBranch = tree0; 158 allowedFunctions = gardener.GetAllowedSubFunctions(null, 0); 159 } else { 160 removedBranchIndex = random.Next(crossoverPoint.SubTrees.Count); 161 removedBranch = crossoverPoint.SubTrees[removedBranchIndex]; 162 allowedFunctions = gardener.GetAllowedSubFunctions(crossoverPoint.Function, removedBranchIndex); 163 } 164 removedBranchSize = removedBranch.Size; 165 maxBranchSize = maxTreeSize - (tree0.Size - removedBranchSize); 166 maxBranchHeight = maxTreeHeight - gardener.GetBranchLevel(tree0, removedBranch) + 1; 167 insertedBranch = GetReplacementBranch(random, gardener, allowedFunctions, tree1, removedBranchSize, maxBranchSize, maxBranchHeight); 168 } 169 if(crossoverPoint != null) { 170 // replace the branch below the crossoverpoint with the selected branch from root1 171 crossoverPoint.RemoveSubTree(removedBranchIndex); 172 crossoverPoint.InsertSubTree(removedBranchIndex, insertedBranch); 173 return tree0; 174 } else { 175 return insertedBranch; 176 } 151 removedBranchSize = removedBranch.Size; 152 maxBranchSize = maxTreeSize - (tree0.Size - removedBranchSize); 153 maxBranchHeight = maxTreeHeight - gardener.GetBranchLevel(tree0, removedBranch) + 1; 154 insertedBranch = GetReplacementBranch(random, gardener, allowedFunctions, tree1, removedBranchSize, maxBranchSize, maxBranchHeight); 155 } 156 if (crossoverPoint != null) { 157 // replace the branch below the crossoverpoint with the selected branch from root1 158 crossoverPoint.RemoveSubTree(removedBranchIndex); 159 crossoverPoint.InsertSubTree(removedBranchIndex, insertedBranch); 160 return tree0; 161 } else { 162 return insertedBranch; 177 163 } 178 164 } … … 186 172 var equalLengthBranches = branches.Where(t => t.Size == removedBranchSize); 187 173 188 if (shorterBranches.Count() == 0 || longerBranches.Count() == 0) {189 if (equalLengthBranches.Count() == 0) {174 if (shorterBranches.Count() == 0 || longerBranches.Count() == 0) { 175 if (equalLengthBranches.Count() == 0) { 190 176 return null; 191 177 } else { … … 199 185 200 186 double r = random.NextDouble(); 201 if (r < pLonger) {187 if (r < pLonger) { 202 188 return longerBranches.ElementAt(random.Next(longerBranches.Count())).Tree; 203 } else if (r < pLonger + pShorter) {189 } else if (r < pLonger + pShorter) { 204 190 return shorterBranches.ElementAt(random.Next(shorterBranches.Count())).Tree; 205 191 } else { … … 208 194 } 209 195 } 210 211 212 // take f and g and create a tree that has f and g as sub-trees213 // example214 // O215 // /|\216 // g 2 f217 //218 private IFunctionTree CombineTerminals(TreeGardener gardener, IFunctionTree f, IFunctionTree g, MersenneTwister random, int maxTreeHeight, out List<IFunctionTree> newBranches) {219 newBranches = new List<IFunctionTree>();220 // determine the set of possible parent functions221 ICollection<IFunction> possibleParents = gardener.GetPossibleParents(new List<IFunction>() { f.Function, g.Function });222 if(possibleParents.Count == 0) throw new InvalidProgramException();223 // and select a random one224 IFunctionTree parent = possibleParents.ElementAt(random.Next(possibleParents.Count())).GetTreeNode();225 226 int nSlots = Math.Max(2, parent.Function.MinArity);227 // determine which slot can take which sub-trees228 List<IFunctionTree>[] slots = new List<IFunctionTree>[nSlots];229 for(int slot = 0; slot < nSlots; slot++) {230 ICollection<IFunction> allowedSubFunctions = gardener.GetAllowedSubFunctions(parent.Function, slot);231 List<IFunctionTree> allowedTrees = new List<IFunctionTree>();232 if(allowedSubFunctions.Contains(f.Function)) allowedTrees.Add(f);233 if(allowedSubFunctions.Contains(g.Function)) allowedTrees.Add(g);234 slots[slot] = allowedTrees;235 }236 // fill the slots in the order of degrees of freedom237 int[] slotSequence = Enumerable.Range(0, slots.Count()).OrderBy(slot => slots[slot].Count()).ToArray();238 239 // tmp arry to store the tree for each sub-tree slot of the parent240 IFunctionTree[] selectedFunctionTrees = new IFunctionTree[nSlots];241 242 // fill the sub-tree slots of the parent starting with the slots that can take potentially both functions (f and g)243 for(int i = 0; i < slotSequence.Length; i++) {244 int slot = slotSequence[i];245 List<IFunctionTree> allowedTrees = slots[slot];246 // when neither f nor g fit into the slot => create a new random tree247 if(allowedTrees.Count() == 0) {248 var allowedFunctions = gardener.GetAllowedSubFunctions(parent.Function, slot);249 selectedFunctionTrees[slot] = gardener.CreateRandomTree(allowedFunctions, 1, 1);250 newBranches.AddRange(gardener.GetAllSubTrees(selectedFunctionTrees[slot]));251 } else {252 // select randomly which tree to insert into this slot253 IFunctionTree selectedTree = allowedTrees[random.Next(allowedTrees.Count())];254 selectedFunctionTrees[slot] = selectedTree;255 // remove the tree that we used in this slot from following function-sets256 for(int j = i + 1; j < slotSequence.Length; j++) {257 int otherSlot = slotSequence[j];258 slots[otherSlot].Remove(selectedTree);259 }260 }261 }262 // actually append the sub-trees to the parent tree263 for(int i = 0; i < selectedFunctionTrees.Length; i++) {264 parent.InsertSubTree(i, selectedFunctionTrees[i]);265 }266 267 return parent;268 }269 196 } 270 197 }
Note: See TracChangeset
for help on using the changeset viewer.