public void BasicTest() { RandomGenerator.GetInstance().RandomSource = new MockRandomSource(new List<int>(), new List<double> {0.350, 0.623, 0.311, 0.511, 0.999}); ListGenotype<FloatGene> genotype1 = new ListGenotype<FloatGene>(10000); ListGenotype<FloatGene> genotype2 = new ListGenotype<FloatGene>(20000); ListGenotype<FloatGene> genotype3 = new ListGenotype<FloatGene>(30000); List<Individual<ListGenotype<FloatGene>, double>> individuals = new List<Individual<ListGenotype<FloatGene>, double>> { new Individual<ListGenotype<FloatGene>, double>(genotype1, 300), new Individual<ListGenotype<FloatGene>, double>(genotype2, 200), new Individual<ListGenotype<FloatGene>, double>(genotype3, 500) }; RouletteWheelSelector<ListGenotype<FloatGene>> selector = new RouletteWheelSelector<ListGenotype<FloatGene>>(5); IList<Individual<ListGenotype<FloatGene>, double>> selection = selector.Apply(individuals); Assert.AreEqual(5, selection.Count); Assert.AreSame(individuals[2], selection[0]); Assert.AreSame(individuals[0], selection[1]); Assert.AreSame(individuals[2], selection[2]); Assert.AreSame(individuals[0], selection[3]); Assert.AreSame(individuals[1], selection[4]); Assert.AreNotSame(individuals[0], selection[0]); Assert.AreNotSame(individuals[1], selection[0]); }
/** * 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); }