public Core.Sudoku Solve(Core.Sudoku s)
        {
            var internalRows = BuildInternalRowsForSudoku(s);
            var dlxRows      = BuildDlxRows(internalRows);
            var solutions    = _dlx
                               .Solve(dlxRows, d => d, r => r)
                               //.Where(solution => VerifySolution(internalRows, solution))
                               .ToImmutableList();

            //Console.WriteLine();

            if (solutions.Any())
            {
                Console.WriteLine($"First solution (of {solutions.Count}):");
                Console.WriteLine();


                return(SolutionToSudoku(internalRows, solutions.First()));
            }
            else
            {
                Console.WriteLine("No solutions found!");
            }

            return(null);
        }
        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 Solve(Core.Sudoku s)
        {
            var toReturn = SolveCombinatorial(s);


            return(toReturn);
        }
Exemple #4
0
 /// <summary>
 /// Constructor that accepts a Sudoku to solve
 /// </summary>
 /// <param name="targetCore.Sudoku">the target sudoku to solve</param>
 public SudokuCellsChromosome(Core.Sudoku targetSudoku) : base(81)
 {
     _targetSudoku = targetSudoku;
     for (int i = 0; i < Length; i++)
     {
         ReplaceGene(i, GenerateGene(i));
     }
 }
        public Core.Sudoku Solve(Core.Sudoku s)
        {
            //var toReturn = SolveCombinatorial(s);

            var toReturn = SolveGeneticSharp(s);

            return(toReturn);
        }
Exemple #6
0
 /// <summary>
 /// Constructor with a mask and a number of genes
 /// </summary>
 /// <param name="targetCore.Sudoku">the target sudoku to solve</param>
 /// <param name="length">the number of genes</param>
 public SudokuPermutationsChromosome(Core.Sudoku targetSudoku, int length) : base(length)
 {
     TargetSudoku           = targetSudoku;
     TargetRowsPermutations = GetRowsPermutations(TargetSudoku);
     for (int i = 0; i < Length; i++)
     {
         ReplaceGene(i, GenerateGene(i));
     }
 }
Exemple #7
0
        public Core.Sudoku Solve(Core.Sudoku s)
        {
            var solution = (Core.Sudoku)s.Clone();
            var model    = BaseModel.LoadModel(DataSetHelper.GetFullPath(@"Sudoku.NeuralNetwork\Models\sudoku.model"));

            solution = Model.SolveSudoku(solution, model);
            Console.WriteLine(solution);

            return(solution);
        }
Exemple #8
0
        /// <summary>
        /// Evaluates a single Sudoku board by counting the duplicates in rows, boxes
        /// and the digits differing from the target mask.
        /// </summary>
        /// <param name="testSudoku">the board to evaluate</param>
        /// <returns>the number of mistakes the Sudoku contains.</returns>
        public double Evaluate(Core.Sudoku testSudoku)
        {
            var cells  = testSudoku.Cells.Select((c, i) => new { index = i, cell = c }).ToList();
            var toTest = cells.GroupBy(x => x.index / 9).Select(g => g.Select(c => c.cell))                                       // rows
                         .Concat(cells.GroupBy(x => x.index % 9).Select(g => g.Select(c => c.cell)))                              //columns
                         .Concat(cells.GroupBy(x => x.index / 27 * 27 + x.index % 9 / 3 * 3).Select(g => g.Select(c => c.cell))); //boxes
            var toReturn = -toTest.Sum(test => test.GroupBy(x => x).Select(g => g.Count() - 1).Sum());

            toReturn -= cells.Count(x => _targetSudoku.Cells[x.index] > 0 && _targetSudoku.Cells[x.index] != x.cell);
            return(toReturn);
        }
Exemple #9
0
 // Récupération de la solution
 public static void SetValuesFromAssignment(Assignment a, Core.Sudoku s)
 {
     foreach (Variable objVar in a.getVariables().toArray())
     {
         int rowIdx = 0;
         int colIdx = 0;
         GetIndices(objVar, ref rowIdx, ref colIdx);
         int value = (int)a.getAssignment(objVar);
         s.SetCell(rowIdx, colIdx, value);
     }
 }
