コード例 #1
0
        public bool Resolve(GrilleSudoku s)            // La fonction solve va pemettre de choisir la solution valide satsifaisant les contraintes de sodoku
        {
            for (int ligne = 0; ligne < Size; ligne++) // parcourt les lignes
            {
                for (int col = 0; col < Size; col++)   // parcourt les colonnes
                {
                    // Ce double for parcourt chaque colonne pour une ligne donnée
                    if (s.GetCellule(ligne, col) == 0)           // empty: si la cellule est vide alors on va rentrer dans la boucle for
                    {
                        for (int value = 1; value <= 9; value++) // qui va tester les valeur de 1 à 9
                        {
                            if (IsValid(s, ligne, col, value))   // Si la valeur est valide avec les conditions de validité qu'on va définirapres dans le code
                            {
                                s.SetCell(ligne, col, value);    // Alors on remplie la case vide avec la valeur valide

                                if (Resolve(s))                  // Et on appelle la fonction elle-meme pour la récursivité : Principe de backtracking
                                {
                                    return(true);                // On on valide la solution
                                }
                                else
                                {
                                    s.SetCell(ligne, col, 0);  // Sinon on réinitialise la valeur à 0
                                }
                            }
                        }

                        return(false); // On refait le même processus
                    }
                }
            }

            return(true); // Jusqu'à ce qu'on trouve une solution valide et on la garde
        }
コード例 #2
0
        public void AC3(GrilleSudoku s, List <List <int> > possibilites)
        {
            bool test = true;
            int  CaseCheck;

            while (test)
            {
                test = false;
                for (int i = 0; i < 81; i++)
                {
                    if (possibilites[i].Count == 1 && possibilites[i][0] != 10)
                    {
                        test = true;
                    }
                }
                if (test == true)
                {
                    CaseCheck = getNextMRV(possibilites);

                    //AC3 ETAPE : 1
                    //Nb Possibilites = 1
                    if (possibilites[CaseCheck].Count == 1)
                    {
                        s.SetCell(CaseCheck / 9, CaseCheck % 9, possibilites[CaseCheck][0]);
                        DeletePossibilites(s, possibilites, CaseCheck, possibilites[CaseCheck][0]);
                    }
                }
            }
        }
コード例 #3
0
        public void assign(GrilleSudoku s, int cell, int value, List <int> assignment, List <List <int> > possibilites, List <List <int> > pruned)
        {
            assignment.Add(cell);
            s.SetCell(cell / 9, cell % 9, value);

            if (possibilites[cell].Contains(value))
            {
                possibilites[cell].Remove(value);
            }

            if (!pruned[cell].Contains(value))
            {
                pruned[cell].Add(value);
            }

            if (possibilites[cell].Count == 0)
            {
                possibilites[cell].Add(10);
            }

            // supp la Valeur des Possibilités des Voisins de la Cellule
            foreach (int neighboor_value in Cell_Neighboor(s, cell))
            {
                if (possibilites[neighboor_value].Contains(value))
                {
                    possibilites[neighboor_value].Remove(value);
                }
                if (!pruned[neighboor_value].Contains(value))
                {
                    pruned[neighboor_value].Add(value);
                }
            }
        }
コード例 #4
0
        public void Solve(GrilleSudoku s)
        {
            List <List <int> > list_cell = new List <List <int> >();

            foreach (var i in System.Linq.Enumerable.Range(0, 9))
            {
                var ligne = new List <int>(9);
                list_cell.Add(ligne);
                foreach (var j in System.Linq.Enumerable.Range(0, 9))
                {
                    ligne.Add(s.GetCellule(j, i));
                }
            }
            var monTableau = list_cell.Select(l => l.ToArray()).ToArray();
            var monPuzzle  = new Puzzle(monTableau, false);
            var monSolver  = new Solver(monPuzzle);

            monSolver.DoWork(this, new System.ComponentModel.DoWorkEventArgs(null));

            foreach (var i in System.Linq.Enumerable.Range(0, 9))
            {
                foreach (var j in System.Linq.Enumerable.Range(0, 9))
                {
                    s.SetCell(i, j, monPuzzle.Rows[i][j].Value);
                }
            }
        }
