/// <summary> /// The crossover function, takes two parent programs, and generates two sons /// From the two parents. /// </summary> /// <param name="progParentOne">Parent program one</param> /// <param name="progParentTwo">Parent program two</param> /// <param name="progSonOne">Son program one</param> /// <param name="progSonTwo">Son program two</param> protected override void Crossover(BaseProgram baseProgParentOne, BaseProgram baseProgParentTwo, out BaseProgram baseProgSonOne, out BaseProgram baseProgSonTwo) { TreeProgram progParentOne = (TreeProgram)baseProgParentOne; TreeProgram progParentTwo = (TreeProgram)baseProgParentTwo; TreeProgram progSonOne; TreeProgram progSonTwo; // Get the global random ... ImprovedRandom rndRandom = GlobalRandom.m_rndRandom; progSonOne = (TreeProgram)progParentOne.Clone(); progSonTwo = (TreeProgram)progParentTwo.Clone(); // Generate new sons more and more, until the new sons tree limit's are // Good enough and stand the tree limits. Or just do this for the first time // That sons are being generated. for (int nRootNum = 0; nRootNum < progSonOne.m_arrRoots.Length; nRootNum++) { bool bGeneratedNewSons = false; while (((progSonOne.m_arrRoots[nRootNum].Depth > this.m_nMaxOverallTreeDepth) || (progSonTwo.m_arrRoots[nRootNum].Depth > this.m_nMaxOverallTreeDepth)) || !bGeneratedNewSons) { // Clone both parent roots progSonOne.m_arrRoots[nRootNum] = (Node)progParentOne.m_arrRoots[nRootNum].Clone(); progSonTwo.m_arrRoots[nRootNum] = (Node)progParentTwo.m_arrRoots[nRootNum].Clone(); // Random two nodes as a crossover points in the two sons (which are // Now supposed to be a cloned version of the parents) int nSelectNodeInParentOne = rndRandom.Next( NodeHelper.CountNodes(progSonOne.m_arrRoots[nRootNum])); int nSelectNodeInParentTwo = rndRandom.Next( NodeHelper.CountNodes(progSonTwo.m_arrRoots[nRootNum])); NodeHelper.NodeResult ndNodeToExchangeOne = NodeHelper.FindNode( progSonOne.m_arrRoots[nRootNum], nSelectNodeInParentOne); NodeHelper.NodeResult ndNodeToExchangeTwo = NodeHelper.FindNode( progSonTwo.m_arrRoots[nRootNum], nSelectNodeInParentTwo); // Exchange the crossover branches between the two sons, when it is done, // The new sons are ready to be called "new sons" and not just a clone. NodeHelper.ExchangeNodes( ndNodeToExchangeOne.ndNode, ndNodeToExchangeOne.ndNodeParent, ref progSonOne.m_arrRoots[nRootNum], ndNodeToExchangeTwo.ndNode, ndNodeToExchangeTwo.ndNodeParent, ref progSonTwo.m_arrRoots[nRootNum]); bGeneratedNewSons = true; } } baseProgSonOne = progSonOne; baseProgSonTwo = progSonTwo; }
public BaseProgram GetMinFitnessProgramForIsland(int nIslandIndex) { // Sample the first program as a starting fitness BaseProgram progMinFitness = this.m_engEngine.Population[nIslandIndex][0]; float fMinFitness = progMinFitness.m_fFitness; // Go through all the programs and get the program with the // Minimal fitness foreach (BaseProgram progProgram in this.m_engEngine.Population[nIslandIndex]) { // If the current program has least fitness than all the rest so far // Then it's the most minimal fitness program. if (fMinFitness > progProgram.m_fFitness) { fMinFitness = progProgram.m_fFitness; progMinFitness = progProgram; } } return(progMinFitness); }
/// <summary> /// Creates a random node in the tree. The function is recursive, and /// Creates a random node. Which means, a random function or variable will /// Be selected . If a function is selected, then another nodes for the /// Function will be created. If a variable will be selected, then /// The tree will stop evolving at this branch. /// </summary> /// <param name="nCurrentDepth">The current tree depth</param> /// <returns>A random tree node</returns> private Node CreateRandomNode(int nCurrentDepth, BaseProgram baseProgOwner, ArrayList arrRandomableTypes) { TreeProgram progOwner = (TreeProgram)baseProgOwner; // The chosen index in all the types array, to choose some random thing, // Either variable of function, to insert as a node. int nChosenTypeIndex = GlobalRandom.m_rndRandom.Next(arrRandomableTypes.Count); object objChosenType = arrRandomableTypes[nChosenTypeIndex]; // If we are above the tree limit, choose randomly until we select a variable. bool fFoundLeaf = false; while ((nCurrentDepth > this.m_nMaxInitialTreeDepth) && (fFoundLeaf == false)) { nChosenTypeIndex = GlobalRandom.m_rndRandom.Next(arrRandomableTypes.Count); objChosenType = arrRandomableTypes[nChosenTypeIndex]; if (objChosenType is FunctionType) { if (((FunctionType)objChosenType).NumberOfArguments == 0) { fFoundLeaf = true; } } else // The type is variable { fFoundLeaf = true; } } // If we are below the initial tree limit, choose randomly until we select // A function. bool fFoundBranch = false; while ((nCurrentDepth < this.m_nMinInitialTreeDepth) && (fFoundBranch == false)) { nChosenTypeIndex = GlobalRandom.m_rndRandom.Next(arrRandomableTypes.Count); objChosenType = arrRandomableTypes[nChosenTypeIndex]; if (objChosenType is FunctionType) { if (((FunctionType)objChosenType).NumberOfArguments > 0) { fFoundBranch = true; } } } // If the object chosen is a variable, create a new VariableNode if (objChosenType is Variable) { Variable vlVariable = (Variable)objChosenType; return(new VariableNode(vlVariable, progOwner)); } // If the object chosen is a value, create a new ValueNode else if (objChosenType is Value) { Value vlValue = (Value)objChosenType; return(new ValueNode(vlValue)); } // If the object chosen is a RandomMacro, create a new ValueNode which // Will be randomized. else if (objChosenType is RandomMacro) { return(new ValueNode(((RandomMacro)objChosenType).ReturnValue())); } // If the object chosen is a function, then create a function and also // Create trees for that function. else if (objChosenType is Function) { FunctionNode fncNewNode = new FunctionNode(); Function funcChosenFunction = (Function)objChosenType; fncNewNode.m_funcFunction = funcChosenFunction; fncNewNode.m_arrSons = new Node[funcChosenFunction.NumberOfArguments]; for (int nSonIndex = 0; nSonIndex < fncNewNode.m_arrSons.Length; nSonIndex++) { fncNewNode.m_arrSons[nSonIndex] = CreateRandomNode(nCurrentDepth + 1, progOwner, arrRandomableTypes); } return(fncNewNode); } // We will never normally reach here. return(null); }
protected override void RunProgram(BaseProgram progProgram) { this.EvalFitnessForProgramEvent((TreeProgram)progProgram, this); }