Exemple #10
0
        // Fonction principale pour construire le CSP à partir d'un masque de Sudoku à résoudre
        public static CSP GetSudokuCSP(Core.Sudoku s)
        {
            //initialisation à l'aide des contraintes communes

            var toReturn = GetSudokuBaseCSP();


            // Ajout des contraintes spécifiques au masque fourni

            //var sArray = s.getInitialSudoku();
            var cellVars = toReturn.getVariables();


            //récupération du masque
            var mask = new Dictionary <int, int>();

            for (int i = 0; i < 9; i++)
            {
                for (int j = 0; j < 9; j++)
                {
                    var cellVal = s.GetCell(i, j);
                    if (cellVal != 0)
                    {
                        mask[i * 9 + j] = cellVal;
                    }
                }
            }

            //Ajout des contraintes de masque en faisant défiler les variables existantes

            var maskQueue = new Queue <int>(mask.Keys);

            var currentMaskIdx = maskQueue.Dequeue();
            var currentVarName = GetVarName(currentMaskIdx / 9, currentMaskIdx % 9);

            foreach (Variable objVar in cellVars.toArray())
            {
                if (objVar.getName() == currentVarName)
                {
                    //toReturn.addConstraint(new ValueConstraint(objVar, mask[currentMaskIdx]));
                    var cellValue = mask[currentMaskIdx];
                    toReturn.setDomain(objVar, new Domain(new object[] { cellValue }));
                    if (maskQueue.Count == 0)
                    {
                        break;
                    }
                    currentMaskIdx = maskQueue.Dequeue();
                    currentVarName = GetVarName(currentMaskIdx / 9, currentMaskIdx % 9);
                }
            }

            return(toReturn);
        }
Exemple #11
0
        /// <summary>
        /// Evaluates a single Sudoku board by counting the duplicates in rows, boxes
        /// and the digits differing from the target mask.
        /// </summary>
        /// <param name="testSudoku">the board to evaluate</param>
        /// <returns>the number of mistakes the Sudoku contains.</returns>
        public double Evaluate(Core.Sudoku testSudoku)
        {
            // We use a large lambda expression to count duplicates in rows, columns and boxes
            var cells  = testSudoku.Cells.Select((c, i) => new { index = i, cell = c }).ToList();
            var toTest = cells.GroupBy(x => x.index / 9).Select(g => g.Select(c => c.cell))                                       // rows
                         .Concat(cells.GroupBy(x => x.index % 9).Select(g => g.Select(c => c.cell)))                              //columns
                         .Concat(cells.GroupBy(x => x.index / 27 * 27 + x.index % 9 / 3 * 3).Select(g => g.Select(c => c.cell))); //boxes
            var toReturn = -toTest.Sum(test => test.GroupBy(x => x).Select(g => g.Count() - 1).Sum());                            // Summing over duplicates

            toReturn -= cells.Count(x => _targetSudoku.Cells[x.index] > 0 && _targetSudoku.Cells[x.index] != x.cell);             // Mask
            return(toReturn);
        }
Exemple #12
0
        /// <summary>
        /// builds a single Sudoku from the given row permutation genes
        /// </summary>
        /// <returns>a list with the single Sudoku built from the genes</returns>
        public virtual IList <Core.Sudoku> GetSudokus()
        {
            var listInt = new List <int>(81);

            for (int i = 0; i < 9; i++)
            {
                var perm = GetPermutation(i);
                listInt.AddRange(perm);
            }
            var sudoku = new Core.Sudoku(listInt);

            return(new List <Core.Sudoku>(new[] { sudoku }));
        }
        public static Core.Sudoku SolveSudoku(Core.Sudoku s, BaseModel model)
        {
            NDarray sFeatures = np.array(s.Cells.ToArray()).reshape(9, 9);

            sFeatures = (sFeatures / 9) - 0.5;

            var prediction = Solve(sFeatures, model);

            return(new Core.Sudoku()
            {
                Cells = prediction.flatten().astype(np.int32).GetData <int>().ToList()
            });
        }
        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);
        }
