public void Solve(GrilleSudoku s) { Console.WriteLine("Begin solving Sudoku"); Console.WriteLine("The problem is: "); int[][] problem = new int[9][]; for (int row = 0; row <= 8; row++) { problem[row] = new int[9]; for (int column = 0; column <= 8; column++) { problem[row][column] = s.GetCellule(row, column); } } int[,] tab = new int[9, 9]; for (int row = 0; row <= 8; row++) { problem[row] = new int[9]; for (int column = 0; column <= 8; column++) { tab[row, column] = s.GetCellule(row, column); } } //DisplayMatrix(problem); int numOrganisms = 200; int maxEpochs = 5000; int maxRestarts = 20; Sudoku sudo = Sudoku.New(tab); Sudoku soln = Solvette(sudo, numOrganisms, maxEpochs, maxRestarts); Console.WriteLine("Best solution found: "); //DisplayMatrix(soln); //affichage du sudoku Console.WriteLine(soln.ToString()); //Reconversion depuis int[,] for (int row = 0; row < 9; row++) { for (int column = 0; column < 9; column++) { s.Cellules[row * 9 + column] = soln.CellValues[row, column]; } } int err = Error(soln); if (err == 0) { Console.WriteLine("Success \n"); } else { Console.WriteLine("Did not find optimal solution \n"); } Console.WriteLine("End Sudoku demo"); Console.ReadLine(); }
static void AddDataConstraints(GrilleSudoku data, Model model, Decision[][] grid) { for (int r = 0; r < 9; ++r) { for (int c = 0; c < 9; ++c) { if (data.GetCellule(r, c) != 0) { model.AddConstraint("v" + r + c, grid[r][c] == data.GetCellule(r, c)); } } } }
public void Solve(GrilleSudoku s) { //Création d'un solver Or-tools Solver solver = new Solver("Sudoku"); //Création de la grille de variables IntVar[,] grid = solver.MakeIntVarMatrix(9, 9, 1, 9, "grid"); IntVar[] grid_flat = grid.Flatten(); //Masque de résolution foreach (int i in cellIndices) { foreach (int j in cellIndices) { 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 foreach (int i in cellIndices) { // Lignes solver.Add((from j in cellIndices select grid[i, j]).ToArray().AllDifferent()); // Colonnes } //Cellules //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 }
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); } } }
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 }
private static IImmutableList <Tuple <int, int, int, bool> > BuildInternalRowsForGrid(GrilleSudoku grid) { var rowsByCols = from row in Rows from col in Cols let value = grid.GetCellule(row, col) select BuildInternalRowsForCell(row, col, value); return(rowsByCols.SelectMany(cols => cols).ToImmutableList()); }
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"); } }
private IList <IList <IList <int> > > GetRowsPermutationsUncached(GrilleSudoku 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.GetCellule(rowIdx, j) > 0 && ((rowIdx == i && perm[j] != objSudoku.GetCellule(rowIdx, j)) || (rowIdx != i && perm[j] == objSudoku.GetCellule(rowIdx, j)))))) { tempList.Add(perm); } } toReturn.Add(tempList); } return(toReturn); }
private bool IsColValid(GrilleSudoku s, int col, int value) { for (var ligne = 0; ligne < Size; ligne++) { if (s.GetCellule(ligne, col) == value) { return(false); } } return(true); }
private bool IsLigneValid(GrilleSudoku s, int ligne, int value) { for (var col = 0; col < Size; col++) { if (s.GetCellule(ligne, col) == value) { return(false); } } return(true); }
private bool IsLigneValid(GrilleSudoku s, int ligne, int value) //Vérifie que chaque nombre n'apparait qu'une fois sur la ligne { for (var col = 0; col < Size; col++) { if (s.GetCellule(ligne, col) == value) { return(false); } } return(true); }
public int[][] ConvertToMatrix(GrilleSudoku grille) // conversion de grillesudoku en int[][] { int[][] sud = new int[9][]; for (int i = 0; i < 9; i++) { sud[i] = new int[9]; for (int j = 0; j < 9; j++) { sud[i][j] = grille.GetCellule(i, j); } } return(sud); }
private bool IsColValid(GrilleSudoku s, int col, int value) //Vérifie que chaque nombre n'apparait qu'une fois sur la colonne { for (var ligne = 0; ligne < Size; ligne++) { if (s.GetCellule(ligne, col) == value) { return(false); } } return(true); }
public bool Is_present(GrilleSudoku s, List <List <int> > possibilites, int poss, int position) { foreach (int voisin in Cell_Neighboor(s, position)) { int ligne = voisin / 9; int colonne = voisin % 9; if (s.GetCellule(ligne, colonne) == poss) { return(false); } } return(true); }
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"); } }
private bool IsCarreValid(GrilleSudoku s, int ligne, int col, int value) { var l = ligne - ligne % 3; var c = col - col % 3; for (var i = l; i < l + 3; i++) { for (var j = c; j < c + 3; j++) { if (s.GetCellule(i, j) == value) { return(false); } } } return(true); }
private bool IsCarreValid(GrilleSudoku s, int ligne, int col, int value) //Vérifie que chaque valeur n'apparait qu'une fois dans le carré { var l = ligne - ligne % 3; var c = col - col % 3; for (var i = l; i < l + 3; i++) { for (var j = c; j < c + 3; j++) { if (s.GetCellule(i, j) == value) { return(false); } } } return(true); }
// FONCTION DE FOWARD CHECKING public List <List <int> > Foward_Checking(GrilleSudoku s) { List <List <int> > LesPoss = new List <List <int> >(); for (int i = 0; i < 81; i++) { List <int> Poss = new List <int>(); if (s.GetCellule(i / 9, i % 9) != 0) { Poss.Add(10); } else { foreach (int possibilities in s.GetPossibilities(i / 9, i % 9)) { Poss.Add(possibilities); } } LesPoss.Add(Poss); } return(LesPoss); }
private int[][] workingSudoku; //Sudoku sur lequel vous allez travailler public Sudoku(GrilleSudoku grid) //Constructeur { initialSudoku = new int[9][]; workingSudoku = new int[9][]; string phrase = ""; for (int i = 0; i < 9; i++) { initialSudoku[i] = new int[9]; workingSudoku[i] = new int[9]; } for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { phrase = phrase + grid.GetCellule(i, j); } } initialSudoku = stringToSudoku(phrase); workingSudoku = stringToSudoku(phrase); }
// FONCTION SOLVE public void Solve(GrilleSudoku s) { // Foward Checking List <List <int> > possibilites = this.Foward_Checking(s); List <List <int> > pruned = new List <List <int> >(); List <int> liste = new List <int>(); for (int i = 0; i < 81; i++) { pruned.Add(liste); } // ACR CONSITENCY CHECKING AC3(s, possibilites); if (Is_Finished(possibilites)) { Console.WriteLine("Résolue juste avec AC3 !!!"); } else { List <int> assignment = new List <int>(); for (int i = 0; i < 81; i++) { if (s.GetCellule(i / 9, i % 9) != 0) { assignment.Add(i); } } if (recursive_backtrack_algorithm(s, possibilites, assignment, pruned)) { Console.WriteLine("Résolue avec Backtracking !!"); } } }
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(); }
//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); } } }
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]))); }