static int[,] Mutate(ASudokuGrid Grid) { ASudokuGrid MutatedGrid = new ASudokuGrid((int[, ])Grid.Grid.Clone()); List <int> GridGenes = new List <int>(); GridGenes = GetGridAsGenes(Grid.Grid); float OriginalFitness = Grid.fitness;//GridsFitness(Grid); bool HasMutated = false; //Swapping when we know it is safe, instead of just randomly switching or always swapping has helped the GA make progress significantly, as this helps prevent back tracking. if (rand.NextDouble() <= MutationRate) { while (!HasMutated) { //Mutate randomly int RandRowA = rand.Next(0, 9); int RandColA = rand.Next(0, 9); int RandRowB = rand.Next(0, 9); int RandColB = rand.Next(0, 9); while (RandColA == RandColB) { RandColA = rand.Next(0, 9); RandColB = rand.Next(0, 9); } //This is very important, since we ensure all made grids to start have no doubles, it won't be possible to swap items between two randomr rows, so instead do it in the same row at two random cols RandRowB = RandRowA; //Check if new value already exists in row. if (ProblemGrid.Grid[RandRowA, RandColA] == 0 && ProblemGrid.Grid[RandRowB, RandColB] == 0) { if ((!WillWeInsertDuplicateForCol(ProblemGrid, RandColA, MutatedGrid.Grid[RandRowB, RandColB]) && !WillWeInsertduplicateForSubgid(ProblemGrid, RandRowA, RandColA, MutatedGrid.Grid[RandRowB, RandColB])) && (!WillWeInsertDuplicateForCol(ProblemGrid, RandColB, MutatedGrid.Grid[RandRowA, RandColA]) && !WillWeInsertduplicateForSubgid(ProblemGrid, RandRowB, RandColB, MutatedGrid.Grid[RandRowA, RandColA]))) // && //(!WillWeInsertDuplicateForRow(MutatedGrid.Grid, RandRowA, Grid.Grid[RandRowB, RandColB]) && !WillWeInsertDuplicateForRow(MutatedGrid.Grid, RandRowB, Grid.Grid[RandRowA, RandColA]))) { //Safe to swap so swap Values at random spots. int AValue = MutatedGrid.Grid[RandRowA, RandColA]; MutatedGrid.Grid[RandRowA, RandColA] = MutatedGrid.Grid[RandRowB, RandColB]; MutatedGrid.Grid[RandRowB, RandColB] = AValue; HasMutated = true; NumberOfMutations++; } } } } if (DoesGridRowsHaveDoubles(MutatedGrid)) { Console.WriteLine("Why?"); } if (MutatedGrid.fitness > OriginalFitness && HasMutated) { Phi = Phi + 1; } return(MutatedGrid.Grid); }
static bool WillWeInsertDuplicateForCol(ASudokuGrid Grid, int ColToCheck, int value) { List <int> ColInts = new List <int>(); for (int x = 0; x < (Grid.Grid.GetLength(0)); ++x) { if (Grid.Grid[x, ColToCheck] == value) { return(true); } } return(false); }
static float BestFitnessInPopulation(bool DisplayGrid) { ASudokuGrid BestGrid = new ASudokuGrid(); List <ASudokuGrid> TempGridToSort = Population; TempGridToSort.Sort((SudokuGridA, SudokuGridB) => SudokuGridA.fitness.CompareTo(SudokuGridB.fitness)); BestGrid = TempGridToSort[0]; if (DisplayGrid) { PrintGrid(GridToString(BestGrid.Grid)); } return(BestGrid.fitness); }
public static void InitProblemGrid() { ProblemSudokuGrid = new int[9, 9] { { 5, 3, 0, 0, 7, 0, 0, 0, 0 }, { 6, 0, 0, 1, 9, 5, 0, 0, 0 }, { 0, 9, 8, 0, 0, 0, 0, 6, 0 }, { 8, 0, 0, 0, 6, 0, 0, 0, 3 }, { 4, 0, 0, 8, 0, 3, 0, 0, 1 }, { 7, 0, 0, 0, 2, 0, 0, 0, 6 }, { 0, 6, 0, 0, 0, 0, 2, 8, 0 }, { 0, 0, 0, 4, 1, 9, 0, 0, 5 }, { 0, 0, 0, 0, 8, 0, 0, 7, 9 } }; ProblemGrid = new ASudokuGrid(ProblemSudokuGrid); }
static ASudokuGrid TournamentSelection() { //List<ASudokuGrid> TempPopulation = new List<ASudokuGrid>(Population); //List<ASudokuGrid> FilteredPopulation = new List<ASudokuGrid>(); ASudokuGrid BestGrid = new ASudokuGrid(); // = null;// = new int[9,9]; ASudokuGrid CurrentGrid = new ASudokuGrid(); // = null; ASudokuGrid WeakestGrid = new ASudokuGrid(); // = null; float BestGridFitness = 1.0f; float WeakestGridFitness = 1.0f; for (int i = 0; i < k; i++) { //Randomly select from the population who is going to compete int randIndex = rand.Next(0, Population.Count - 1); CurrentGrid = Population[randIndex]; //TempPopulation.RemoveAt(randIndex); float CurrentGridFitness = CurrentGrid.fitness;//GridsFitness(CurrentGrid.Grid); if (BestGrid.Grid != null) { BestGridFitness = BestGrid.fitness;//GridsFitness(BestGrid.Grid); } if (BestGrid.Grid == null || CurrentGridFitness < BestGridFitness) { if (BestGrid.Grid != null) { WeakestGrid = new ASudokuGrid((int[, ])BestGrid.Grid.Clone()); } BestGrid = new ASudokuGrid((int[, ])CurrentGrid.Grid.Clone()); } else { WeakestGrid = new ASudokuGrid((int[, ])CurrentGrid.Grid.Clone()); BestGrid = new ASudokuGrid((int[, ])BestGrid.Grid.Clone()); } } if (rand.NextDouble() < SelectionRate) { return(new ASudokuGrid((int[, ])BestGrid.Grid.Clone())); } else { return(new ASudokuGrid((int[, ])WeakestGrid.Grid.Clone())); } }
//Bad because it can produce doubles static List <ASudokuGrid> MateViaCrossover(ASudokuGrid Mommy, ASudokuGrid Daddy) { List <int> MommyGenes = new List <int>(); List <int> DaddyGenes = new List <int>(); List <int> NewChildGenes1 = new List <int>(); List <int> NewChildGenes2 = new List <int>(); List <ASudokuGrid> Children = new List <ASudokuGrid>(); int[,] ChildGrid = new int[9, 9]; MommyGenes = GetGridAsGenes((int[, ])Mommy.Grid.Clone()); DaddyGenes = GetGridAsGenes((int[, ])Daddy.Grid.Clone()); if (rand.NextDouble() <= CrossoverRate) { int RandomCrossOverPoint = rand.Next(0, 80); NewChildGenes1.AddRange(MommyGenes.ToList().GetRange(0, RandomCrossOverPoint)); NewChildGenes1.AddRange(DaddyGenes.ToList().GetRange(RandomCrossOverPoint, ((DaddyGenes.Count) - RandomCrossOverPoint))); NewChildGenes2.AddRange(DaddyGenes.ToList().GetRange(0, RandomCrossOverPoint)); NewChildGenes2.AddRange(MommyGenes.ToList().GetRange(RandomCrossOverPoint, ((DaddyGenes.Count) - RandomCrossOverPoint))); Children.Add(new ASudokuGrid((int[, ])ConvertRawGenesToGrid(NewChildGenes1).Clone())); Children.Add(new ASudokuGrid((int[, ])ConvertRawGenesToGrid(NewChildGenes2).Clone())); } else { //Asexual reproduction Children.Add(new ASudokuGrid((int[, ])Mommy.Grid.Clone())); Children.Add(new ASudokuGrid((int[, ])Daddy.Grid.Clone())); } if (DoesGridRowsHaveDoubles(Children[0]) || DoesGridRowsHaveDoubles(Children[1])) { Children.Clear(); //Asexual reproduction Children.Add(new ASudokuGrid((int[, ])Mommy.Grid.Clone())); Children.Add(new ASudokuGrid((int[, ])Daddy.Grid.Clone())); } return(Children); }
static bool DoesGridRowsHaveDoubles(ASudokuGrid Grid) { List <int> RowInts = new List <int>(); for (int x = 0; x < (Grid.Grid.GetLength(0)); ++x) { for (int y = 0; y < (Grid.Grid.GetLength(1)); ++y) { RowInts.Add(Grid.Grid[x, y]); } if (RowInts.Count != RowInts.Distinct().Count()) { return(true); } RowInts.Clear(); } return(false); }
static bool DoesGridColHaveDuplicates(ASudokuGrid Grid) { List <int> ColInts = new List <int>(); //Count for rows and cols for (int x = 0; x < (Grid.Grid.GetLength(0)); ++x) { for (int y = 0; y < (Grid.Grid.GetLength(1)); ++y) { ColInts.Add(Grid.Grid[y, x]); } if (ColInts.Count != ColInts.Distinct().Count()) { return(true); } ColInts.Clear(); } return(false); }
static bool WillWeInsertduplicateForSubgid(ASudokuGrid Grid, int row, int col, int value) { int i = 3 * (int)(row / 3); int j = 3 * (int)(col / 3); if (Grid.Grid[i, j] == value || (Grid.Grid[i, j + 1] == value) || (Grid.Grid[i, j + 2] == value) || (Grid.Grid[i + 1, j] == value) || (Grid.Grid[i + 1, j + 1] == value) || (Grid.Grid[i + 1, j + 2] == value) || (Grid.Grid[i + 2, j] == value) || (Grid.Grid[i + 2, j + 1] == value) || (Grid.Grid[i + 2, j + 2] == value)) { return(true); } return(false); }
static bool DoesSubgridsHaveDuplicates(ASudokuGrid Grid) { List <List <int> > Subgrids = new List <List <int> >(); int YCounter = 1; int XCounter = 1; bool ContainsDuplicate = false; //May want/need to wrap into a method, this converts a 2D Grid into sub grids for a 9x9 grid. for (int SubgridIndex = 1; SubgridIndex <= 9; SubgridIndex++) { Subgrids.Add(new List <int>()); for (int x = ((Grid.Grid.GetLength(0) / 3) * XCounter) - (Grid.Grid.GetLength(0) / 3); x < (Grid.Grid.GetLength(0) / 3) * XCounter; ++x) { //Y Works well, do something for X now. for (int y = (Grid.Grid.GetLength(1) - (3 * (3 - YCounter))) - 3; y < (Grid.Grid.GetLength(1) - (3 * (3 - YCounter))); ++y) { Subgrids[Subgrids.Count - 1].Add(Grid.Grid[x, y]); } } if (SubgridIndex % 3 == 0) { YCounter = 1; XCounter++; } else { YCounter++; } } //Count doubles for subgrids Subgrids.ForEach(SubGrid => { if (SubGrid.Count != SubGrid.Distinct().Count()) { ContainsDuplicate = true; } }); return(ContainsDuplicate); }
public static void InitProblemGridWithOCR() { ProblemSudokuGrid = new int[9, 9]; NewPuzzle = SudokuPuzzle.Create(3, 3, 30); NewPuzzle.GetNodes().ToList().ForEach(Node => { if (Node.Value == -1) { ProblemSudokuGrid[Node.Line, Node.Column] = 0; } else { ProblemSudokuGrid[Node.Line, Node.Column] = Node.Value; } }); ProblemGrid = new ASudokuGrid(ProblemSudokuGrid); Console.WriteLine("Press any key to have GA solve this grid."); PrintGrid(GridToString(ProblemGrid.Grid)); Console.ReadKey(); }
//static List<ASudokuGrid> MateViaCrossoverCycle(ASudokuGrid Mommy, ASudokuGrid Daddy) //{ // List<int> MommyGenes = new List<int>(); // List<int> DaddyGenes = new List<int>(); // MommyGenes = GetGridAsGenes(Mommy.Grid); // DaddyGenes = GetGridAsGenes(Daddy.Grid); // List<int> NewChildGenes1 = MommyGenes; // List<int> NewChildGenes2 = DaddyGenes; // List<ASudokuGrid> Children = new List<ASudokuGrid>(); // List<int> NewRow1 = new List<int>(); // List<int> NewRow2 = new List<int>(); // int P1 = 1; // int P2 = 1; // int StopPoint = 0; // for (int i = 0; i < 9; i++) // { // if() // P2 = Mommy.Grid[0, P1 - 1]; // NewRow1.Add(P2); // P1 = Daddy.Grid[0, P2 - 1]; // NewRow2.Add(P1); // P1 = P2; // } // return Children; //} static List <ASudokuGrid> MateViaCrossoverCycle(ASudokuGrid Mommy, ASudokuGrid Daddy) { List <int> MommyGenes = new List <int>(); List <int> DaddyGenes = new List <int>(); MommyGenes = GetGridAsGenes(Mommy.Grid); DaddyGenes = GetGridAsGenes(Daddy.Grid); List <int> NewChildGenes1 = MommyGenes; List <int> NewChildGenes2 = DaddyGenes; ASudokuGrid Child1 = new ASudokuGrid((int[, ])Mommy.Grid.Clone()); ASudokuGrid Child2 = new ASudokuGrid((int[, ])Daddy.Grid.Clone()); List <int> Child1Row = new List <int>(); List <int> Child2Row = new List <int>(); List <ASudokuGrid> Children = new List <ASudokuGrid>(); if (rand.NextDouble() <= CrossoverRate) { int CrossoverPoint_1 = rand.Next(0, 8); int CrossoverPoint_2 = rand.Next(1, 9); //Idea seems to be to pick a point a and b crossover range, ex. 0 - 9 or 4 - 5 //Can't have them equal that wouldn't be a range. while (CrossoverPoint_1 == CrossoverPoint_2) { CrossoverPoint_1 = rand.Next(0, 8); CrossoverPoint_2 = rand.Next(1, 9); } //need 1 to be the starting point (min in range) so if it is larger than 2 swap. if (CrossoverPoint_1 > CrossoverPoint_2) { int temp = CrossoverPoint_1; CrossoverPoint_1 = CrossoverPoint_2; CrossoverPoint_2 = temp; } for (int i = CrossoverPoint_1; i < CrossoverPoint_2; i++) { //Reset for next row/attempt Child1Row.Clear(); Child2Row.Clear(); //Pluck rows out in C# fashion for (int y = 0; y < 9; y++) { Child1Row.Add(Child1.Grid[i, y]); Child2Row.Add(Child2.Grid[i, y]); } if (Child1Row.Count != Child1Row.Distinct().Count() || Child2Row.Count != Child2Row.Distinct().Count()) { //Console.Write("Why"); } //Crossover Rows in Cycle Fashion List <List <int> > RowsCrossed = CrossoverRows(Child1Row, Child2Row); //Child1Row = RowsCrossed[0]; //Child2Row = RowsCrossed[1]; //Put crossed rows back in to their slots, make check here to not replace known values from original grid for (int y = 0; y < 9; y++) { if (!AnsweredPosition.Exists(pos => pos.Item1 == i && pos.Item2 == y)) { Child1.Grid[i, y] = RowsCrossed[0][y]; Child2.Grid[i, y] = RowsCrossed[1][y]; } } } } //Children[0].UpdateFitness(); //Children[1].UpdateFitness(); Children.Add(Child1); Children.Add(Child2); //Return Crossed Children return(Children); }