Exemple #15
0
            public Core.Sudoku Solve(Core.Sudoku s)
            {
                //Construction du CSP

                var objCSP = SudokuCSPHelper.GetSudokuCSP(s);

                // Résolution du Sudoku
                var objChrono   = Stopwatch.StartNew();
                var assignation = _Strategy.solve(objCSP);

                Console.WriteLine($"Pure solve Time : {objChrono.Elapsed.TotalMilliseconds} ms");


                //Traduction du Sudoku
                SudokuCSPHelper.SetValuesFromAssignment(assignation, s);

                return(s);
            }
Exemple #16
0
        private void Run()
        {
            Inputs = new int[Core.Sudoku.SIZE, Core.Sudoku.SIZE];

            for (int y = 0; y < Core.Sudoku.SIZE; y++)
            {
                System.Console.Out.WriteLine($"Enter line {y + 1}, followed by enter key");
                for (int x = 0; x < Core.Sudoku.SIZE; x++)
                {
                    while (true)
                    {
                        int key    = System.Console.Read();
                        var number = key - 48;
                        if (number >= 0 && number <= 9)
                        {
                            Inputs[x, y] = number;
                            break;
                        }
                    }
                }
            }

            // var transposedInput = new int[Core.Sudoku.SIZE, Core.Sudoku.SIZE];
            // for (var i = 0; i < Core.Sudoku.SIZE; i++)
            // {
            //     for (var j = 0; j < Core.Sudoku.SIZE; j++)
            //     {
            //         transposedInput[i, j] = Inputs[j, i];
            //     }
            // }

            for (int y = 0; y < 9; y++)
            {
                for (int x = 0; x < 9; x++)
                {
                    System.Console.Out.Write($"{Inputs[x, y]}".PadRight(10, ' '));
                }

                System.Console.Out.WriteLine();
            }

            _sudoku = new Core.Sudoku(this);
            _sudoku.Solve();
        }
        public Core.Sudoku SolveWithTimeLimit(Core.Sudoku puzzle, TimeSpan maxDuration)
        {
            try
            {
                Core.Sudoku toReturn = null;

                Task task = Task.Factory.StartNew(() => toReturn = Solver.Solve(puzzle.CloneSudoku()));
                task.Wait(maxDuration);
                if (!task.IsCompleted)
                {
                    throw new ApplicationException($"Solver {ToString()} has exceeded the maximum allowed duration {maxDuration.TotalSeconds} seconds");
                }
                return(toReturn);
            }
            catch (AggregateException ae)
            {
                throw ae.InnerExceptions[0];
            }
        }
Exemple #18
0
        private IList <IList <IList <int> > > GetRowsPermutationsUncached(Core.Sudoku objSudoku)
        {
            var toReturn = new List <IList <IList <int> > >(9);

            for (int i = 0; i < 9; i++)
            {
                var tempList = new List <IList <int> >();
                foreach (var perm in AllPermutations)
                {
                    // Permutation should match current mask row numbers, and have numbers different that other mask rows
                    if (!Range9.Any(rowIdx => Range9.Any(j => objSudoku.GetCell(rowIdx, j) > 0 &&
                                                         ((rowIdx == i && perm[j] != objSudoku.GetCell(rowIdx, j)) || (rowIdx != i && perm[j] == objSudoku.GetCell(rowIdx, j))))))
                    {
                        tempList.Add(perm);
                    }
                }
                toReturn.Add(tempList);
            }

            return(toReturn);
        }
