예제 #1
0
파일: Program.cs 프로젝트: nonlin/SudokuGA
        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);
        }
예제 #2
0
파일: Program.cs 프로젝트: nonlin/SudokuGA
        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);
        }
예제 #3
0
파일: Program.cs 프로젝트: nonlin/SudokuGA
        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);
        }
예제 #4
0
파일: Program.cs 프로젝트: nonlin/SudokuGA
 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);
 }
예제 #5
0
파일: Program.cs 프로젝트: nonlin/SudokuGA
        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()));
            }
        }
예제 #6
0
파일: Program.cs 프로젝트: nonlin/SudokuGA
        //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);
        }
예제 #7
0
파일: Program.cs 프로젝트: nonlin/SudokuGA
        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);
        }
예제 #8
0
파일: Program.cs 프로젝트: nonlin/SudokuGA
        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);
        }
예제 #9
0
파일: Program.cs 프로젝트: nonlin/SudokuGA
        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);
        }
예제 #10
0
파일: Program.cs 프로젝트: nonlin/SudokuGA
        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);
        }
예제 #11
0
파일: Program.cs 프로젝트: nonlin/SudokuGA
        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();
        }
예제 #12
0
파일: Program.cs 프로젝트: nonlin/SudokuGA
        //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);
        }