コード例 #5
0
 public void Solve(GrilleSudoku grid)
 {
     Sud      = new Sudoku(grid);
     s.sudoku = Sud;
     s.Solve();
     Sud = s.sudoku;
     for (int i = 0; i < 9; i++)
     {
         for (int j = 0; j < 9; j++)
         {
             grid.SetCell(i, j, Sud.getCaseSudoku(i, j));
         }
     }
 }
コード例 #6
0
        public void Solve(GrilleSudoku s)
        {
            var game     = String.Concat(s.Cellules.Select(c => (c == 0) ? "." : c.ToString()));
            var solution = LinqSudokuSolver.search(LinqSudokuSolver.parse_grid(game));

            foreach (var r in Enumerable.Range(0, 9))
            {
                foreach (var c in Enumerable.Range(0, 9))
                {
                    var cellules = Int32.Parse(solution[LinqSudokuSolver.rows[r].ToString() + LinqSudokuSolver.cols[c].ToString()]);

                    s.SetCell(r, c, cellules);
                }
            }
        }
コード例 #7
0
        public void Solve(GrilleSudoku s)
        {
            string game = string.Concat(s.Cellules.Select(c => (c == 0) ? "." : c.ToString()));
            Dictionary <string, string> solution = LinqSudokuSolver.Search(LinqSudokuSolver.Parse_grid(game));

            for (int r = 0; r < cellIndices.Count(); r++)
            {
                for (int c = 0; c < cellIndices.Count(); c++)
                {
                    var cellules = Int32.Parse(solution[LinqSudokuSolver.Rows[r].ToString() + LinqSudokuSolver.Cols[c].ToString()]);

                    s.SetCell(r, c, cellules);
                }
            }
        }
コード例 #8
0
        public void unassign(GrilleSudoku s, int cell, List <int> assignment, List <List <int> > possibilites, List <List <int> > pruned)
        {
            int val_cell = s.GetCellule(cell / 9, cell % 9);

            if (assignment.Contains(cell))
            {
                if (!possibilites[cell].Contains(val_cell))
                {
                    possibilites[cell].Add(val_cell);
                }


                if (possibilites[cell].Contains(10))
                {
                    possibilites[cell].Remove(10);
                }

                assignment.Remove(cell);
                s.SetCell(cell / 9, cell % 9, 0);
                List <int> l = new List <int>();
                pruned[cell] = l;

                foreach (int neighboor_value in Cell_Neighboor(s, cell))
                {
                    List <int> r = new List <int>();

                    if (!possibilites[neighboor_value].Contains(val_cell))
                    {
                        if (Is_present(s, possibilites, val_cell, neighboor_value))
                        {
                            possibilites[neighboor_value].Add(val_cell);
                            //Console.WriteLine("Voisin : {0} Re add dans poss : {1}", neighboor_value, val_cell);
                        }
                    }

                    if (pruned[neighboor_value].Contains(val_cell))
                    {
                        pruned[neighboor_value].Remove(val_cell);
                    }
                }
            }
            else
            {
                Console.WriteLine("ERROOR 265 : UNSIGN A NON SIGN");
            }
        }
コード例 #9
0
        public void Solve(GrilleSudoku s)
        {
            var substExprs = new List <Expr>();
            var substVals  = new List <Expr>();

            for (int i = 0; i < 9; i++)
            {
                for (int j = 0; j < 9; j++)
                {
                    if (s.GetCellule(i, j) != 0)
                    {
                        substExprs.Add(X[i][j]);
                        substVals.Add(z3Context.MkInt(s.GetCellule(i, j)));
                    }
                }
            }
            BoolExpr instance_c = (BoolExpr)GenericContraints.Substitute(substExprs.ToArray(), substVals.ToArray());

            var z3Solver = GetSolver();

            z3Solver.Assert(instance_c);

            if (z3Solver.Check() == Status.SATISFIABLE)
            {
                Model m = z3Solver.Model;
                for (int i = 0; i < 9; i++)
                {
                    for (int j = 0; j < 9; j++)
                    {
                        if (s.GetCellule(i, j) == 0)
                        {
                            s.SetCell(i, j, ((IntNum)m.Evaluate(X[i][j])).Int);
                        }
                    }
                }
            }
            else
            {
                Console.WriteLine("Failed to solve sudoku");
            }
        }
