/// <summary> /// Moves a piece to another place on the board /// </summary> /// <param name="oldBoard"> the board before the piece is moved </param> /// <param name="pieceToMove"> the piece to be moved on the board </param> /// <param name="squareToMoveTo"> yhe square to move the piece to </param> public Move(char[] oldBoard, int pieceToMove, int squareToMoveTo) { from = pieceToMove; to = squareToMoveTo; newBoard = new char[oldBoard.Length]; for (int i = 0; i < newBoard.Length; i++) { if (i == squareToMoveTo) { //moves piece to new place newBoard[i] = oldBoard[pieceToMove]; } else { //Just copy it over newBoard[i] = oldBoard[i]; } } //Enpassant check if (to == BoardManager.Instance.enPassentIndex && char.ToUpper(oldBoard[from]) == 'P') { if (from > to && to + 8 < newBoard.Length) { //Moving downward newBoard[to + 8] = '\0'; enpassentIndex = to + 8; } else if (to - 8 >= 0) { //Moving upward newBoard[to - 8] = '\0'; enpassentIndex = to - 8; } } //Promotion Check if ((char.ToUpper(movedPiece) == 'P') && (to > 55 || to < 8)) { //Promoted if (TurnManager.Instance.IsPlayerTurn()) { //Prompt player for which piece they want } else { //Choose queen, as statistcally it is the best choice newBoard[to] = (GameManager.Instance.playerTeam == PieceScript.Team.White) ? 'q' : 'Q'; promotionType = PieceScript.Type.Queen; } } //Remove old piece newBoard[pieceToMove] = '\0'; //Set Self Fitness self_fitness = FitnessEvaluator.Evaluate(newBoard); pathFitness = self_fitness; }
static void Main(string[] args) { string targetPhenotype; int popSize; long maxGenerations; long totalGenerationsPassed = 0; double bestFitness = 0.0; double mutationRate; double crossoverRate; Random random = new Random(); Stopwatch stopwatch = new Stopwatch(); List <Genome> population = new List <Genome>(); List <Tuple <double, Genome> > evaluatedPopulation = new List <Tuple <double, Genome> >(); List <Task <Tuple <double, Genome> > > taskList = new List <Task <Tuple <double, Genome> > >(); (popSize, maxGenerations, mutationRate, crossoverRate, targetPhenotype) = MultiStrandCLISetup(); for (int i = 0; i < popSize; i++) { /* * The initial population has random generators seeded with randomly generated numbers. * That way the states of generators won't be the same and mutations will be applied in more stochastic manner. */ population.Add(new Genome(targetPhenotype.Length, random.Next())); } stopwatch.Start(); while (bestFitness != 1 && maxGenerations <= totalGenerationsPassed) { foreach (Genome genome in population) { taskList.Add( Task.Run( () => FitnessEvaluator.EvaluateGenome(targetPhenotype, genome))); } for (int i = 0; i < popSize; i++) { evaluatedPopulation.Add(taskList[i].Result); } evaluatedPopulation = evaluatedPopulation.OrderBy( genomeFitnessPair => genomeFitnessPair.Item1).ToList(); //Clear lists population.Clear(); taskList.Clear(); //Keep only the 10 best individuals evaluatedPopulation = evaluatedPopulation.TakeLast(10).ToList(); bestFitness = evaluatedPopulation.Last().Item1; //Print results every 10th generations or if the optimum fitness is met. if (totalGenerationsPassed % 10 == 0 || bestFitness == 1.0) { Console.WriteLine("Generation: {2} \nBest fitness: {0} \nText: {1} \n\n", bestFitness, evaluatedPopulation.First().Item2.Genes, totalGenerationsPassed); } for (int index = 0; index < popSize; index++) { if (random.NextDouble() <= crossoverRate) { population.Add( evaluatedPopulation[(index + 1) % evaluatedPopulation.Count].Item2.Cross( evaluatedPopulation[index % evaluatedPopulation.Count].Item2)); } else { population.Add(evaluatedPopulation[index % evaluatedPopulation.Count].Item2); } } foreach (Genome genome in population) { genome.Mutate(mutationRate); } population.Add(evaluatedPopulation[0].Item2); totalGenerationsPassed++; } stopwatch.Stop(); Console.WriteLine("Time elapsed: {0:T}", stopwatch.Elapsed); Console.WriteLine("Over {0} generations.", totalGenerationsPassed); }
/// <summary> /// Solves the specified minimum temperature. /// </summary> /// <param name="minimumTemperature">The minimum temperature.</param> /// <param name="maximumTemperature">The maximum temperature.</param> /// <param name="iterationCount">The iteration count.</param> /// <param name="fitnessEvaluator">The fitness evaluator.</param> public void Solve(double minimumTemperature, double maximumTemperature, int iterationCount, FitnessEvaluator fitnessEvaluator) { double bestFitness = double.PositiveInfinity; var bestValues = new double[this.Variables.Length]; //providing initial value for fitness double Fitness = fitnessEvaluator(); double temperatureIncrement = (maximumTemperature - minimumTemperature) / iterationCount; for (int i = 0; i <= iterationCount; i++) { this.randomizeValues(); //in addition to evaluating fitness, the FitnessEvaluator delegate can also update interface double currentFitness = fitnessEvaluator(); //updating the best set of variable values if (currentFitness < bestFitness) { for (int j = 0; j < bestValues.Length; j++) { bestValues[j] = this.Variables[j].Value; } bestFitness = currentFitness; this.OnBestFitnessUpdated(new UIEventArgs(bestFitness)); } //annealing core if (currentFitness < Fitness) { Fitness = currentFitness; this.OnFitnessUpdated(new UIEventArgs(Fitness)); } else // fitness - currentfitness < 0 { double temperature = minimumTemperature + (iterationCount - i) * temperatureIncrement; double power = (Fitness - currentFitness) / temperature; double p = Math.Exp(power); double random = this._randomizer.NextDouble(); if (p > random) { Fitness = currentFitness; this.OnFitnessUpdated(new UIEventArgs(Fitness)); } else //revesring the changes in variable values { this.Variables[this._selectedVariableIndex].Value = this._selectedVariablePreviousValue; } } } //updating the variables with the best set of variables for (int i = 0; i < this.Variables.Length; i++) { this.Variables[i].Value = bestValues[i]; } }
/// <summary> /// Creates a population and let it evolve until termination condition is reached. /// </summary> /// <param name="terminationCondition">Evolution termination condition evaluated on each new epoch</param> /// <returns>The best solution found across the evolution</returns> public ISolution EvolveUntil(TerminationCondition terminationCondition) { var rnd = RandomProvider.GetThreadRandom(); var shiftMatrix = MatrixBuilder.Build(this.problem); var enumerator = new IncreasingRowsRandomColumns(this.problem.Days, this.problem.Slots); var constraints = ConstraintsBuilder.Build(this.problem); var chromoProcessor = new ChromosomeProcessor(shiftMatrix, enumerator, constraints); var evaluator = new FitnessEvaluator(problem); var fitnessFunction = new Fitness.FitnessFunction(chromoProcessor, evaluator, shiftMatrix); var chromosomeLength = shiftMatrix.GetNumberOfUnforcedSlots(); const double crossoverProbability = 0.90; const double mutationProbability = 0.05; const int elitismPercentage = 5; epochs = 1; epochsWithoutFitnessImprovement = 0; overallBestFitness = -1; log.Debug("Starting population."); var population = new Population(); for (var i = 0; i < populationSize; i++) { var c = new Double[chromosomeLength]; for (var k = 0; k < chromosomeLength; k++) { c[k] = rnd.NextDouble(); } var ch = new Chromosome(c); population.Solutions.Add(ch); } //create the genetic operators var elite = new Elite(elitismPercentage); var crossover = new Crossover(crossoverProbability, true) { CrossoverType = CrossoverType.SinglePoint }; var mutation = new SwapMutate(mutationProbability); //create the GA itself var ga = new GeneticAlgorithm(population, fitnessFunction.Evaluate); //subscribe to the GAs Generation Complete event ga.OnGenerationComplete += Ga_OnGenerationComplete; //add the operators to the ga process pipeline ga.Operators.Add(elite); ga.Operators.Add(crossover); ga.Operators.Add(mutation); //run the GA ga.Run((pop, currentGeneration, currentEvaluation) => { return(terminationCondition(currentGeneration, epochsWithoutFitnessImprovement, population.MaximumFitness, population.AverageFitness)); }); population.GetTop(1)[0].Evaluate(fitnessFunction.Evaluate); return(SolutionBuilder.Build(overallBestFitness, shiftMatrix, epochs * population.PopulationSize, this.problem.Items)); }