Exemple #19
0
        /// <summary>
        /// This method computes for each row the list of digit permutations that respect the target mask, that is the list of valid rows discarding columns and boxes
        /// </summary>
        /// <param name="Core.Sudoku">the target sudoku to account for</param>
        /// <returns>the list of permutations available</returns>
        public IList <IList <IList <int> > > GetRowsPermutations(Core.Sudoku objSudoku)
        {
            if (objSudoku == null)
            {
                return(UnfilteredPermutations);
            }

            // we store permutations to compute them once only for each target Sudoku
            if (!_rowsPermutations.TryGetValue(objSudoku, out var toReturn))
            {
                // Since this is a static member we use a lock to prevent parallelism.
                // This should be computed once only.
                lock (_rowsPermutations)
                {
                    if (!_rowsPermutations.TryGetValue(objSudoku, out toReturn))
                    {
                        toReturn = GetRowsPermutationsUncached(objSudoku);
                        _rowsPermutations[objSudoku] = toReturn;
                    }
                }
            }
            return(toReturn);
        }
        public static CombinatorialSudoku Convert(Core.Sudoku sudoku)
        {
            var problem = new[, ]
            {
                { 0, 0, 7, 0, 0, 2, 9, 3, 0 },
                { 0, 8, 1, 0, 0, 0, 0, 0, 5 },
                { 9, 0, 4, 7, 0, 0, 1, 6, 0 },
                { 0, 1, 0, 8, 0, 0, 0, 0, 6 },
                { 8, 4, 6, 0, 0, 0, 5, 9, 2 },
                { 5, 0, 0, 0, 0, 6, 0, 1, 0 },
                { 0, 9, 2, 0, 0, 8, 3, 0, 1 },
                { 4, 0, 0, 0, 0, 0, 6, 5, 0 },
                { 0, 6, 5, 4, 0, 0, 2, 0, 0 }
            };

            for (int row = 1; row <= 9; row++)
            {
                for (int column = 1; column <= 9; column++)
                {
                    problem[row - 1, column - 1] = sudoku.GetCell(row - 1, column - 1);
                }
            }
            return(new CombinatorialSudoku(problem));
        }
Exemple #21
0
 private void btnSolve_Click(object sender, System.EventArgs e)
 {
     txtStatus.Text = string.Empty;
     _sudoku        = new Core.Sudoku(this);
     _sudoku.Solve();
 }
Exemple #22
0
        /// <summary>
        /// Builds a single Sudoku from the 81 genes
        /// </summary>
        /// <returns>A Sudoku board built from the 81 genes</returns>
        public IList <Core.Sudoku> GetSudokus()
        {
            var sudoku = new Core.Sudoku(GetGenes().Select(g => (int)g.Value));

            return(new List <Core.Sudoku>(new[] { sudoku }));
        }
        private static IImmutableList <Tuple <int, int, int, bool> > BuildInternalRowsForSudoku(Core.Sudoku s)
        {
            var rowsByCols =
                from row in Rows
                from col in Cols
                let value = s.GetCell(row, col)
                            select BuildInternalRowsForCell(row, col, value);

            return(rowsByCols.SelectMany(cols => cols).ToImmutableList());
        }
Exemple #24
0
 /// <summary>
 /// Constructor with a mask sudoku to solve, assuming a length of 9 genes
 /// </summary>
 /// <param name="targetCore.Sudoku">the target sudoku to solve</param>
 public SudokuPermutationsChromosome(Core.Sudoku targetSudoku) : this(targetSudoku, 9)
 {
 }
        public Core.Sudoku SolveGeneticSharp(Core.Sudoku s)
        {
            var         populationSize   = 5000;
            IChromosome sudokuChromosome = new SudokuPermutationsChromosome(s);
            //IChromosome sudokuChromosome = new SudokuCellsChromosome(s);
            var fitnessThreshold     = 0;
            var crossoverProbability = 0.75f;
            var mutationProbability  = 0.2f;
            var fitness   = new SudokuFitness(s);
            var selection = new EliteSelection();
            var crossover = new UniformCrossover();
            var mutation  = new UniformMutation();

            IChromosome bestIndividual;
            var         solution = s;
            int         nbErrors = int.MaxValue;


            do
            {
                var population = new Population(populationSize, populationSize, sudokuChromosome);
                var ga         = new GeneticAlgorithm(population, fitness, selection, crossover, mutation)
                {
                    Termination = new OrTermination(new ITermination[]
                    {
                        new FitnessThresholdTermination(fitnessThreshold),
                        new FitnessStagnationTermination(10),
                        //new GenerationNumberTermination(generationNb)
                        //new TimeEvolvingTermination(TimeSpan.FromSeconds(10)),
                    }),
                    MutationProbability  = mutationProbability,
                    CrossoverProbability = crossoverProbability,
                    OperatorsStrategy    = new TplOperatorsStrategy(),
                };
                ga.GenerationRan += delegate(object sender, EventArgs args)
                {
                    bestIndividual = (ga.Population.BestChromosome);
                    solution       = ((ISudokuChromosome)bestIndividual).GetSudokus()[0];
                    nbErrors       = solution.NbErrors(s);
                    Console.WriteLine($"Generation #{ga.GenerationsNumber}: best individual has {nbErrors} errors");
                };
                ga.Start();

                //bestIndividual = (ga.Population.BestChromosome);
                //solution = ((ISudokuChromosome)bestIndividual).GetSudokus()[0];
                //nbErrors = solution.NbErrors(s);
                if (nbErrors == 0)
                {
                    break;
                }
                else
                {
                    populationSize *= 2;
                    Console.WriteLine($"Genetic search failed with {nbErrors} resulting errors, doubling population to {populationSize}");
                }
            } while (true);



            return(solution);
        }
        public Core.Sudoku Solve(Core.Sudoku s)
        {
            var toReturn = SolveGeneticSharp(s);

            return(toReturn);
        }
