/// <summary> /// Returns true if inner1 can feasibly be swapped into inner2's position. /// </summary> private bool VerifyPoints(GPInitializer initializer, GPNode inner1, GPNode inner2) { // first check to see if inner1 is swap-compatible with inner2 // on a type basis if (!inner1.SwapCompatibleWith(initializer, inner2)) { return(false); } // next check to see if inner1 can fit in inner2's spot if (inner1.Depth + inner2.AtDepth() > MaxDepth) { return(false); } // checks done! return(true); }
/// <summary> /// Returns true if inner1 can feasibly be swapped into inner2's position. /// </summary> public bool VerifyPoints(GPInitializer initializer, GPNode inner1, GPNode inner2) { // first check to see if inner1 is swap-compatible with inner2 // on a type basis if (!inner1.SwapCompatibleWith(initializer, inner2)) { return(false); } // next check to see if inner1 can fit in inner2's spot if (inner1.Depth + inner2.AtDepth() > MaxDepth) { return(false); } // check for size // NOTE: this is done twice, which is more costly than it should be. But // on the other hand it allows us to toss a child without testing both times // and it's simpler to have it all here in the verifyPoints code. if (MaxSize != NO_SIZE_LIMIT) { // first easy check var inner1Size = inner1.NumNodes(GPNode.NODESEARCH_ALL); var inner2Size = inner2.NumNodes(GPNode.NODESEARCH_ALL); if (inner1Size > inner2Size) // need to test further { // let's keep on going for the more complex test var root2 = ((GPTree)(inner2.RootParent())).Child; var root2Size = root2.NumNodes(GPNode.NODESEARCH_ALL); if (root2Size - inner2Size + inner1Size > MaxSize) // take root2, remove inner2 and swap in inner1. Is it still small enough? { return(false); } } } // checks done! return(true); }
/** * This method finds a node using the logic given in the langdon paper. * @param nodeToSubtrees For Tree of Parent2 all precomputed stats about depth,subtrees etc * @param sizeToNodes Quick lookup for LinkedList of size to Nodes * @param parent1SelectedNode Node selected in parent1 * @param Tree2 Tree of parent2 * @param state Evolution State passed for getting access to Random Object of MersenneTwiser * @param thread thread number */ protected GPNode FindFairSizeNode(ArrayList nodeToSubtrees, Hashtable sizeToNodes, GPNode parent1SelectedNode, GPTree tree2, IEvolutionState state, int thread) { GPNode selectedNode = null; // get the size of subtrees of parent1 int parent1SubTrees = parent1SelectedNode.NumNodes(GPNode.NODESEARCH_NONTERMINALS); // the maximum length in mate we are looking for int maxmatesublen = parent1SubTrees == 0 ? 0 : 2 * parent1SubTrees + 1; // lets see if for all lengths we have trees corresponding bool[] mateSizeAvailable = new bool[maxmatesublen + 1]; // initialize the array to false for (int i = 0; i < maxmatesublen; i++) { mateSizeAvailable[i] = false; } // check for ones we have for (int i = 0; i < nodeToSubtrees.Count; i++) { NodeInfo nodeInfo = (NodeInfo)nodeToSubtrees[i]; // get the length of trees int subtree = nodeInfo.NumberOfSubTreesBeneath; if (subtree <= maxmatesublen) { mateSizeAvailable[subtree] = true; } } // choose matesublen so mean size change=0 if possible int countOfPositives = 0; int countOfNegatives = 0; int sumOfPositives = 0; int sumOfNegatives = 0; int l; for (l = 1; l < parent1SubTrees; l++) { if (mateSizeAvailable[l]) { countOfNegatives++; sumOfNegatives += parent1SubTrees - l; } } for (l = parent1SubTrees + 1; l <= maxmatesublen; l++) { if (mateSizeAvailable[l]) { countOfPositives++; sumOfPositives += l - parent1SubTrees; } } // if they are missing use the same int mateSublengthSelected = 0; if (sumOfPositives == 0 || sumOfNegatives == 0) { //if so then check if mate has the length and use that if (mateSizeAvailable[parent1SubTrees]) { mateSublengthSelected = parent1SubTrees; } //else we go with zero } else { // probability of same is dependent on do we find same sub trees // else 0.0 double pzero = (mateSizeAvailable[parent1SubTrees]) ? 1.0 / parent1SubTrees : 0.0; // positive probability double ppositive = (1.0 - pzero) / (countOfPositives + ((double)(countOfNegatives * sumOfPositives) / (sumOfNegatives))); // negative probability double pnegative = (1.0 - pzero) / (countOfNegatives + ((double)(countOfPositives * sumOfNegatives) / (sumOfPositives))); // total probability, just for making sure math is right ;-) double total = countOfNegatives * pnegative + pzero + countOfPositives * ppositive; // putting an assert for floating point calculations, similar to what langdon does // assert(total<1.01&&total>.99); // now create a Roulette Wheel RouletteWheelSelector wheel = new RouletteWheelSelector(maxmatesublen); // add probabilities to the wheel // all below the length of parent node get pnegative // all above get ppositive and one on node gets pzero for (l = 1; l < parent1SubTrees; l++) { if (mateSizeAvailable[l]) { wheel.Add(pnegative, l); } } if (mateSizeAvailable[parent1SubTrees]) { wheel.Add(pzero, parent1SubTrees); } for (l = parent1SubTrees + 1; l <= maxmatesublen; l++) { if (mateSizeAvailable[l]) { wheel.Add(ppositive, l); } } // spin the wheel mateSublengthSelected = wheel.Roulette(state, thread); } // now we have length chosen, but there can be many nodes with that // LinkedList <NodeInfo> listOfNodes = (LinkedList <NodeInfo>)sizeToNodes[mateSublengthSelected]; if (listOfNodes == null) { state.Output.Fatal("In SizeFairCrossoverPipeline, nodes for tree length " + mateSublengthSelected + " is null, indicates some serious error"); } // in size fair we choose the elements at random for given length int chosenNode = 0; // if using fair size get random from the list if (!Homologous) { chosenNode = state.Random[thread].NextInt(listOfNodes.Count); } // if Homologous else { if (listOfNodes.Count > 1) { GPInitializer initializer = ((GPInitializer)state.Initializer); int currentMinDistance = int.MaxValue; for (int i = 0; i < listOfNodes.Count; i++) { // get the GP node GPNode selectedMateNode = listOfNodes.ElementAt(i).Node; // now lets traverse selected and parent 1 to see divergence GPNode currentMateNode = selectedMateNode; GPNode currentParent1Node = parent1SelectedNode; // found a match? bool foundAMatchInAncestor = false; int distance = 0; while (currentMateNode.Parent != null && currentMateNode.Parent is GPNode && currentParent1Node.Parent != null && currentParent1Node.Parent is GPNode && !foundAMatchInAncestor) { GPNode parent1 = (GPNode)currentParent1Node.Parent; GPNode parent2 = (GPNode)currentMateNode.Parent; // if there is match between compatibility of Parents break if (parent1.SwapCompatibleWith(initializer, parent2)) { foundAMatchInAncestor = true; break; } else { // need to go one level above of both currentMateNode = parent2; currentParent1Node = parent1; //increment the distance distance = distance + 1; } } // find the one with least distance if (distance < currentMinDistance) { currentMinDistance = distance; chosenNode = i; } } } // else take the first node, no choice } NodeInfo nodeInfoSelected = listOfNodes.ElementAt(chosenNode); selectedNode = nodeInfoSelected.Node; return(selectedNode); }