public override void Run(Configuration config) { //Setup log and solution this.log = new RandomLogSpecification(config.RandomSeed, config.MemoryLength, config.MaxTreeDepth); this.solution = new SolutionSpecification(); this.config = config; Dilemma best = null; //For the number of runs for(int run = 0; run < config.NumberOfRuns; run++) { //Initialize best fitness, so the first will always be a best fitness found double bestfitness = -1.0; //As long as we are under the number of fitness evals while(fitnessevals < config.NumberOfEvals) { //Make a new dilemma List<Dilemma> sequence = new List<Dilemma>(); //Initialize the memory InitializeUniformRandomMemory(config.MemoryLength); //Create a new tree Dilemma newdilemma = new Dilemma(); newdilemma.Tree = GenerateNewUniformRandomTree(config.MaxTreeDepth, 0); //Zero out total fitness for an average double totalfitness = 0.0; //Play IPD for(int i = 0; i < config.SequenceLength; i++) { //Add to total fitness totalfitness += (double)SingleFitnessCalculation(newdilemma.Tree.GetValue(memory), memory.ToArray()[memory.Count - 1][0]); //Place it in memory memory.Enqueue(new bool[2] { newdilemma.Tree.GetValue(memory), memory.ToArray()[memory.Count - 1][0] }); //If the memory is bigger than is allowed, pop the shiz. if(memory.Count > config.MemoryLength) { memory.Dequeue(); } } //Get the average totalfitness /= (double)config.SequenceLength; //Increment fitness evals because this is technically a fitness eval fitnessevals++; //Check for best and make a log entry if it is a new best. if(best == null || bestfitness < totalfitness) { best = newdilemma; bestfitness = totalfitness; ((RandomLogSpecification)log).AddEvaluation(fitnessevals, bestfitness); Console.WriteLine(fitnessevals + "\t" + bestfitness); } } } solution.PreOrderListing = best.Tree.PreOrderStringRealization; }
public Dilemma Clone() { Dilemma newdil = new Dilemma(); newdil.tree = this.tree.Clone(); newdil.fitness = this.fitness; newdil.memory = new Queue<bool[]>(); foreach(bool[] b in this.memory) newdil.memory.Enqueue(new bool[] { b[0], b[1] }); return newdil; }
//Randomly choose subtrees, and recombine. //This returns 2 new dilemma trees. public Dilemma[] SubTreeRecombination(Dilemma dilemmaA, Dilemma dilemmaB, Random randomgenerator, out int indexa, out int indexb) { Dilemma a1 = dilemmaA.Clone(); Dilemma b1 = dilemmaB.Clone(); Dilemma a2 = dilemmaA.Clone(); Dilemma b2 = dilemmaB.Clone(); int nodeaindex = randomgenerator.Next(0, a1.Tree.Size); int nodebindex = randomgenerator.Next(0, b1.Tree.Size); indexa = nodeaindex; indexb = nodebindex; if (nodeaindex == 0) a1 = b1; else { a1.Tree.ReplaceTree(nodeaindex, b1.Tree.RetrieveTree(nodebindex)); } if(nodebindex == 0) b2 = a2; else { b2.Tree.ReplaceTree(nodebindex, a2.Tree.RetrieveTree(nodeaindex)); } return new Dilemma[2] {a1.Clone(), b2.Clone()}; }
//10% chance of mutating a subtree. public Dilemma SubTreeMutation(Dilemma dilemma, Random randomgenerator, int maxtreedepth, out int mutateposition) { mutateposition = 0; int randomnumber; Dilemma newd = dilemma.Clone(); for(int i = 0; i < newd.Tree.Size; i++) { randomnumber = randomgenerator.Next(0, 10); OperatorTree tree; if(randomnumber == 5) { tree = newd.Tree.RetrieveTree(i); if (i == 0) newd.Tree = GenerateNewUniformRandomTreeGrow(maxtreedepth, 1, dilemma.Memory, randomgenerator, treepossibilities); else newd.Tree.ReplaceTree(i, GenerateNewUniformRandomTreeGrow(maxtreedepth, tree.Depth, dilemma.Memory, randomgenerator, treepossibilities)); mutateposition = i; break; } } return newd.Clone(); }
//Initializes Population and their memories. public List<Dilemma> RampedHalfAndHalfInitialization(int populationsize, int memorylength) { List<Dilemma> population = new List<Dilemma>(); for(int i = 0; i < populationsize; i++) { int fullorgrow = RandomGenerator.Next(0, 2); Dilemma newdilemma = new Dilemma(); newdilemma.GenerateUniformRandomMemory(memorylength, RandomGenerator); //Full Method if(fullorgrow == 0) { newdilemma.Tree = GenerateNewUniformRandomTreeFull(config.MaxTreeDepth, 1, newdilemma.Memory, RandomGenerator, treepossibilities); population.Add(newdilemma); } //Grow Method else { newdilemma.Tree = GenerateNewUniformRandomTreeGrow(config.MaxTreeDepth, 1, newdilemma.Memory, RandomGenerator, treepossibilities); population.Add(newdilemma); } } return population; }
//Play the IPD, evaluating fitness for sequencelength - 2 * memorylength //Evaluate Tit For Tat. public Dilemma PlayIPDTitForTat(Dilemma dil, int sequencelength, double parsimonypressure, int maxtreedepth, int memorylength) { Dilemma dilemma = dil.Clone(); dilemma.Fitness = 0.0; dilemma.GenerateUniformRandomMemory(memorylength, RandomGenerator); for(int i = 0; i < sequencelength; i++) { if (i >= 2 * memorylength) { //Add to total fitness dilemma.Fitness += (double)SingleFitnessCalculation(dilemma.Tree.GetValue(dilemma.Memory), dilemma.Memory.ToArray()[dilemma.Memory.Count - 1][0]); } //Place it in memory dilemma.Memory.Enqueue(new bool[2] { dilemma.Tree.GetValue(dilemma.Memory), dilemma.Memory.ToArray()[dilemma.Memory.Count - 1][0] }); //If the memory is bigger than is allowed, pop the shiz. if(dilemma.Memory.Count > memorylength) { dilemma.Memory.Dequeue(); } } //ESSENTIALLY EVALUATING FITNESS dilemma.Fitness /= (sequencelength - 2 * memorylength); //Parsimony pressure: //Fitness = Fitness - Fitness * Parsimony Pressure * (Tree Size / Max Tree Size) //Parsimony Pressure is a double between 0.0 and 1.0. //Max tree size is 2^(Max Tree Depth) + 1 dilemma.Fitness -= (dilemma.Fitness * (parsimonypressure * (double)dilemma.Tree.Size / (double)((2<<maxtreedepth) + 1))); return dilemma; }
//Play the IPD, evaluating fitness for sequencelength - 2 * memorylength public void PlayIPD(ref Dilemma dilemma1, ref Dilemma dilemma2, int sequencelength, double parsimonypressure, int maxtreedepth, int memorylength) { dilemma1.GenerateUniformRandomMemory(memorylength, RandomGenerator); dilemma2.GenerateUniformRandomMemory(memorylength, RandomGenerator); double fitness1 = 0.0; double fitness2 = 0.0; for(int i = 0; i < sequencelength; i++) { if (i >= 2 * memorylength) { //Add to total fitness fitness1 += (double)SingleFitnessCalculation(dilemma1.Tree.GetValue(dilemma1.Memory), dilemma2.Tree.GetValue(dilemma2.Memory)); fitness2 += (double)SingleFitnessCalculation(dilemma2.Tree.GetValue(dilemma2.Memory), dilemma1.Tree.GetValue(dilemma1.Memory)); } //Place it in memory dilemma1.Memory.Enqueue(new bool[2] { dilemma1.Tree.GetValue(dilemma1.Memory), dilemma2.Tree.GetValue(dilemma2.Memory) }); dilemma2.Memory.Enqueue(new bool[2] { dilemma2.Tree.GetValue(dilemma2.Memory), dilemma1.Tree.GetValue(dilemma1.Memory) }); //If the memory is bigger than is allowed, pop the shiz. if(dilemma1.Memory.Count > memorylength) { dilemma1.Memory.Dequeue(); } if(dilemma2.Memory.Count > memorylength) { dilemma2.Memory.Dequeue(); } } fitness1 /= ((double)sequencelength - 2.0 * (double)memorylength); fitness2 /= ((double)sequencelength - 2.0 * (double)memorylength); //Parsimony pressure: //Fitness = Fitness - Fitness * Parsimony Pressure * (Tree Size / Max Tree Size) //Parsimony Pressure is a double between 0.0 and 1.0. //Max tree size is 2^(Max Tree Depth) + 1 fitness1 -= (fitness1 * (parsimonypressure * (double)dilemma1.Tree.Size / (double)((2<<maxtreedepth) + 1))); fitness2 -= (fitness2 * (parsimonypressure * (double)dilemma2.Tree.Size / (double)((2<<maxtreedepth) + 1))); dilemma1.Fitness += fitness1; dilemma2.Fitness += fitness2; fitnessevals++; }
//Randomly choose subtrees, and recombine. public Dilemma SubTreeRecombination(Dilemma dilemmaA, Dilemma dilemmaB, Random randomgenerator, out int indexa, out int indexb) { Dilemma a = dilemmaA.Clone(); Dilemma b = dilemmaB.Clone(); int nodeaindex = randomgenerator.Next(0, a.Tree.Size); int nodebindex = randomgenerator.Next(0, b.Tree.Size); indexa = nodeaindex; indexb = nodebindex; if (nodeaindex == 0) a = b; else { a.Tree.ReplaceTree(nodeaindex, b.Tree.RetrieveTree(nodebindex)); } return a.Clone(); }