public HSGAIndividual SelectIndividual(List <HSGAIndividual> pop, GeneLogger l) { /*float winRateSum = 0f; * float legalitySum = 0f; * float deviationSum = 0f; * * for(int i = 0; i < pop.Count; i++) * { * winRateSum += pop[i].winRateFitness; * legalitySum += pop[i].legalFitness; * deviationSum += pop[i].standardDeviationFitness; * }*/ // check legality fitness first // retrieve a new list of individuals which are legal // we have no need of using illegal individuals // because their overall fitness will be too low. List <HSGAIndividual> editedList = new List <HSGAIndividual>(); for (int i = 0; i < pop.Count; i++) { if (pop[i].legalFitness < 0) { editedList.Add(pop[i]); } } // K tournament selection // select 2 to 4 members from current population at random List <HSGAIndividual> tourneyList = new List <HSGAIndividual>(); HSGAIndividual currentIndToCheck = new HSGAIndividual(); int tourneyCount = 4;//rand.Next(1, 5); for (int j = 0; j < tourneyCount; j++) { int index = rand.Next(0, editedList.Count); tourneyList.Add(editedList[index]); } HSGAIndividual selectedParent = new HSGAIndividual(); for (int p = 0; p < tourneyList.Count; p++) { currentIndToCheck = tourneyList[p]; if (selectedParent.cardList == null) { selectedParent = currentIndToCheck; } if (currentIndToCheck.winRateFitness > selectedParent.winRateFitness && currentIndToCheck.standardDeviationFitness < selectedParent.standardDeviationFitness) { selectedParent = currentIndToCheck; } } l.AddToLog("Parent Selected:" + selectedParent.winRateFitness); return(selectedParent); }
/// <summary> /// Recreates the population from the previously created population /// Needed this in case program crashed and wanted to continue where /// it left off. /// </summary> private void RecreatePreviousPopulation() { for (int i = 0; i < 10; i++) { string currentPath = generationDirectory + "\\Generation" + 11 + "\\Individual" + i + ".txt"; string ctype = "Shaman"; List <string> deck = new List <string>(); HSGAIndividual temp = new HSGAIndividual(); //get numerical stats from file List <float> l = new List <float>(); using (StreamReader sr = File.OpenText(currentPath)) { string s = sr.ReadToEnd(); string[] numbers = Regex.Split(s, @"[^-?\d+\.]"); foreach (string value in numbers) { if (!string.IsNullOrEmpty(value)) { if (l.Count == 3) { break; } float h = float.Parse(value); l.Add(h); } } } temp.winRateFitness = l[0]; temp.legalFitness = l[1]; temp.standardDeviationFitness = l[2]; // get deck of card IDs deck = File.ReadLines(currentPath).ToList(); deck.RemoveRange(0, 5); // recreate current population Tuple <string, List <Card> > t = new Tuple <string, List <Card> >("", null); t = JSONHandler.RecreateIndividualFromFile(deck, ctype); temp.deck = t.Item1; temp.cardList = t.Item2; currentPopulation.Add(temp); } }
public string GenerateDeckString(HSGAIndividual ind, string classType) { string cardList = ""; string finalDeck = ""; for (int j = 0; j < ind.cardList.Count; j++) { cardList += "\t\"" + ind.cardList[j]._CardID + "\",\n"; } finalDeck = "{\n \"cards\": [\n" + cardList + " ],\n \"name\": \"" + finalGeneratedDeckName + "\",\n \"heroClass\": \"" + classType.ToUpper() + "\",\n \"arbitrary\": false\n}"; GenerateDeckAsJson(finalDeck, filePath); return(finalDeck); }
public List <HSGAIndividual> Crossover(List <HSGAIndividual> parents, float crossoverProb, GeneLogger l) { // child 1 left = parent 1, right = parent 2 // child 2 left = parent 2, right = parent 1 HSGAIndividual child1 = new HSGAIndividual(); child1.cardList = new List <Card>(); HSGAIndividual child2 = new HSGAIndividual(); child2.cardList = new List <Card>(); List <HSGAIndividual> children = new List <HSGAIndividual>(); /* for(int i = 0; i < 30; i++) * { * Card c = new Card("", "", "", "", "", "", ""); * child1.cardList.Add(c); * child2.cardList.Add(c); * }*/ if (rand.NextDouble() <= crossoverProb) { l.AddToLog("Performing Crossover."); int point1 = rand.Next(0, parents[0].cardList.Count); if (point1 == 0) { point1 = rand.Next(0, parents[0].cardList.Count); } // need to replace item in list for (int i = 0; i <= point1; i++) { child1.cardList.Add(parents[0].cardList[i]); child2.cardList.Add(parents[1].cardList[i]); } for (int i = point1 + 1; i < parents[0].cardList.Count; i++) { // set index to 1 above crossover point so we dont replace // that card which is set in the previous for loop child1.cardList.Add(parents[1].cardList[i]); child2.cardList.Add(parents[0].cardList[i]); } children.Add(child1); children.Add(child2); } else { // coin flip to determine which parent to clone if // crossover is not chosen. l.AddToLog("Not Performing Crossover."); //Console.WriteLine("Not Performing Crossover."); if (rand.NextDouble() > 0.5f) { child1.cardList = parents[0].cardList; child2.cardList = parents[0].cardList; } else { child1.cardList = parents[1].cardList; child2.cardList = parents[1].cardList; } children.Add(child1); children.Add(child2); } return(children); }
private List <HSGAIndividual> ProduceInitialPopulation(int initialGenNum) { selectedClass = comboBox1.GetItemText(comboBox1.SelectedItem); JSONHandler.filePath = deckDirectory; List <HSGAIndividual> currentPop = new List <HSGAIndividual>(); // assemble the initial population // test each individual in the population for (int i = 0; i < _MaxPopulation; i++) { JSONHandler.RemoveAllCards(); JSONHandler.GetAllCards(numOfFiles, initialDirectory); HSGAIndividual GeneIndividual = new HSGAIndividual(); // Create the deck for the current individual. Tuple <string, List <Card> > t = new Tuple <string, List <Card> >("", null); t = JSONHandler.GenerateSpecificDeck(selectedClass); GeneIndividual.deck = t.Item1; // cList = JSONHandler.GetFinalDeckList(); GeneIndividual.cardList = t.Item2; GeneFunctions gene = new GeneFunctions(); // check if deck is legal - dont really need to do it here // because initial population will be legal regardless bool isLegal = JSONHandler.ValidateDeck(GeneIndividual.cardList); //if deck isnt legal, no need to test it in metastone if (isLegal == true) { // test each individual against each hero class type. for (int opponentNum = 0; opponentNum < 9; opponentNum++) { // send over individual and opponent class numbers GenerateMetastoneValues(comboBox1.SelectedIndex, opponentNum); // run gradlew run command in cmd in metastone directory GenerateAndValidatePopulation(GeneIndividual.deck); // retreive the sim stats from text file. Dictionary <string, float> currentStats = new Dictionary <string, float>(); currentStats = ParseMetastoneResults(); // accumulate current win rate per game. gene.CalculatePerGameStats(currentStats, opponentNum); } } // calc fitness - fitness function // calc legality gene.CalculateFitness(isLegal); GeneIndividual.winRateFitness = gene.winRateFitness; GeneIndividual.legalFitness = gene.legalityFitness; GeneIndividual.standardDeviationFitness = gene.standardDeviationFitness; // Add the individual to the population currentPop.Add(GeneIndividual); // send individual stats to its correspondent folder. using (StreamWriter w = File.CreateText(generationDirectory + "\\Generation" + initialGenNum + "\\Individual" + i + ".txt")) { w.WriteLine("Total Wins: " + GeneIndividual.winRateFitness); w.WriteLine("Legality: " + GeneIndividual.legalFitness); w.WriteLine("Standard Deviation: " + GeneIndividual.standardDeviationFitness); w.WriteLine(); w.WriteLine("Decklist:"); for (int j = 0; j < GeneIndividual.cardList.Count; j++) { string s = GeneIndividual.cardList[j]._CardID; w.WriteLine(s); } } } return(currentPop); }
//TODO // check if it works // may be errors if both pops are illegal due to low pop count // may not occur when full population numbers // MAYBE RUN 2 AT A TIME TO COMPARE SINGLE POINT OVER K POINT CROSSOVER private void ProduceGenerationStats(int generationNum, List <HSGAIndividual> pop) { string path = generationDirectory + "\\Generation" + generationNum; int filesNum = Directory.GetDirectories(generationDirectory, "*", SearchOption.TopDirectoryOnly).Length; float winRateSum = 0f; //float legalSum = 0f; float stdSum = 0f; // calculate avg generation stats for (int i = 0; i < 9; i++) { string currentPath = generationDirectory + "\\Generation" + generationNum + "\\Individual" + i + ".txt"; string[] data = File.ReadAllLines(currentPath); string wr = data[0].Split(':')[1].ToString(); string lg = data[1].Split(':')[1].ToString(); string sd = data[2].Split(':')[1].ToString(); winRateSum += float.Parse(wr); stdSum += float.Parse(sd); } float winRateAvg = winRateSum / 9; float stdAvg = stdSum / 9; // get the best and worst individuals HSGAIndividual bestInd = null; HSGAIndividual worstInd = null; for (int j = 0; j < pop.Count; j++) { float bestWr = pop.Max(HSGAIndividual => HSGAIndividual.winRateFitness); //float bestSd = pop.Max(HSGAIndividual => HSGAIndividual.standardDeviationFitness); float worstWr = pop.Min(HSGAIndividual => HSGAIndividual.winRateFitness); //float worstSd = pop.Min(HSGAIndividual => HSGAIndividual.standardDeviationFitness); bestInd = pop.First(HSGAIndividual => HSGAIndividual.winRateFitness == bestWr); worstInd = pop.First(HSGAIndividual => HSGAIndividual.winRateFitness == worstWr); } using (StreamWriter w = File.CreateText(generationDirectory + "\\Generation" + generationNum + "\\_GenerationAvgStats.txt")) { w.WriteLine("Total Wins:" + winRateAvg); w.WriteLine("Standard Deviation Average:" + stdAvg); w.WriteLine(); w.WriteLine("Best Individual:"); w.WriteLine("Total Wins:" + bestInd.winRateFitness); w.WriteLine("Standard Deviation:" + bestInd.standardDeviationFitness); w.WriteLine("Decklist:"); for (int j = 0; j < bestInd.cardList.Count; j++) { string s = bestInd.cardList[j]._CardID; w.WriteLine(s); } w.WriteLine(); w.WriteLine("Worst Individual:"); w.WriteLine("Total Wins:" + worstInd.winRateFitness); w.WriteLine("Standard Deviation:" + worstInd.standardDeviationFitness); w.WriteLine("Decklist:"); for (int j = 0; j < worstInd.cardList.Count; j++) { string s = worstInd.cardList[j]._CardID; w.WriteLine(s); } } }