//lancia un torneo su population; alla fine di tutto, ordina i pesi in population in base al migliore risultato del torneo public SortedList <WeightScore, int> LaunchTournament(SortedList <WeightScore, int> population, List <WeightsForBoardEval> testPopulation) { SortedList <WeightScore, int> newPopulation = new SortedList <WeightScore, int>(); Dictionary <WeightScore, int> scores = new Dictionary <WeightScore, int>(); for (int i = 0; i < population.Count; i++) { WeightScore ws1 = population.Keys[i]; for (int j = 0; j < testPopulation.Count; j++) { WeightsForBoardEval testPlayer = testPopulation[j]; AlphaBeta ws1AsGoose = new AlphaBeta(PawnType.Goose, 3, ws1.weights, false); AlphaBeta ws1AsFox = new AlphaBeta(PawnType.Fox, 3, ws1.weights, false); AlphaBeta ws2AsGoose = new AlphaBeta(PawnType.Goose, 3, testPlayer, false); AlphaBeta ws2AsFox = new AlphaBeta(PawnType.Fox, 3, testPlayer, false); PairOfScores pairOfScoresGoose = MatchTwoAi(ws1AsGoose, ws2AsFox, 1, i, j); PairOfScores pairOfScoresFox = MatchTwoAi(ws1AsFox, ws2AsGoose, 1, i, j); if (!scores.ContainsKey(ws1)) { scores[ws1] = 0; } scores[ws1] += pairOfScoresGoose.first; scores[ws1] += pairOfScoresFox.first; } WeightScore ws = new WeightScore(ws1.weights, scores[ws1]); newPopulation.Add(ws, scores[ws1]); } return(newPopulation); }
public AlphaBeta(PawnType aiPlayer, int maxPly, WeightsForBoardEval weights, bool random) { this.aiPlayer = aiPlayer; this.maxPly = maxPly; this.weights = weights; this.random = random; }
//valuta la qualità della board public int EvaluateBoard(PawnType aiPlayer, WeightsForBoardEval weights) { //TODO GIULIA //return winner == player ? 1 : -1; int score = 0; //winningState int signOfPlayer = aiPlayer == PawnType.Goose ? 1 : -1; if (IsGooseWinner()) { return(weights.wWinningState * signOfPlayer); } if (IsFoxWinner()) { return(weights.wWinningState * signOfPlayer * -1); } //AIplayer == oca e vince oca torna +200 //AIplayer == oca e vince volpe torna -200 //AIplayer == volpe e vince volpe torna +200 //AIplayer == volpe e vince oca -200 // else non ha vinto nessuno //Console.WriteLine("game weights = " + weights); //gooseNumber score += GetGooseNumber() * weights.weightDict["wGooseNumber"]; //aheadGooseNumber score += GetAheadGooseNumber() * weights.weightDict["wAheadGooseNumber"]; //foxEatingMoves Vector2 foxCoordinates = FindFoxCoordinates(); int rFox = (int)foxCoordinates.x; int cFox = (int)foxCoordinates.y; //cambio score += IACalculateFoxValidEatingMoves(rFox, cFox).Count() * weights.weightDict["wFoxEatingMoves"]; //foxMoves //cambio score += IACalculateFoxValidMoves(rFox, cFox).Count() * weights.weightDict["wFoxMoves"]; //freedomness //cambio score += (int)Math.Round(GetGooseFreedomness() * weights.weightDict["wGooseFreedomness"], 0); //interness //cambio score += GetInterness(rFox, cFox) * weights.weightDict["wInterness"]; //externess score += GetExterness(rFox, cFox) * weights.weightDict["wExterness"]; //Console.WriteLine("score evaluated: " + score * signOfPlayer); return(score * signOfPlayer); }
public void StartTest() { MatchAlgo matchAlgo = new MatchAlgo(); GeneticAlgo geneticAlgo = new GeneticAlgo(); System.Random rand = new System.Random(); List <WeightsForBoardEval> weights = new List <WeightsForBoardEval>(); for (int i = 0; i < 50; i++) { WeightsForBoardEval w = new WeightsForBoardEval(rand); weights.Add(w); Console.WriteLine("pesInizRand = " + w); } SortedList <WeightScore, int> scoreMap = new SortedList <WeightScore, int>(); //per ogni peso = giocatore, fa giocare 3 match come oca e 3 match come volpe al giocatore contro un giocatore casuale for (int i = 0; i < weights.Count; i++) { int score = 0; WeightsForBoardEval weight = weights[i]; AlphaBeta playerAsFox = new AlphaBeta(PawnType.Fox, 3, weight, false); AlphaBeta playerAsGoose = new AlphaBeta(PawnType.Goose, 3, weight, false); score = matchAlgo.MatchTwoAi(playerAsFox, null, 3, -1, -1).first; score += matchAlgo.MatchTwoAi(playerAsGoose, null, 3, -1, -1).first; WeightScore ws = new WeightScore(weight, score); scoreMap.Add(ws, score); } Console.WriteLine("aiTester prima di evoluzione"); // evolve 50 volte la popolazione for (int i = 0; i < 50; i++) { Console.WriteLine("\n \n \n \n inizio evoluzione generazione " + i); scoreMap = geneticAlgo.Evolve(scoreMap, 0.3, 0.1, 0.01); } Console.WriteLine("best weights " + scoreMap.Keys[0]); Console.WriteLine("finito completamente aiTester ore: " + DateTime.Now.ToString("h:mm:ss tt")); Console.ReadKey(); }
// ritorna un WeightsForBoardEval nato da male e female con operazioni bitwise private WeightsForBoardEval CrossoverAndMutate(WeightsForBoardEval male, WeightsForBoardEval female, double mutationProbability) { Console.WriteLine("genetic algo crossover"); Dictionary <String, BitArray> bitFather = new Dictionary <String, BitArray>(); Dictionary <String, BitArray> bitMother = new Dictionary <String, BitArray>(); Dictionary <String, BitArray> bitChild = new Dictionary <String, BitArray>(); foreach (String key in male.weightDict.Keys) { byte[] byteFather = BitConverter.GetBytes(male.weightDict[key]); byte[] byteMother = BitConverter.GetBytes(female.weightDict[key]); bitFather[key] = new BitArray(byteFather); bitMother[key] = new BitArray(byteMother); //crossover bitChild[key] = Mix(bitFather[key], bitMother[key]); //mutazione System.Random random = new System.Random(); double prob = random.NextDouble(); if (prob < mutationProbability) { bitChild[key] = Mutate(bitChild[key]); } } WeightsForBoardEval child = new WeightsForBoardEval( GetIntFromBitArray(bitChild["wGooseNumber"]), GetIntFromBitArray(bitChild["wAheadGooseNumber"]), GetIntFromBitArray(bitChild["wFoxEatingMoves"]), GetIntFromBitArray(bitChild["wFoxMoves"]), GetIntFromBitArray(bitChild["wGooseFreedomness"]), GetIntFromBitArray(bitChild["wInterness"]), GetIntFromBitArray(bitChild["wExterness"]) ); return(child); }
} //punteggio di vittorie public WeightScore(WeightsForBoardEval weights, int score) { this.weights = weights; this.score = score; }
public SortedList <WeightScore, int> Evolve(SortedList <WeightScore, int> population, double retain, double randomSelect, double mutate) { Console.WriteLine("start genetic algo evolve"); foreach (var key in population.Keys) { Console.WriteLine(key); } System.Random rand = new System.Random(); int retainIndex = (int)(population.Count * retain); Console.WriteLine("population size = " + population.Count + " " + retain + " " + randomSelect + " " + mutate); Console.WriteLine("retain tengo " + retainIndex + " soggetti"); SortedList <WeightScore, int> parents = new SortedList <WeightScore, int>(); var iter = population.GetEnumerator(); iter.MoveNext(); for (int i = 0; i < retainIndex; i++) { parents[iter.Current.Key] = iter.Current.Value; iter.MoveNext(); } //aggiunge altri soggetti con una percentuale di aggiunta pari a randomSelect while (iter.MoveNext()) { if (randomSelect > rand.NextDouble()) { var ws = iter.Current; parents[ws.Key] = ws.Value; } } foreach (var key in parents.Keys) { Console.WriteLine(key); } int parentsCount = parents.Count; int childrenToGenerate = population.Count - parentsCount; //quanti figli devo generare per ritornare ad avere una popolazione completa int generatedChildren = 0; Console.WriteLine("fine evolve" + population.Count + " " + parents.Count + " " + childrenToGenerate); //crossover while (parents.Count < population.Count - 2) { //Console.WriteLine("parent count= " + parents.Count + " pop count = " + population.Count); //Console.WriteLine("GeneticAlgo genero figli"); int firstN = rand.Next(parentsCount); int secondN = rand.Next(parentsCount); WeightsForBoardEval male = parents.Keys[firstN].weights; WeightsForBoardEval female = parents.Keys[secondN].weights; if (!male.Equals(female)) { WeightsForBoardEval child = CrossoverAndMutate(male, female, mutate); WeightScore ws = new WeightScore(child, 0); parents[ws] = 0; generatedChildren++; } } WeightScore ws1 = new WeightScore(new WeightsForBoardEval(rand), 0); WeightScore ws2 = new WeightScore(new WeightsForBoardEval(rand), 0); parents[ws1] = 0; parents[ws2] = 0; List <WeightsForBoardEval> testPopulation = new List <WeightsForBoardEval>(); testPopulation.Add(new WeightsForBoardEval(1, 0, 0, 0, 0, 0, 0)); testPopulation.Add(new WeightsForBoardEval(2, 2, -2, -2, -1, -1, 0)); return(new MatchAlgo().LaunchTournament(parents, testPopulation)); //lancia un torneo sulla popolazione e ritorna la popolazione con gli score aggiornati }