コード例 #10
0
        private static void SolutionToGrid(GrilleSudoku sudoku, IReadOnlyList <Tuple <int, int, int, bool> > internalRows, Solution solution)
        {
            var rowStrings = solution.RowIndexes
                             .Select(rowIndex => internalRows[rowIndex])
                             .OrderBy(t => t.Item1)
                             .ThenBy(t => t.Item2)
                             .GroupBy(t => t.Item1, t => t.Item3)
                             .Select(value => string.Concat(value))
                             .ToImmutableList();

            String w = rowStrings.ItemRef(0);

            for (int a = 1; a <= 8; a++)
            {
                w = w + rowStrings.ItemRef(a);
            }
            for (int a = 1; a <= 162; a++)
            {
                if (a % 2 == 1)
                {
                    w = w.Insert(a, " ");
                }
            }
            String[] Sub = w.Split(' ');
            int      cpt = 0;

            for (int i = 0; i <= 8; i++)
            {
                for (int j = 0; j <= 8; j++)
                {
                    sudoku.SetCell(i, j, int.Parse(Sub[cpt]));
                    cpt = cpt + 1;
                }
            }
            // Console.WriteLine(sudoku.ToString());
        }
コード例 #11
0
        public void Solve(GrilleSudoku s)
        {
            int[][] sJaggedTableau = Enumerable.Range(0, 9).Select(i => Enumerable.Range(0, 9).Select(j => s.GetCellule(i, j)).ToArray()).ToArray();
            var     sTableau       = To2D(sJaggedTableau);

            Program.estValide(sTableau, 0);
            Enumerable.Range(0, 9).ToList().ForEach(i => Enumerable.Range(0, 9).ToList().ForEach(j => s.SetCell(i, j, sTableau[i, j])));
        }
