protected Sudoku.Core.Sudoku SolveOriginalCleanup(Sudoku.Core.Sudoku instance) { BoolExpr instance_c = GetPuzzleConstraint(instance); var z3Solver = GetSolver(); z3Solver.Assert(GenericContraints); 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 (instance.GetCell(i, j) == 0) { instance.SetCell(i, j, ((IntNum)m.Evaluate(X[i][j])).Int); } } } } else { Console.WriteLine("Failed to solve sudoku"); } return(instance); }
private static Sudoku.Core.Sudoku SolutionToSudoku( IReadOnlyList <Tuple <int, int, int, bool> > internalRows, Solution solution, Sudoku.Core.Sudoku sudoku) { List <int> mySudoku = new List <int>(); Sudoku.Core.Sudoku mySudokuSolution = new Sudoku.Core.Sudoku(); 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(); mySudokuSolution.Cells.Clear(); for (int i = 0; i < rowStrings.Count; i++) { string line = rowStrings[i].Replace(" ", "0"); foreach (char myChar in line) { mySudokuSolution.Cells.Add(int.Parse(myChar.ToString())); } } return(mySudokuSolution); }
public Sudoku.Core.Sudoku Solve(Sudoku.Core.Sudoku s) { var strGrid = new List <string>(9); for (int i = 0; i < 9; i++) { var i1 = i; strGrid.Add(string.Join("", Indices.Select(j => s.Cells[i1 * 9 + j]).Select(i2 => i2 == 0 ? " " : i2.ToString(CultureInfo.InvariantCulture)))); } var grid = new Grid(ImmutableList.Create(strGrid.ToArray())); /*int[,] mySudoku = new int[9, 9]; * for (int i = 0; i < 9; i++) { * for (int j = 0; j < 9; j++) { * mySudoku[i, j] = mySudoku[i, s.Cells[j]]; * } * } */ //var internalRows = BuildInternalRowsForSudoku(mySudoku); var internalRows = BuildInternalRowsForSudoku(grid); var dlxRows = BuildDlxRows(internalRows); var solutions = new Dlx() .Solve(dlxRows, d => d, r => r) .Where(solution => VerifySolution(internalRows, solution)) .ToImmutableList(); //return SolutionToGrid(internalRows, solutions.First()); return(SolutionToSudoku(internalRows, solutions.First(), s)); }
protected Sudoku.Core.Sudoku SolveWithScope(Sudoku.Core.Sudoku instance) { var z3Solver = GetReusableSolver(); z3Solver.Push(); BoolExpr instance_c = GetPuzzleConstraint(instance); 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 (instance.GetCell(i, j) == 0) { instance.SetCell(i, j, ((IntNum)m.Evaluate(X[i][j])).Int); } } } } else { Console.WriteLine("Failed to solve sudoku"); } z3Solver.Pop(); return(instance); }
public Sudoku.Core.Sudoku Solve(Sudoku.Core.Sudoku s) { int[,] instance = new int[9, 9]; for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { instance[i, j] = s.GetCell(i, j); } } IntExpr[,] R = SudokuExample(instance); var listCells = new List <int>(81); for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { listCells.Add(((IntNum)R[i, j]).Int); } } return(new Sudoku.Core.Sudoku(listCells)); }
public Sudoku.Core.Sudoku Solve(Sudoku.Core.Sudoku grid_sudoku) { var solution = search(parse_grid(grid_sudoku)); Sudoku.Core.Sudoku solution_sudoku = Sudoku.Core.Sudoku.Parse(toLine(solution)); return(solution_sudoku); }
static void DisplayEasy() { var allSudokus = LoadEasy(); for (int i = 0; i < allSudokus.Count; i++) { Sudoku.Core.Sudoku sudoku = (Sudoku.Core.Sudoku)allSudokus[i]; Console.WriteLine(sudoku.ToString()); } }
public Sudoku.Core.Sudoku Solve(Sudoku.Core.Sudoku s) { using (var ctx = new Z3Context()) { var theorem = CreateTheorem(ctx, s); theorem.DefaultCollectionHandling = CollectionHandling.Constants; return(theorem.Solve()); } }
static void Benchmark1() { var solvers = new List <ISudokuSolver>(); foreach (var file in Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory)) { if (file.EndsWith("dll") && !(Path.GetFileName(file).StartsWith("libz3"))) { var assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(file); foreach (var type in assembly.GetTypes()) { if (typeof(ISudokuSolver).IsAssignableFrom(type) && !(typeof(ISudokuSolver) == type)) { var solver = (ISudokuSolver)Activator.CreateInstance(type); solvers.Add(solver); } } } } var allSudokus = LoadEasy(); var premierSudoku = allSudokus[0]; Console.WriteLine(premierSudoku.ToString()); TimeSpan tempsTotal = new TimeSpan(); var chrono = new Stopwatch(); foreach (var sudokuSolver in solvers) { foreach (var unsudoku in allSudokus) { var aResoudre = new Sudoku.Core.Sudoku() { Cells = new List <int>(unsudoku.Cells) }; chrono.Restart(); var resolu = sudokuSolver.Solve(aResoudre); var tempsPasse = chrono.Elapsed; tempsTotal += tempsPasse; Console.WriteLine(sudokuSolver.GetType().Name); Console.WriteLine(resolu.ToString()); Console.WriteLine(tempsPasse.ToString()); } Console.WriteLine(String.Concat("temps total de résolution pour ", sudokuSolver.GetType().Name, " :", tempsTotal.ToString())); } }
BoolExpr GetPuzzleConstraint(Sudoku.Core.Sudoku instance) { BoolExpr instance_c = z3Context.MkTrue(); for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { if (instance.GetCell(i, j) != 0) { instance_c = z3Context.MkAnd(instance_c, (BoolExpr) z3Context.MkEq(X[i][j], z3Context.MkInt(instance.GetCell(i, j)))); } } } return(instance_c); }
public static Dictionary <string, string> parse_grid(Sudoku.Core.Sudoku grid_sudoku) { string grid = toLine(grid_sudoku); var values = squares.ToDictionary(s => s, s => digits); foreach (var sd in zip(squares, (from s in grid select s.ToString()).ToArray())) { var s = sd[0]; var d = sd[1]; if (digits.Contains(d) && assign(values, s, d) == null) { return(null); } } return(values); }
protected Sudoku.Core.Sudoku SolveWithSubstitutions(Sudoku.Core.Sudoku instance) { 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 (instance.GetCell(i, j) != 0) { substExprs.Add(X[i][j]); substVals.Add(z3Context.MkInt(instance.GetCell(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 (instance.GetCell(i, j) == 0) { instance.SetCell(i, j, ((IntNum)m.Evaluate(X[i][j])).Int); } } } } else { Console.WriteLine("Failed to solve sudoku"); } return(instance); }
protected Sudoku.Core.Sudoku SolveOriginalVersion(Sudoku.Core.Sudoku instance) { BoolExpr instance_c = z3Context.MkTrue(); for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { instance_c = z3Context.MkAnd(instance_c, (BoolExpr) z3Context.MkITE(z3Context.MkEq(z3Context.MkInt(instance.GetCell(i, j)), z3Context.MkInt(0)), z3Context.MkTrue(), z3Context.MkEq(X[i][j], z3Context.MkInt(instance.GetCell(i, j))))); } } Solver s = z3Context.MkSolver(); s.Assert(GenericContraints); s.Assert(instance_c); if (s.Check() == Status.SATISFIABLE) { Model m = s.Model; for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { instance.SetCell(i, j, ((IntNum)m.Evaluate(X[i][j])).Int); } } return(instance); } else { Console.WriteLine("Failed to solve sudoku"); return(instance); } }
Sudoku.Core.Sudoku SudokuExample(Sudoku.Core.Sudoku instance) { BoolExpr instance_c = _ctx.MkTrue(); for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { instance_c = _ctx.MkAnd(instance_c, (BoolExpr) _ctx.MkITE(_ctx.MkEq(_ctx.MkInt(instance.GetCell(i, j)), _ctx.MkInt(0)), _ctx.MkTrue(), _ctx.MkEq(X[i][j], _ctx.MkInt(instance.GetCell(i, j))))); } } Solver s = _ctx.MkSolver(); s.Assert(sudoku_c); s.Assert(instance_c); if (s.Check() == Status.SATISFIABLE) { Model m = s.Model; for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { instance.SetCell(i, j, ((IntNum)m.Evaluate(X[i][j])).Int); } } return(instance); } else { Console.WriteLine("Failed to solve sudoku"); return(instance); } }
public virtual Sudoku.Core.Sudoku Solve(Sudoku.Core.Sudoku s) { return(SolveWithSubstitutions(s)); }
public static String toLine(Sudoku.Core.Sudoku grid) { return(string.Join("", grid.Cells.Select(x => x.ToString()).ToArray())); }
public Sudoku.Core.Sudoku Solve(Sudoku.Core.Sudoku sudoku) { //Sudoku -> Tableau int[,] sudokuInGrid = new int[9, 9]; for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { sudokuInGrid[i, j] = sudoku.GetCell(i, j); } } Solver solver = new Solver("Sudoku"); int cell_size = 3; IEnumerable <int> CELL = Enumerable.Range(0, cell_size); int n = cell_size * cell_size; IEnumerable <int> RANGE = Enumerable.Range(0, n); //Création de la grille de solution IntVar[,] grid = solver.MakeIntVarMatrix(n, n, 1, 9, "grid"); IntVar[] grid_flat = grid.Flatten(); //Tableau -> Solver foreach (int i in RANGE) { foreach (int j in RANGE) { if (sudokuInGrid[i, j] > 0) { solver.Add(grid[i, j] == sudokuInGrid[i, j]); } } } //Un chiffre ne figure qu'une seule fois par ligne/colonne/cellule foreach (int i in RANGE) { // Lignes solver.Add((from j in RANGE select grid[i, j]).ToArray().AllDifferent()); // Colonnes solver.Add((from j in RANGE select grid[j, i]).ToArray().AllDifferent()); } //Cellules foreach (int i in CELL) { foreach (int j in CELL) { 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); // Solver -> Liste var gridToSudoku = new List <int>(); while (solver.NextSolution()) { for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { gridToSudoku.Add((int)grid[i, j].Value()); } } } solver.EndSearch(); //Liste -> Sudoku return(new Sudoku.Core.Sudoku(gridToSudoku)); }
public Sudoku.Core.Sudoku Solve(Sudoku.Core.Sudoku s) { // Z3Solver z3 = new Z3Solver(); return(SudokuExample(s)); }
static void Benchmark1() { var solvers = new List <ISudokuSolver>(); foreach (var file in Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory)) { if (file.EndsWith("dll") && !(Path.GetFileName(file).StartsWith("libz3"))) { var assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(file); foreach (var type in assembly.GetTypes()) { if (typeof(ISudokuSolver).IsAssignableFrom(type) && !(typeof(ISudokuSolver) == type)) { var solver = (ISudokuSolver)Activator.CreateInstance(type); solvers.Add(solver); } } } } var allSudokus = Menu(); var premierSudoku = allSudokus[0]; //Console.WriteLine(premierSudoku.ToString()); var chrono = new Stopwatch(); // List<List<TimeSpan>> tempsTotalParSolver = new List<List<TimeSpan>>(); List <TempsParSudoku> listParSolver = new List <TempsParSudoku>(); Int32 i = 0; bool printSudoku = true; foreach (var unsudoku in allSudokus) { printSudoku = true; foreach (var sudokuSolver in solvers) { var aResoudre = new Sudoku.Core.Sudoku() { Cells = new List <int>(unsudoku.Cells) }; chrono.Restart(); var resolu = sudokuSolver.Solve(aResoudre); var tempsPasse = chrono.Elapsed; if (printSudoku) { printSudoku = false; Console.WriteLine(resolu.ToString()); } Console.WriteLine(String.Concat("Temps résolu par ", sudokuSolver.GetType().Name, " : ", tempsPasse.ToString())); listParSolver.Add(new TempsParSudoku(sudokuSolver.GetType().Name, tempsPasse)); } //Pour le solver CSP en IronPython chrono.Restart(); CSP(i); var tempsPasseCSP = chrono.Elapsed; listParSolver.Add(new TempsParSudoku("CSP", tempsPasseCSP)); Console.WriteLine(String.Concat("Temps résolu par CSP : ", tempsPasseCSP.ToString())); i++; } ILookup <String, TempsParSudoku> tempsPasseSurUnSudokuBySolver = listParSolver.ToLookup(o => o.NomSolver); foreach (var solver in tempsPasseSurUnSudokuBySolver) { TimeSpan tempsTotal = new TimeSpan(); foreach (var time in solver) { tempsTotal += time.TempsPasse; } Console.WriteLine("Solver {0} a tout résolu en {1}", solver.Key, tempsTotal); } }
/// <summary> /// Creates a Z3-capable theorem to solve a Sudoku /// </summary> /// <param name="context">The wrapping Z3 context used to interpret c# Lambda into Z3 constraints</param> /// <returns>A typed theorem to be further filtered with additional contraints</returns> public static Theorem <Sudoku.Core.Sudoku> CreateTheorem(Z3Context context, Sudoku.Core.Sudoku s) { var sudokuTheorem = context.NewTheorem <Sudoku.Core.Sudoku>(); for (int i = 0; i < 81; i++) { if (s.Cells[i] != 0) { var idx = i; var cellValue = s.Cells[i]; sudokuTheorem = sudokuTheorem.Where(sudoku => sudoku.Cells[idx] == cellValue); } } // Cells have values between 1 and 9 for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { //To avoid side effects with lambdas, we copy indices to local variables var i1 = i; var j1 = j; sudokuTheorem = sudokuTheorem.Where(sudoku => (sudoku.Cells[i1 * 9 + j1] > 0 && sudoku.Cells[i1 * 9 + j1] < 10)); } } // Rows must have distinct digits for (int r = 0; r < 9; r++) { //Again we avoid Lambda closure side effects var r1 = r; sudokuTheorem = sudokuTheorem.Where(t => Z3Methods.Distinct(Indices.Select(j => t.Cells[r1 * 9 + j]).ToArray())); } // Columns must have distinct digits for (int c = 0; c < 9; c++) { //Preventing closure side effects var c1 = c; sudokuTheorem = sudokuTheorem.Where(t => Z3Methods.Distinct(Indices.Select(i => t.Cells[i * 9 + c1]).ToArray())); } // Boxes must have distinct digits for (int b = 0; b < 9; b++) { //On évite les effets de bords par closure var b1 = b; // We retrieve to top left cell for all boxes, using integer division and remainders. var iStart = b1 / 3; var jStart = b1 % 3; var indexStart = iStart * 3 * 9 + jStart * 3; sudokuTheorem = sudokuTheorem.Where(t => Z3Methods.Distinct(new int[] { t.Cells[indexStart], t.Cells[indexStart + 1], t.Cells[indexStart + 2], t.Cells[indexStart + 9], t.Cells[indexStart + 10], t.Cells[indexStart + 11], t.Cells[indexStart + 18], t.Cells[indexStart + 19], t.Cells[indexStart + 20], } ) ); } return(sudokuTheorem); }
public bool IsValid(Sudoku originalPuzzle) { return(NbErrors(originalPuzzle) == 0); }