public Core.Sudoku SolveCombinatorial(Core.Sudoku s)
        {
            var sudokuTab = (Core.Sudoku)s.Clone();

            Console.WriteLine("Begin solving Sudoku using combinatorial evolution");
            Console.WriteLine("The Sudoku is:");

            var sudoku = CombinatorialSudoku.Convert(sudokuTab);

            const int numOrganisms = 200;
            const int maxEpochs    = 5000;
            const int maxRestarts  = 40;

            Console.WriteLine($"Setting numOrganisms: {numOrganisms}");
            Console.WriteLine($"Setting maxEpochs: {maxEpochs}");
            Console.WriteLine($"Setting maxRestarts: {maxRestarts}");

            var solver       = new CombinatorialSudokuSolver();
            var solvedSudoku = solver.Solve(sudoku, numOrganisms, maxEpochs, maxRestarts);

            Console.WriteLine(solvedSudoku.Error == 0 ? "Success" : "Did not find optimal solution");
            Console.WriteLine("End Sudoku using combinatorial evolution");
            var solution = ConvertSolution(solvedSudoku);

            return(solution);
        }
        public Core.Sudoku ConvertSolution(CombinatorialSudoku sudoku)
        {
            var list = new List <int> {
            };

            for (int row = 1; row <= 9; row++)
            {
                for (int column = 1; column <= 9; column++)
                {
                    list.Add(sudoku.CellValues[row - 1, column - 1]);
                }
            }
            var output = new Core.Sudoku(list);

            return(output);
        }
Beispiel #3
0
        public CombinatorialSudoku Solve(CombinatorialSudoku sudoku, int numOrganisms, int maxEpochs, int maxRestarts)
        {
            var error = int.MaxValue;
            CombinatorialSudoku bestSolution = null;
            var attempt = 0;

            while (error != 0 && attempt < maxRestarts)
            {
                Console.WriteLine($"Attempt: {attempt}, {numOrganisms} individuals");
                _rnd          = new Random(attempt);
                bestSolution  = SolveInternal(sudoku, numOrganisms, maxEpochs);
                error         = bestSolution.Error;
                numOrganisms += numOrganisms / 10;
                ++attempt;
            }

            return(bestSolution);
        }
Beispiel #4
0
        private CombinatorialSudoku SolveInternal(CombinatorialSudoku sudoku, int numOrganisms, int maxEpochs)
        {
            var numberOfWorkers = (int)(numOrganisms * 0.90);
            var hive            = new Organism[numOrganisms];

            var bestError = int.MaxValue;
            CombinatorialSudoku bestSolution = null;

            for (var i = 0; i < numOrganisms; ++i)
            {
                var organismType = i < numberOfWorkers
          ? OrganismType.Worker
          : OrganismType.Explorer;

                var randomSudoku = CombinatorialSudoku.New(MatrixHelper.RandomMatrix(_rnd, sudoku.CellValues));
                var err          = randomSudoku.Error;

                hive[i] = new Organism(organismType, randomSudoku.CellValues, err, 0);

                if (err >= bestError)
                {
                    continue;
                }
                bestError    = err;
                bestSolution = CombinatorialSudoku.New(randomSudoku);
            }

            var epoch = 0;

            while (epoch < maxEpochs)
            {
                if (epoch % 1000 == 0)
                {
                    Console.WriteLine($"Epoch: {epoch}, Best error: {bestError}");
                }

                if (bestError == 0)
                {
                    break;
                }

                for (var i = 0; i < numOrganisms; ++i)
                {
                    if (hive[i].Type == OrganismType.Worker)
                    {
                        var neighbor       = MatrixHelper.NeighborMatrix(_rnd, sudoku.CellValues, hive[i].Matrix);
                        var neighborSudoku = CombinatorialSudoku.New(neighbor);
                        var neighborError  = neighborSudoku.Error;

                        var p = _rnd.NextDouble();
                        if (neighborError < hive[i].Error || p < 0.001)
                        {
                            hive[i].Matrix = MatrixHelper.DuplicateMatrix(neighbor);
                            hive[i].Error  = neighborError;
                            if (neighborError < hive[i].Error)
                            {
                                hive[i].Age = 0;
                            }

                            if (neighborError >= bestError)
                            {
                                continue;
                            }
                            bestError    = neighborError;
                            bestSolution = neighborSudoku;
                        }
                        else
                        {
                            hive[i].Age++;
                            if (hive[i].Age <= 1000)
                            {
                                continue;
                            }
                            var randomSudoku = CombinatorialSudoku.New(MatrixHelper.RandomMatrix(_rnd, sudoku.CellValues));
                            hive[i] = new Organism(0, randomSudoku.CellValues, randomSudoku.Error, 0);
                        }
                    }
                    else
                    {
                        var randomSudoku = CombinatorialSudoku.New(MatrixHelper.RandomMatrix(_rnd, sudoku.CellValues));
                        hive[i].Matrix = MatrixHelper.DuplicateMatrix(randomSudoku.CellValues);
                        hive[i].Error  = randomSudoku.Error;

                        if (hive[i].Error >= bestError)
                        {
                            continue;
                        }
                        bestError    = hive[i].Error;
                        bestSolution = randomSudoku;
                    }
                }

                // merge best worker with best explorer into worst worker
                var bestWorkerIndex     = 0;
                var smallestWorkerError = hive[0].Error;
                for (var i = 0; i < numberOfWorkers; ++i)
                {
                    if (hive[i].Error >= smallestWorkerError)
                    {
                        continue;
                    }
                    smallestWorkerError = hive[i].Error;
                    bestWorkerIndex     = i;
                }

                var bestExplorerIndex     = numberOfWorkers;
                var smallestExplorerError = hive[numberOfWorkers].Error;
                for (var i = numberOfWorkers; i < numOrganisms; ++i)
                {
                    if (hive[i].Error >= smallestExplorerError)
                    {
                        continue;
                    }
                    smallestExplorerError = hive[i].Error;
                    bestExplorerIndex     = i;
                }

                var worstWorkerIndex   = 0;
                var largestWorkerError = hive[0].Error;
                for (var i = 0; i < numberOfWorkers; ++i)
                {
                    if (hive[i].Error <= largestWorkerError)
                    {
                        continue;
                    }
                    largestWorkerError = hive[i].Error;
                    worstWorkerIndex   = i;
                }

                var merged       = MatrixHelper.MergeMatrices(_rnd, hive[bestWorkerIndex].Matrix, hive[bestExplorerIndex].Matrix);
                var mergedSudoku = CombinatorialSudoku.New(merged);

                hive[worstWorkerIndex] = new Organism(0, merged, mergedSudoku.Error, 0);
                if (hive[worstWorkerIndex].Error < bestError)
                {
                    bestError    = hive[worstWorkerIndex].Error;
                    bestSolution = mergedSudoku;
                }

                ++epoch;
            }

            return(bestSolution);
        }
 public static CombinatorialSudoku New(CombinatorialSudoku sudoku)
 {
     return(new CombinatorialSudoku(MatrixHelper.DuplicateMatrix(sudoku.CellValues)));
 }