コード例 #12
0
        //NOUVEAU CODE


        public void Solve2(GrilleSudoku s)
        {
            bool solved  = false;
            bool full    = false; // If this is true after a segment, the puzzle is solved and we can break
            bool deadEnd = false;

            List <List <int> > list_cell = new List <List <int> >();

            foreach (var i in System.Linq.Enumerable.Range(0, 9))
            {
                var ligne = new List <int>(9);
                list_cell.Add(ligne);
                foreach (var j in System.Linq.Enumerable.Range(0, 9))
                {
                    ligne.Add(s.GetCellule(j, i));
                }
            }



            var monTableau = list_cell.Select(l => l.ToArray()).ToArray();
            var monPuzzle  = new Puzzle(monTableau, false);
            var monSolver  = new Solver(monPuzzle);
            //monSolver.DoWork(this, new System.ComponentModel.DoWorkEventArgs(null));

            List <Cell> allCells = null;
            Stack <BackTrackingState> exploredCellValues = null;

            monPuzzle.RefreshCandidates();
            do
            {
                deadEnd = false;

                // First we do human inference
                do
                {
                    full = true;

                    bool changed = false;
                    // Check for naked singles or a completed puzzle
                    for (int x = 0; x < 9; x++)
                    {
                        for (int y = 0; y < 9; y++)
                        {
                            Cell cell = monPuzzle[x, y];
                            if (cell.Value == 0)
                            {
                                full = false;
                                // Check for naked singles
                                int[] a = cell.Candidates.ToArray(); // Copy
                                if (a.Length == 1)
                                {
                                    cell.Set(a[0]);
                                    changed = true;
                                }
                            }
                        }
                    }
                    // Solved or failed to solve
                    if (full || (!changed && !monSolver.RunTechnique()))
                    {
                        break;
                    }
                } while (true);

                full = monPuzzle.Rows.All(row => row.All(c => c.Value != 0));
                //full = s.SetCell(x, y, monPuzzle.Rows[x][y].Value);

                // If puzzle isn't full, we do exploration
                if (!full)
                {
                    // Les Sudokus les plus difficiles ne peuvent pas être résolus avec un stylo bille, c'est à dire en inférence pure.
                    // Il va falloir lacher le stylo bille et prendre le crayon à papier et la gomme pour commencer une exploration fondée sur des hypothèses avec possible retour en arrière
                    if (allCells == null)
                    {
                        allCells           = monPuzzle.Rows.SelectMany((row, rowIdx) => row).ToList();
                        exploredCellValues = new Stack <BackTrackingState>();
                    }
                    //puzzle.RefreshCandidates();

                    // Pour accélérer l'exploration et éviter de traverser la feuille en gommant trop souvent, on va utiliser les heuristiques des problèmes à satisfaction de contraintes
                    // cf. les slides et le problème du "coffre de voiture" abordé en cours

                    //heuristique MRV
                    var minCandidates = allCells.Min(cell => cell.Candidates.Count > 0 ? cell.Candidates.Count : int.MaxValue);

                    if (minCandidates != int.MaxValue)
                    {
                        // Utilisation de l'heuristique Deg: de celles qui ont le moins de candidats à égalité, on choisi celle la plus contraignante, celle qui a le plus de voisins (on pourrait faire mieux avec le nombre de candidats en commun avec ses voisins)
                        var candidateCells = allCells.Where(cell => cell.Candidates.Count == minCandidates);
                        //var degrees = candidateCells.Select(candidateCell => new {Cell = candidateCell, Degree = candidateCell.GetCellsVisible().Aggregate(0, (sum, neighbour) => sum + neighbour.Candidates.Count) });
                        var degrees = candidateCells.Select(candidateCell => new { Cell = candidateCell, Degree = candidateCell.GetCellsVisible().Count(c => c.Value == 0) }).ToList();
                        //var targetCell = list_cell.First(cell => cell.Candidates.Count == minCandidates);
                        var maxDegree  = degrees.Max(deg1 => deg1.Degree);
                        var targetCell = degrees.First(deg => deg.Degree == maxDegree).Cell;

                        //dernière exploration pour ne pas se mélanger les pinceaux

                        BackTrackingState currentlyExploredCellValues;
                        if (exploredCellValues.Count == 0 || !exploredCellValues.Peek().Cell.Equals(targetCell))
                        {
                            currentlyExploredCellValues = new BackTrackingState()
                            {
                                Board = monPuzzle.GetBoard(), Cell = targetCell, ExploredValues = new List <int>()
                            };
                            exploredCellValues.Push(currentlyExploredCellValues);
                        }
                        else
                        {
                            currentlyExploredCellValues = exploredCellValues.Peek();
                        }


                        //utilisation de l'heuristique LCV: on choisi la valeur la moins contraignante pour les voisins
                        var candidateValues  = targetCell.Candidates.Where(i => !currentlyExploredCellValues.ExploredValues.Contains(i));
                        var neighbourood     = targetCell.GetCellsVisible();
                        var valueConstraints = candidateValues.Select(v => new
                        {
                            Value       = v,
                            ContraintNb = neighbourood.Count(neighboor => neighboor.Candidates.Contains(v))
                        }).ToList();
                        var minContraints = valueConstraints.Min(vc => vc.ContraintNb);
                        var exploredValue = valueConstraints.First(vc => vc.ContraintNb == minContraints).Value;
                        currentlyExploredCellValues.ExploredValues.Add(exploredValue);
                        targetCell.Set(exploredValue);
                        //targetCell.Set(exploredValue, true);
                    }
                    else
                    {
                        //Plus de candidats possibles, on atteint un cul-de-sac
                        if (monPuzzle.IsValid())
                        {
                            solved = true;
                        }
                        else
                        {
                            deadEnd = true;
                        }


                        //deadEnd = true;
                    }
                }
                else
                {
                    //If puzzle is full, it's either solved or a deadend
                    if (monPuzzle.IsValid())
                    {
                        solved = true;
                    }
                    else
                    {
                        deadEnd = true;
                    }
                }


                if (deadEnd)
                {
                    //On se retrouve bloqué, il faut gommer et tenter d'autres hypothèses
                    BackTrackingState currentlyExploredCellValues = exploredCellValues.Peek();
                    //On annule la dernière assignation
                    currentlyExploredCellValues.Backtrack(monPuzzle);
                    var targetCell = currentlyExploredCellValues.Cell;
                    //targetCell.Set(0, true);
                    while (targetCell.Candidates.All(i => currentlyExploredCellValues.ExploredValues.Contains(i)))
                    {
                        //on a testé toutes les valeurs possibles, On est à un cul de sac, il faut revenir en arrière
                        exploredCellValues.Pop();
                        if (exploredCellValues.Count == 0)
                        {
                            Debug.WriteLine("bug in the algorithm techniques humaines");
                        }
                        currentlyExploredCellValues = exploredCellValues.Peek();
                        //On annule la dernière assignation
                        currentlyExploredCellValues.Backtrack(monPuzzle);
                        targetCell = currentlyExploredCellValues.Cell;
                        //targetCell.Set(0, true);
                    }
                    // D'autres valeurs sont possible pour la cellule courante, on les tente
                    //utilisation de l'heuristique LCV
                    var candidateValues  = targetCell.Candidates.Where(i => !currentlyExploredCellValues.ExploredValues.Contains(i));
                    var neighbourood     = targetCell.GetCellsVisible();
                    var valueConstraints = candidateValues.Select(v => new
                    {
                        Value       = v,
                        ContraintNb = neighbourood.Count(neighboor => neighboor.Candidates.Contains(v))
                    }).ToList();
                    var minContraints = valueConstraints.Min(vc => vc.ContraintNb);
                    var exploredValue = valueConstraints.First(vc => vc.ContraintNb == minContraints).Value;
                    currentlyExploredCellValues.ExploredValues.Add(exploredValue);
                    targetCell.Set(exploredValue);
                }
            } while (!solved);



            foreach (var i in System.Linq.Enumerable.Range(0, 9))
            {
                foreach (var j in System.Linq.Enumerable.Range(0, 9))
                {
                    s.SetCell(i, j, monPuzzle.Rows[i][j].Value);
                }
            }
        }