Exemple #27
0
 public SudokuFitness(Core.Sudoku targetSudoku)
 {
     _targetSudoku = targetSudoku;
 }
        public static (BaseModel model, double accuracy) TrainAndTest(BaseModel model)
        {
            // Global parameters
            string datasetPath = @"Sudoku.NeuralNetwork\Dataset\sudoku.csv.gz";
            int    numSudokus  = 1000;

            // ML parameters
            double testPercent  = 0.2;
            float  learningRate = .001F;
            int    batchSize    = 32;
            int    epochs       = 2;

            Console.WriteLine("Initialize dataset");
            var(sPuzzles, sSols) = DataSetHelper.ParseCSV(datasetPath, numSudokus);
            var(_sPuzzzlesTrain, _sPuzzlesTest) = DataSetHelper.SplitDataSet(sPuzzles, testPercent);
            var(_sSolsTrain, _sSolsTest)        = DataSetHelper.SplitDataSet(sSols, testPercent);

            Console.WriteLine("Preprocess data");
            var sPuzzzlesTrain = DataSetHelper.PreprocessSudokus(_sPuzzzlesTrain);
            var sSolsTrain     = DataSetHelper.PreprocessSudokus(_sSolsTrain);
            var sPuzzlesTest   = DataSetHelper.PreprocessSudokus(_sPuzzlesTest);
            var sSolsTest      = DataSetHelper.PreprocessSudokus(_sSolsTest);

            // Add optimizer
            var adam = new Keras.Optimizers.Adam(learningRate);

            model.Compile(loss: "sparse_categorical_crossentropy", optimizer: adam);

            Console.WriteLine("Train model");
            model.Fit(sPuzzzlesTrain, sSolsTrain, batch_size: batchSize, epochs: epochs);

            // Test model
            int correct = 0;

            for (int i = 0; i < 1; i++)
            {
                Console.WriteLine("Testing " + i);

                // Predict result
                var prediction = Solve(sPuzzlesTest[i], model);

                // Convert to sudoku
                var sPredict = new Core.Sudoku()
                {
                    Cells = prediction.flatten().astype(np.int32).GetData <int>().ToList()
                };
                var sSol = new Core.Sudoku()
                {
                    Cells = ((sSolsTest[i] + 0.5) * 9).flatten().astype(np.int32).GetData <int>().ToList()
                };

                // Compare sudoku
                var same = true;
                for (int j = 0; j < 9; j++)
                {
                    for (int k = 0; k < 9; k++)
                    {
                        if (sPredict.GetCell(j, k) != sSol.GetCell(j, k))
                        {
                            same = false;
                        }
                    }
                }
                Console.WriteLine("Prediction : \n" + sPredict);
                Console.WriteLine("Solution : \n" + sSol);

                if (same)
                {
                    correct += 1;
                }
            }

            // Calculate accuracy
            var accuracy = (correct / sPuzzlesTest.size) * 100;

            // Return
            return(model, accuracy);
        }
 public Core.Sudoku Solve(Core.Sudoku s)
 {
     return(s);
 }