/** * Two-point crossover. * @param parent1 The first parent. * @param parent2 The second parent. * @return The child drawing. */ private CandidateSolution crossover(CandidateSolution parent1, CandidateSolution parent2) { Random random = new Random(); int startPosition = random.Next(GenotypeLength); int endPosition = random.Next(GenotypeLength); if (startPosition > endPosition) { int tmp = startPosition; startPosition = endPosition; endPosition = tmp; } CandidateSolution child = new CandidateSolution(fitnessCalculator, BitSize, GenotypeLength, GroupSize); for (int i = 0; i < GenotypeLength; i++) { if (startPosition <= i && i <= endPosition) { child.Solution[i] = parent2.Solution[i]; } else { child.Solution[i] = parent1.Solution[i]; } } return(child); }
private void Redraw(int generation, CandidateSolution <List <DungeonOp> > bestSolution) { var data = new List <DungeonOp>(bestSolution.Solution); var map = new GridMap(new Random()); foreach (var op in data) { op.Execute(map); } lock (drawLock) { this.Clear(); var status = $"{(DateTime.Now - this.startedOn).TotalSeconds}s | Generation {generation}, FITNESS: best={bestSolution.Fitness}, with {data.Count} ops"; this.Print(0, STATUS_Y, status, Color.White); System.Console.WriteLine(status); for (var y = 0; y < this.Height - 1; y++) { for (var x = 0; x < this.Width; x++) { var text = map.Get(x, y) ? "." : "#"; var colour = text == "#" ? WALL_COLOUR : FLOOR_COLOUR; this.Print(x, y, text, colour); } } } }
public double Calculate(CandidateSolution solution) { double sum = 0d; var groups = GetGroups(solution); foreach (var group in groups.Keys) { var groupSum = 0; var members = groups[group].ToArray(); for (int memberOne = 0; memberOne < members.Length; memberOne++) { for (int memberTwo = 0; memberTwo < members.Length; memberTwo++) { if (memberOne != memberTwo) { if (relationships[members[memberOne]].ContainsKey(members[memberTwo])) { groupSum++; } } } } sum += groupSum; } return(sum); }
private void PerGenerationCallback(string status, CandidateSolution <bool, ProblemState> bestThisGeneration) { var strategy = StrategyFactory.GetStrategyForGP(bestThisGeneration); DisplayStrategyGrids(strategy, ""); DisplayCurrentStatus(status); }
//------------------------------------------------------------------------- // each candidate gets evaluated here //------------------------------------------------------------------------- private float EvaluateCandidate(CandidateSolution <bool, ProblemState> candidate) { // test every possible situation and store the candidate's suggested action in the strategy object Strategy strategy = StrategyFactory.GetStrategyForGP(candidate); // then test that strategy and return the total money lost/made var strategyTester = new StrategyTester(strategy, settings.TestSettings); return(strategyTester.GetStrategyScore(settings.TestSettings.NumHandsToPlay)); }
public static void DebugDisplayStrategy(CandidateSolution <bool, ProblemState> candidate, string prefixText) { string debug = prefixText + (String.IsNullOrWhiteSpace(prefixText) ? "" : " ") + " Plr: " + candidate.StateData.PlayerHand + " H: " + candidate.StateData.VotesForHit + " S: " + candidate.StateData.VotesForStand + " P: " + candidate.StateData.VotesForSplit + " D: " + candidate.StateData.VotesForDoubleDown; Debug.WriteLine(debug); }
/** * @return The solution with the highest fitness. */ public CandidateSolution getFittest() { CandidateSolution fittest = candidateSolutions[0]; for (int i = 1; i < candidateSolutions.Length; i++) { if (fittest.Fitness < candidateSolutions[i].Fitness) { fittest = candidateSolutions[i]; } } return(fittest); }
public static Strategy GetStrategyForGP(CandidateSolution <bool, ProblemState> candidate) { Strategy result = new Strategy(); foreach (var upcardRank in Card.ListOfRanks) { if (upcardRank == Card.Ranks.Jack || upcardRank == Card.Ranks.Queen || upcardRank == Card.Ranks.King) { continue; } AddStrategyForUpcard(upcardRank, result, candidate); } return(result); }
/** * Constructs a new population. * @param size The size of the population. * @param initialise True, if the population will be initialised. */ public Population(FitnessCalculator fitnessCalculator, int size, int bitSize, int genotypeLength, int groupSize, bool initialise = false) { candidateSolutions = new CandidateSolution[size]; this.fitnessCalculator = fitnessCalculator; this.groupSize = groupSize; if (initialise) { for (int i = 0; i < candidateSolutions.Length; i++) { CandidateSolution candidateSolution = new CandidateSolution(fitnessCalculator, bitSize, genotypeLength, groupSize); candidateSolution.GenerateIndividual(); candidateSolutions[i] = candidateSolution; } } }
private Dictionary <int, List <int> > GetGroups(CandidateSolution solution) { var max = solution.Solution.Max(); var groups = new Dictionary <int, List <int> >(); for (int i = 1; i <= max; i++) { groups.Add(i, new List <int>()); } for (int member = 0; member < solution.Solution.Length; member++) { groups[solution.Solution[member]].Add(member + 1); } return(groups); }
static void ShowFinalResults(CandidateSolution <double, StateData> solution) { // then test how well it does double finalScore; string testDetails; RunFinalTests(solution, out finalScore, out testDetails); Console.WriteLine(); Console.WriteLine("Final score: " + finalScore.ToString("0.0000")); Console.WriteLine(); Console.WriteLine(solution.ToString()); var writer = File.AppendText("test-results.csv"); writer.Write(testDetails); writer.Close(); }
//------------------------------------------------------------------------- // For each generation, we get information about what's going on //------------------------------------------------------------------------- private bool PerGenerationCallback(EngineProgress progress, CandidateSolution <bool, ProblemState> bestThisGeneration) { string summary = "Upcard " + currentDealerUpcardRank + " gen: " + progress.GenerationNumber + " best: " + progress.BestFitnessThisGen.ToString("0") + " avg: " + progress.AvgFitnessThisGen.ToString("0"); perGenerationCallback(summary, bestThisGeneration); Debug.WriteLine(summary); // keep track of how many gens we've searched NumGenerationsNeeded++; // return true to keep going, false to halt the system bool keepRunning = true; return(keepRunning); }
/** * Mutation of a candidate solution. * @param candidateSolution The candidate solution. */ private void mutate(CandidateSolution candidateSolution) { Random random = new Random(); if (random.NextDouble() < MutationProbability) { int i = random.Next(candidateSolution.Solution.Length); int j = random.Next(candidateSolution.Solution.Length); while (i == j) { j = random.Next(candidateSolution.Solution.Length); } var temp = candidateSolution.Solution[i]; candidateSolution.Solution[i] = candidateSolution.Solution[j]; candidateSolution.Solution[j] = temp; } }
static void RunFinalTests(CandidateSolution <double, StateData> candidate, out double finalScore, out string testDetails) { var sampleData = new Dataset(); StringBuilder sb = new StringBuilder(); sb.AppendLine("Test results at " + DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToShortTimeString()); // run through our test data and see how close the answer the genetic program // comes up with is to the training data. Lower fitness scores are better than bigger scores double totalDifference = 0; while (true) { var row = sampleData.GetRowOfTestingData(); if (row == null) { break; } // populate vars with values from row of the training data for (int i = 0; i < Dataset.NumColumns; i++) { if (i != Dataset.LabelColumnIndex) { candidate.SetVariableValue("v" + i, row[i]); } } var result = candidate.Evaluate(); // now figure the difference between the calculated value and the training data var actualAnswer = row[Dataset.LabelColumnIndex]; var diff = result - actualAnswer; totalDifference += diff * diff; Console.WriteLine("Ans: " + actualAnswer.ToString(" 0") + " AI: " + result.ToString("0.00")); sb.AppendLine(actualAnswer.ToString("0.0") + ", " + result.ToString("0.000")); } totalDifference = Math.Sqrt(totalDifference); finalScore = (float)totalDifference; sb.AppendLine("\"Final score\", " + finalScore.ToString("0.000")); testDetails = sb.ToString(); }
private bool IsValid(CandidateSolution solution) { var counter = new Dictionary <int, int>(); for (int i = 1; i <= BitSize; i++) { counter.Add(i, 0); } for (int i = 0; i < solution.Solution.Length; i++) { counter[solution.Solution[i]]++; if (counter[solution.Solution[i]] > GroupSize) { return(false); } } return(true); }
static float EvaluateCandidate(CandidateSolution <double, StateData> candidate) { var sampleData = new Dataset(); // run through our test data and see how close the answer the genetic program // comes up with is to the training data. Lower fitness scores are better than bigger scores double totalDifference = 0; while (true) { var row = sampleData.GetRowOfTrainingData(); if (row == null) { break; } // populate vars with values from row of the training data, and then get the calculated value for (int i = 0; i < Dataset.NumColumns; i++) { if (i != Dataset.LabelColumnIndex) { candidate.SetVariableValue("v" + i, row[i]); } } var result = candidate.Evaluate(); // now figure the difference between the calculated value and the training data var actualAnswer = row[Dataset.LabelColumnIndex]; var diff = result - actualAnswer; totalDifference += diff * diff; } // sqrt of the summed squared diffences totalDifference = Math.Sqrt(totalDifference); // fitness function returns a float return((float)totalDifference); }
public abstract void SetCandidateRef(CandidateSolution <T, S> candidate);
public override void SetCandidateRef(CandidateSolution <T, S> candidate) { // no need to store a reference to the candidate for a constant }
public void BuildProgram( int populationSize, int crossoverPercentage, double mutationPercentage, int ElitismPercentage, int tourneySize, Action <string> currentStatusCallback, string dealerUpcardRankToUse) { displayGenerationCallback = currentStatusCallback; dealerUpcardRank = dealerUpcardRankToUse; // just some values, leave the rest as defaults var engineParams = new EngineParameters() { CrossoverRate = crossoverPercentage / 100F, ElitismRate = ElitismPercentage / 100F, IsLowerFitnessBetter = false, MutationRate = mutationPercentage / 100F, PopulationSize = populationSize, TourneySize = tourneySize }; // create the engine. each tree (and node within the tree) will return a bool. // we also indicate the type of our problem state data (used by terminal functions and stateful functions) var engine = new Engine <bool, ProblemState>(engineParams); // no constants for this problem // no variables for this solution - we can't pass in information about our hand // via boolean variables, so we do it via some terminal functions instead // for a boolean tree, we use the standard operators engine.AddFunction((a, b) => a || b, "Or"); engine.AddFunction((a, b, c) => a || b || c, "Or3"); engine.AddFunction((a, b) => a && b, "And"); engine.AddFunction((a, b, c) => a && b && c, "And3"); engine.AddFunction((a) => !a, "Not"); // then add functions to indicate a strategy engine.AddStatefulFunction(HitIf, "HitIf"); engine.AddStatefulFunction(StandIf, "StandIf"); engine.AddStatefulFunction(DoubleIf, "DoubleIf"); engine.AddStatefulFunction(SplitIf, "SplitIf"); // terminal functions to look at game state // first, player holding ace? engine.AddTerminalFunction(HasAce, "HasAce"); engine.AddTerminalFunction(HasPair, "HasPair"); // player hand totals engine.AddTerminalFunction(HandVal4, "Has4"); engine.AddTerminalFunction(HandVal5, "Has5"); engine.AddTerminalFunction(HandVal6, "Has6"); engine.AddTerminalFunction(HandVal7, "Has7"); engine.AddTerminalFunction(HandVal8, "Has8"); engine.AddTerminalFunction(HandVal9, "Has9"); engine.AddTerminalFunction(HandVal10, "Has10"); engine.AddTerminalFunction(HandVal11, "Has11"); engine.AddTerminalFunction(HandVal12, "Has12"); engine.AddTerminalFunction(HandVal13, "Has13"); engine.AddTerminalFunction(HandVal14, "Has14"); engine.AddTerminalFunction(HandVal15, "Has15"); engine.AddTerminalFunction(HandVal16, "Has16"); engine.AddTerminalFunction(HandVal17, "Has17"); engine.AddTerminalFunction(HandVal18, "Has18"); engine.AddTerminalFunction(HandVal19, "Has19"); engine.AddTerminalFunction(HandVal20, "Has20"); // num cards held engine.AddTerminalFunction(Holding2Cards, "Hold2"); engine.AddTerminalFunction(Holding3Cards, "Hold3"); // pass a fitness evaluation function and run engine.AddFitnessFunction((t) => EvaluateCandidate(t)); // and add something so we can track the progress engine.AddProgressFunction((t) => PerGenerationCallback(t)); BestSolution = engine.FindBestSolution(); }
//------------------------------------------------------------------------- // each candidate gets evaluated here //------------------------------------------------------------------------- private float EvaluateCandidate(CandidateSolution <bool, ProblemState> candidate) { int playerChips = 0; for (int handNum = 0; handNum < TestConditions.NumHandsToPlay; handNum++) { // for each hand, we generate a random deck. Blackjack is often played with multiple decks to improve the house edge MultiDeck deck = new MultiDeck(TestConditions.NumDecks); // always use the designated dealer upcard (of hearts), so we need to remove from the deck so it doesn't get used twice deck.RemoveCard(dealerUpcardRank, "H"); Hand dealerHand = new Hand(); Hand playerHand = new Hand(); playerHand.AddCard(deck.DealCard()); dealerHand.AddCard(new Card(dealerUpcardRank, "H")); playerHand.AddCard(deck.DealCard()); dealerHand.AddCard(deck.DealCard()); // save the cards in state, and reset the votes for this hand candidate.StateData.PlayerHands.Clear(); candidate.StateData.PlayerHands.Add(playerHand); // do the intial wager int totalBetAmount = TestConditions.BetSize; playerChips -= TestConditions.BetSize; // outer loop is for each hand the player holds. Obviously this only happens when they've split a hand for (int handIndex = 0; handIndex < candidate.StateData.PlayerHands.Count; handIndex++) { candidate.StateData.HandIndex = handIndex; playerHand = candidate.StateData.PlayerHand; // gets the current hand, based on index // loop until the hand is done var currentHandState = TestConditions.GameState.PlayerDrawing; // check for player having a blackjack, which is an instant win if (playerHand.HandValue() == 21) { // if the dealer also has 21, then it's a tie if (dealerHand.HandValue() != 21) { currentHandState = TestConditions.GameState.PlayerBlackjack; playerChips += TestConditions.BlackjackPayoffSize; } else { // a tie means we just ignore it and drop through currentHandState = TestConditions.GameState.HandComparison; } } // check for dealer having blackjack, which is either instant loss or tie if (dealerHand.HandValue() == 21) { currentHandState = TestConditions.GameState.HandComparison; } // player draws while (currentHandState == TestConditions.GameState.PlayerDrawing) { // get the decision candidate.StateData.VotesForDoubleDown = 0; candidate.StateData.VotesForHit = 0; candidate.StateData.VotesForStand = 0; candidate.StateData.VotesForSplit = 0; candidate.Evaluate(); // throw away the result, because it's meaningless // look at the votes to see what to do var action = GetAction(candidate.StateData); // if there's an attempt to double-down with more than 2 cards, turn into a hit if (action == ActionToTake.Double && playerHand.Cards.Count > 2) { action = ActionToTake.Hit; } // if we're trying to split, but don't have a pair, turn that into a stand? if (action == ActionToTake.Split && !playerHand.IsPair()) { Debug.Assert(false, "Vote for split without a pair"); } switch (action) { case ActionToTake.Hit: // hit me playerHand.AddCard(deck.DealCard()); // if we're at 21, we're done if (playerHand.HandValue() == 21) { currentHandState = TestConditions.GameState.DealerDrawing; } // did we bust? if (playerHand.HandValue() > 21) { currentHandState = TestConditions.GameState.PlayerBusted; } break; case ActionToTake.Stand: // if player stands, it's the dealer's turn to draw currentHandState = TestConditions.GameState.DealerDrawing; break; case ActionToTake.Double: // double down means bet another chip, and get one and only card card playerChips -= TestConditions.BetSize; totalBetAmount += TestConditions.BetSize; playerHand.AddCard(deck.DealCard()); if (playerHand.HandValue() > 21) { currentHandState = TestConditions.GameState.PlayerBusted; } else { currentHandState = TestConditions.GameState.DealerDrawing; } break; case ActionToTake.Split: // do the split and add the hand to our collection var newHand = new Hand(); newHand.AddCard(playerHand.Cards[1]); playerHand.Cards[1] = deck.DealCard(); newHand.AddCard(deck.DealCard()); candidate.StateData.PlayerHands.Add(newHand); //Debug.WriteLine("TID " + AppDomain.GetCurrentThreadId() + " " + // "is splitting and has " + candidate.StateData.PlayerHands.Count + " hands"); Debug.Assert(candidate.StateData.PlayerHands.Count < 5, "Too many hands for player"); // our extra bet playerChips -= TestConditions.BetSize; // we don't adjust totalBetAmount because each bet pays off individually, so the total is right //totalBetAmount += TestConditions.BetSize; break; } } // if the player busted, nothing to do, since chips have already been consumed. Just go on to the next hand // on the other hand, if the player hasn't busted, then we need to play the hand for the dealer while (currentHandState == TestConditions.GameState.DealerDrawing) { // if player didn't bust or blackjack, dealer hits until they have 17+ (hits on soft 17) if (dealerHand.HandValue() < 17) { dealerHand.AddCard(deck.DealCard()); if (dealerHand.HandValue() > 21) { currentHandState = TestConditions.GameState.DealerBusted; playerChips += totalBetAmount * 2; // the original bet and a matching amount } } else { // dealer hand is 17+, so we're done currentHandState = TestConditions.GameState.HandComparison; } } if (currentHandState == TestConditions.GameState.HandComparison) { int playerHandValue = playerHand.HandValue(); int dealerHandValue = dealerHand.HandValue(); // if it's a tie, give the player his bet back if (playerHandValue == dealerHandValue) { playerChips += totalBetAmount; } else { if (playerHandValue > dealerHandValue) { // player won playerChips += totalBetAmount * 2; // the original bet and a matching amount } else { // player lost, nothing to do since the chips have already been decremented } } } } } return(playerChips); }
private static void AddStrategyForUpcard(Card.Ranks upcardRank, Strategy result, CandidateSolution <bool, ProblemState> candidate) { Card dealerCard = new Card(upcardRank, Card.Suits.Diamonds); // do pairs for (var pairedRank = Card.Ranks.Ace; pairedRank >= Card.Ranks.Two; pairedRank--) { // build player hand Hand playerHand = new Hand(); playerHand.AddCard(new Card(pairedRank, Card.Suits.Hearts)); playerHand.AddCard(new Card(pairedRank, Card.Suits.Spades)); // find strategy SetupStateData(candidate.StateData, playerHand, dealerCard); candidate.Evaluate(); // get the decision and store in the strategy object var action = GetActionFromCandidate(candidate.StateData); result.SetActionForPair(upcardRank, pairedRank, action); } // then soft hands // we don't start with Ace, because that would be AA, which is handled in the pair zone // we also don't start with 10, since that's blackjack. So 9 is our starting point for (int otherCard = 9; otherCard > 1; otherCard--) { // build player hand Hand playerHand = new Hand(); // first card is an ace, second card is looped over playerHand.AddCard(new Card(Card.Ranks.Ace, Card.Suits.Hearts)); playerHand.AddCard(new Card((Card.Ranks)otherCard, Card.Suits.Spades)); // find strategy SetupStateData(candidate.StateData, playerHand, dealerCard); candidate.Evaluate(); // get the decision and store in the strategy object var action = GetActionFromCandidate(candidate.StateData); result.SetActionForSoftHand(upcardRank, otherCard, action); } // hard hands. for (int hardTotal = 20; hardTotal > 4; hardTotal--) { // build player hand Hand playerHand = new Hand(); // divide by 2 if it's even, else add one and divide by two int firstCardRank = ((hardTotal % 2) != 0) ? (hardTotal + 1) / 2 : hardTotal / 2; int secondCardRank = hardTotal - firstCardRank; // 20 is always TT, which is a pair, so we handle that by building a 3 card hand if (hardTotal == 20) { playerHand.AddCard(new Card(Card.Ranks.Ten, Card.Suits.Diamonds)); firstCardRank = 6; secondCardRank = 4; } // we don't want pairs, so check for that if (firstCardRank == secondCardRank) { firstCardRank++; secondCardRank--; } playerHand.AddCard(new Card((Card.Ranks)firstCardRank, Card.Suits.Diamonds)); playerHand.AddCard(new Card((Card.Ranks)secondCardRank, Card.Suits.Spades)); // find strategy SetupStateData(candidate.StateData, playerHand, dealerCard); candidate.Evaluate(); // get the decision and store in the strategy object var action = GetActionFromCandidate(candidate.StateData); result.SetActionForHardHand(upcardRank, hardTotal, action); } }
/// <summary> /// Calculate and return the optimal solution to the given problem. /// </summary> /// <param name="problem">The problem whose optimal solution we seek</param> /// <returns>The optimal solution</returns> public Solution OptimalSoultion(Problem problem) { // Figure out our temperature and strength requirements double targetTemp = 0.0; double strengthReq = 0.0; foreach (Constraint constraint in problem.Constraints) { switch (constraint.Value) { case VALUE.TEMP: targetTemp = constraint.Target; break; case VALUE.FORCE_LIMIT: strengthReq = constraint.Target; break; } } // Enumerate solutions for every combination of material and cooler List <CandidateSolution> candidates = new List <CandidateSolution>(); foreach (Material m in materials) { foreach (Cooler c in coolers) { CandidateSolution cs = new CandidateSolution(m, c, targetTemp, strengthReq, problem); if (cs.IsFeasible) { candidates.Add(cs); } } } // Find the best solution double solutionCost = Double.MaxValue; CandidateSolution optimalSolution = null; foreach (CandidateSolution c in candidates) { if (c.SolutionCost < solutionCost) { optimalSolution = c; solutionCost = c.SolutionCost; } } Solution answer = null; if (candidates.Count == 0) { return(null); } else { answer = new Solution( problem.Name, optimalSolution.Cooler.Name, optimalSolution.CoolerPowerFactor, optimalSolution.Material.Name, optimalSolution.StrutCrossSection, optimalSolution.StrutLength, optimalSolution.SolutionCost ); } return(answer); }
public override void BuildProgram(ProgramSettings settings, Action <string> currentStatusCallback) { this.settings = settings; displayGenerationCallback = currentStatusCallback; // create the engine. each tree (and node within the tree) will return a bool. // we also indicate the type of our problem state data (used by terminal functions and stateful functions) var engine = new Engine <bool, ProblemState>(settings.GPsettings); // no constants for this problem // no variables for this solution - we can't pass in information about our hand // via boolean variables, so we do it via some terminal functions instead // for a boolean tree, we use the standard operators engine.AddFunction((a, b) => a || b, "Or"); engine.AddFunction((a, b, c) => a || b || c, "Or3"); engine.AddFunction((a, b) => a && b, "And"); engine.AddFunction((a, b, c) => a && b && c, "And3"); engine.AddFunction((a) => !a, "Not"); // then add functions to indicate a strategy engine.AddStatefulFunction(HitIf, "HitIf"); engine.AddStatefulFunction(StandIf, "StandIf"); engine.AddStatefulFunction(DoubleIf, "DoubleIf"); engine.AddStatefulFunction(SplitIf, "SplitIf"); //---------------------------------------------- // terminal functions to look at game state //---------------------------------------------- // soft hands engine.AddTerminalFunction(AcePlus2, "AcePlus2"); engine.AddTerminalFunction(AcePlus3, "AcePlus3"); engine.AddTerminalFunction(AcePlus4, "AcePlus4"); engine.AddTerminalFunction(AcePlus5, "AcePlus5"); engine.AddTerminalFunction(AcePlus6, "AcePlus6"); engine.AddTerminalFunction(AcePlus7, "AcePlus7"); engine.AddTerminalFunction(AcePlus8, "AcePlus8"); engine.AddTerminalFunction(AcePlus9, "AcePlus9"); // pairs engine.AddTerminalFunction(HasPairTwos, "HasPair2"); engine.AddTerminalFunction(HasPairThrees, "HasPair3"); engine.AddTerminalFunction(HasPairFours, "HasPair4"); engine.AddTerminalFunction(HasPairFives, "HasPair5"); engine.AddTerminalFunction(HasPairSixes, "HasPair6"); engine.AddTerminalFunction(HasPairSevens, "HasPair7"); engine.AddTerminalFunction(HasPairEights, "HasPair8"); engine.AddTerminalFunction(HasPairNines, "HasPair9"); engine.AddTerminalFunction(HasPairTens, "HasPairT"); engine.AddTerminalFunction(HasPairAces, "HasPairA"); // hard hand totals engine.AddTerminalFunction(HandVal5, "Hard5"); engine.AddTerminalFunction(HandVal6, "Hard6"); engine.AddTerminalFunction(HandVal7, "Hard7"); engine.AddTerminalFunction(HandVal8, "Hard8"); engine.AddTerminalFunction(HandVal9, "Hard9"); engine.AddTerminalFunction(HandVal10, "Hard10"); engine.AddTerminalFunction(HandVal11, "Hard11"); engine.AddTerminalFunction(HandVal12, "Hard12"); engine.AddTerminalFunction(HandVal13, "Hard13"); engine.AddTerminalFunction(HandVal14, "Hard14"); engine.AddTerminalFunction(HandVal15, "Hard15"); engine.AddTerminalFunction(HandVal16, "Hard16"); engine.AddTerminalFunction(HandVal17, "Hard17"); engine.AddTerminalFunction(HandVal18, "Hard18"); engine.AddTerminalFunction(HandVal19, "Hard19"); engine.AddTerminalFunction(HandVal20, "Hard20"); // upcards engine.AddTerminalFunction(DealerShows2, "Dlr2"); engine.AddTerminalFunction(DealerShows3, "Dlr3"); engine.AddTerminalFunction(DealerShows4, "Dlr4"); engine.AddTerminalFunction(DealerShows5, "Dlr5"); engine.AddTerminalFunction(DealerShows6, "Dlr6"); engine.AddTerminalFunction(DealerShows7, "Dlr7"); engine.AddTerminalFunction(DealerShows8, "Dlr8"); engine.AddTerminalFunction(DealerShows9, "Dlr9"); engine.AddTerminalFunction(DealerShows10, "Dlr10"); engine.AddTerminalFunction(DealerShowsA, "DlrA"); // pass a fitness evaluation function and run engine.AddFitnessFunction((t) => EvaluateCandidate(t)); // and add something so we can track the progress engine.AddProgressFunction((t) => PerGenerationCallback(t)); Solution = engine.FindBestSolution(); Fitness = Solution.Fitness; FinalStatus = "Final Score: " + Fitness.ToString() + "\n" + "Generations needed to find: " + NumGenerationsNeeded; }
public override void SetCandidateRef(CandidateSolution <T, S> candidate) { ownerCandidate = candidate; }
public VariableNode(string varName, CandidateSolution <T, S> candidate) { variableName = varName; ownerCandidate = candidate; }
/** * Evolve the population. * @param pop The population. * @return The evolved population. */ private Population EvolvePopulation(Population population) { Array.Sort(population.CandidateSolutions, delegate(CandidateSolution x, CandidateSolution y) { if (x.Fitness > y.Fitness) { return(-1); } else if (x.Fitness < y.Fitness) { return(1); } return(0); }); Population matingPool = GenerateMatingPool(population); Population offsetSpringPopulation = new Population(fitnessCalculator, PopulationSize, BitSize, GenotypeLength, GroupSize); // Crossover operation. Random random = new Random(); for (int i = 0; i < offsetSpringPopulation.CandidateSolutions.Length; i++) { CandidateSolution child = null; var probability = random.NextDouble(); if (CrossoverProbability < probability) { child = matingPool.CandidateSolutions[i]; } else { CandidateSolution parent1 = matingPool.CandidateSolutions[i]; bool reject = true; int trial = 0; do { CandidateSolution parent2 = selection(matingPool); child = crossover(parent1, parent2); if (IsValid(child)) { reject = false; } else { trial++; } }while (reject && trial < 10); if (trial == 10) { child = parent1; } } offsetSpringPopulation.CandidateSolutions[i] = child; } // Mutation. for (int i = 0; i < offsetSpringPopulation.CandidateSolutions.Length; i++) { mutate(offsetSpringPopulation.CandidateSolutions[i]); } // Survivor selection Array.Sort(offsetSpringPopulation.CandidateSolutions, delegate(CandidateSolution x, CandidateSolution y) { if (x.Fitness > y.Fitness) { return(-1); } else if (x.Fitness < y.Fitness) { return(1); } return(0); }); Population newPopulation = new Population(fitnessCalculator, PopulationSize, BitSize, GenotypeLength, GroupSize); var parentCount = (int)(population.CandidateSolutions.Length * SurvivalProbability); var offsetSpringCount = (int)(offsetSpringPopulation.CandidateSolutions.Length * (1.0d - SurvivalProbability)); while (parentCount + offsetSpringCount < PopulationSize) { if (parentCount % 2 == 1) { parentCount++; } else { offsetSpringCount++; } } int counter = 0; for (int i = 0; i < newPopulation.CandidateSolutions.Length; i++) { if (i < parentCount) { newPopulation.CandidateSolutions[i] = population.CandidateSolutions[i]; } else { newPopulation.CandidateSolutions[i] = offsetSpringPopulation.CandidateSolutions[counter]; counter++; } } return(newPopulation); }