コード例 #13
0
        public void Solve(GrilleSudoku s)
        {
            //Création d'un solver Or-tools
            Solver solver = new Solver("Sudoku");

            //Création de la grille de variables
            //Variables de décision

            IntVar[,] grid = solver.MakeIntVarMatrix(9, 9, 1, 9, "grid"); //VERIFIER
            IntVar[] grid_flat = grid.Flatten();                          //VERIFIER


            //Masque de résolution
            for (int i = 0; i < cellIndices.Count(); i++)
            {
                for (int j = 0; j < cellIndices.Count(); j++)
                {
                    if (s.GetCellule(i, j) > 0)
                    {
                        solver.Add(grid[i, j] == s.GetCellule(i, j));
                    }
                }
            }

            //Un chiffre ne figure qu'une seule fois par ligne/colonne/cellule
            for (int i = 0; i < cellIndices.Count(); i++)
            {
                // Lignes
                solver.Add((from j in cellIndices
                            select grid[i, j]).ToArray().AllDifferent());

                // Colonnes
                solver.Add((from j in cellIndices
                            select grid[j, i]).ToArray().AllDifferent());
            }

            //Cellules
            for (int i = 0; i < CELL.Count(); i++)
            {
                for (int j = 0; j < CELL.Count(); j++)
                {
                    solver.Add((from di in CELL
                                from dj in CELL
                                select grid[i * cell_size + di, j * cell_size + dj]
                                ).ToArray().AllDifferent());
                }
            }

            //Début de la résolution
            DecisionBuilder db = solver.MakePhase(grid_flat,
                                                  Solver.INT_VAR_SIMPLE,
                                                  Solver.INT_VALUE_SIMPLE);

            solver.NewSearch(db);

            //Mise à jour du sudoku
            //int n = cell_size * cell_size;
            //Or on sait que cell_size = 3 -> voir ligne 13
            //Inspiré de l'exemple : taille des cellules identique
            while (solver.NextSolution())
            {
                for (int i = 0; i < 9; i++)
                {
                    for (int j = 0; j < 9; j++)
                    {
                        s.SetCell(i, j, (int)grid[i, j].Value());
                    }
                }
            }

            //Si 4 lignes dessus optionnelles, EndSearch est obligatoire
            solver.EndSearch();
        }
コード例 #14
0
        public void Solve(GrilleSudoku s)
        {
            SolverContext problem = SolverContext.GetContext();
            Model         model   = problem.CreateModel();

            Decision[][] grid = new Decision[9][]; // 0-based indices, 1-based values
            for (int r = 0; r < 9; ++r)
            {
                grid[r] = new Decision[9];
            }

            for (int r = 0; r < 9; ++r)
            {
                for (int c = 0; c < 9; ++c)
                {
                    grid[r][c] = new Decision(Domain.IntegerRange(1, 9), "grid" + r + c);
                }
            }

            for (int r = 0; r < 9; ++r)
            {
                model.AddDecisions(grid[r]);
            }

            //for (int r = 0; r < 9; ++r) // alternative to above
            //  for (int c = 0; c < 9; ++c)
            //    model.AddDecisions(grid[r][c]);

            Console.WriteLine("\nCreating generic row constraints");
            for (int r = 0; r < 9; ++r)
            {
                model.AddConstraint("rowConstraint" + r, Model.AllDifferent(grid[r]));
            }

            Console.WriteLine("Creating generic column constraints");
            for (int c = 0; c < 9; ++c)
            {
                for (int first = 0; first < 8; ++first)
                {
                    for (int second = first + 1; second < 9; ++second)
                    {
                        model.AddConstraint("colConstraint" + c + first + second, grid[first][c] != grid[second][c]);
                    }
                }
            }

            Console.WriteLine("Creating generic sub-cube constraints");
            // cube constraints for grid[a][b] and grid[x][y]
            for (int r = 0; r < 9; r += 3)
            {
                for (int c = 0; c < 9; c += 3)
                {
                    for (int a = r; a < r + 3; ++a)
                    {
                        for (int b = c; b < c + 3; ++b)
                        {
                            for (int x = r; x < r + 3; ++x)
                            {
                                for (int y = c; y < c + 3; ++y)
                                {
                                    if ((x == a && y > b) || (x > a))
                                    { // xy > ab
                                        model.AddConstraint("cubeConstraint" + a + b + x + y, grid[a][b] != grid[x][y]);
                                    }
                                } // y
                            }     // x
                        }         // b
                    }             // a
                }                 // c
            }                     // r

            Console.WriteLine("Creating problem specific data constraints");

            // brute force approach:
            //model.AddConstraint("v02", grid[0][2] == 6);
            //model.AddConstraint("v03", grid[0][3] == 2);
            //model.AddConstraint("v07", grid[0][7] == 8);

            //model.AddConstraint("v12", grid[1][2] == 8);
            //model.AddConstraint("v13", grid[1][3] == 9);
            //model.AddConstraint("v14", grid[1][4] == 7);

            //model.AddConstraint("v22", grid[2][2] == 4);
            //model.AddConstraint("v23", grid[2][3] == 8);
            //model.AddConstraint("v24", grid[2][4] == 1);
            //model.AddConstraint("v26", grid[2][6] == 5);

            //model.AddConstraint("v34", grid[3][4] == 6);
            //model.AddConstraint("v38", grid[3][8] == 2);

            //model.AddConstraint("v41", grid[4][1] == 7);
            //model.AddConstraint("v47", grid[4][7] == 3);

            //model.AddConstraint("v50", grid[5][0] == 6);
            //model.AddConstraint("v54", grid[5][4] == 5);

            //model.AddConstraint("v62", grid[6][2] == 2);
            //model.AddConstraint("v64", grid[6][4] == 4);
            //model.AddConstraint("v65", grid[6][5] == 7);
            //model.AddConstraint("v66", grid[6][6] == 1);

            //model.AddConstraint("v72", grid[7][2] == 3);
            //model.AddConstraint("v74", grid[7][4] == 2);
            //model.AddConstraint("v75", grid[7][5] == 8);
            //model.AddConstraint("v76", grid[7][6] == 4);

            //model.AddConstraint("v81", grid[8][1] == 5);
            //model.AddConstraint("v85", grid[8][5] == 1);
            //model.AddConstraint("v86", grid[8][6] == 2);
            ////model.AddConstraint("v86", grid[8][6] == 4); // creates unsolvable problem

            AddDataConstraints(s, model, grid); // more elegant approach

            Console.WriteLine("\nSolving. . . ");

            int numSolutions = NumberSolutions(problem);

            Console.WriteLine("\nThere is/are " + numSolutions + " Solution(s)\n");

            Solution solution = problem.Solve();

            //ShowAnswer(grid); // alternative to below

            for (int r = 0; r < 9; ++r)
            {
                for (int c = 0; c < 9; ++c)
                {
                    double v = grid[r][c].GetDouble();
                    //Console.Write(" " + v);
                    s.SetCell(r, c, (int)v);
                }
            }
        }