private static void Main(string[] args) { // Basic Usage using (var ctx = new Z3Context()) { ctx.Log = Console.Out; // see internal logging var theorem = from t in ctx.NewTheorem(new { x = default(bool), y = default(bool) }) where t.x ^ t.y select t; var result = theorem.Solve(); Console.WriteLine(result); } // Advanced Usage using (var ctx = new Z3Context()) { ctx.Log = Console.Out; // see internal logging var theorem = from t in ctx.NewTheorem <Symbols <int, int> >() where t.X1 < t.X2 + 1 where t.X1 > 2 where t.X1 != t.X2 select t; var result = theorem.Solve(); Console.WriteLine(result); } // Sudoku Extension Usage (Z3.LinqBinding.Sudoku) using (var ctx = new Z3Context()) { var theorem = from t in SudokuTheorem.Create(ctx) where t.Cell13 == 2 && t.Cell16 == 1 && t.Cell18 == 6 where t.Cell23 == 7 && t.Cell26 == 4 where t.Cell31 == 5 && t.Cell37 == 9 where t.Cell42 == 1 && t.Cell44 == 3 where t.Cell51 == 8 && t.Cell55 == 5 && t.Cell59 == 4 where t.Cell66 == 6 && t.Cell68 == 2 where t.Cell73 == 6 && t.Cell79 == 7 where t.Cell84 == 8 && t.Cell87 == 3 where t.Cell92 == 4 && t.Cell94 == 9 && t.Cell97 == 2 select t; var result = theorem.Solve(); Console.WriteLine(result); } // All samples using (var ctx = new Z3Context()) { ctx.Log = Console.Out; // see internal logging Print(from t in ctx.NewTheorem(new { x = default(bool) }) where t.x && !t.x select t); Print(from t in ctx.NewTheorem(new { x = default(bool), y = default(bool) }) where t.x ^ t.y select t); Print(from t in ctx.NewTheorem(new { x = default(int), y = default(int) }) where t.x < t.y + 1 where t.x > 2 select t); Print(from t in ctx.NewTheorem <Symbols <int, int> >() where t.X1 < t.X2 + 1 where t.X1 > 2 where t.X1 != t.X2 select t); Print(from t in ctx.NewTheorem <Symbols <int, int, int, int, int> >() where t.X1 - t.X2 >= 1 where t.X1 - t.X2 <= 3 where t.X1 == (2 * t.X3) + t.X5 where t.X3 == t.X5 where t.X2 == 6 * t.X4 select t); Print(from t in ctx.NewTheorem <Symbols <int, int> >() where Z3Methods.Distinct(t.X1, t.X2) select t); Print(from t in SudokuTheorem.Create(ctx) where t.Cell13 == 2 && t.Cell16 == 1 && t.Cell18 == 6 where t.Cell23 == 7 && t.Cell26 == 4 where t.Cell31 == 5 && t.Cell37 == 9 where t.Cell42 == 1 && t.Cell44 == 3 where t.Cell51 == 8 && t.Cell55 == 5 && t.Cell59 == 4 where t.Cell66 == 6 && t.Cell68 == 2 where t.Cell73 == 6 && t.Cell79 == 7 where t.Cell84 == 8 && t.Cell87 == 3 where t.Cell92 == 4 && t.Cell94 == 9 && t.Cell97 == 2 select t); } }
/// <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); }
private static void AllSamplesInSameContext() { // All samples using (var ctx = new Z3Context()) { ctx.Log = Console.Out; // see internal logging Print(from t in ctx.NewTheorem(new { x = default(bool) }) where t.x && !t.x select t); Print(from t in ctx.NewTheorem(new { x = default(bool), y = default(bool) }) where t.x ^ t.y select t); Print(from t in ctx.NewTheorem(new { x = default(int), y = default(int) }) where t.x < t.y + 1 where t.x > 2 select t); Print(from t in ctx.NewTheorem <Symbols <int, int> >() where t.X1 < t.X2 + 1 where t.X1 > 2 where t.X1 != t.X2 select t); Print(from t in ctx.NewTheorem <Symbols <int, int, int, int, int> >() where t.X1 - t.X2 >= 1 where t.X1 - t.X2 <= 3 where t.X1 == (2 * t.X3) + t.X5 where t.X3 == t.X5 where t.X2 == 6 * t.X4 select t); Print(from t in ctx.NewTheorem <Symbols <int, int> >() where Z3Methods.Distinct(t.X1, t.X2) select t); Print(from t in SudokuTheorem.Create(ctx) where t.Cell13 == 2 && t.Cell16 == 1 && t.Cell18 == 6 where t.Cell23 == 7 && t.Cell26 == 4 where t.Cell31 == 5 && t.Cell37 == 9 where t.Cell42 == 1 && t.Cell44 == 3 where t.Cell51 == 8 && t.Cell55 == 5 && t.Cell59 == 4 where t.Cell66 == 6 && t.Cell68 == 2 where t.Cell73 == 6 && t.Cell79 == 7 where t.Cell84 == 8 && t.Cell87 == 3 where t.Cell92 == 4 && t.Cell94 == 9 && t.Cell97 == 2 select t); // Sudoku Extension Usage Z3.LinqBinding.Sudoku demonstrating array capabilities Print <SudokuAsArray>(SudokuAsArray .Parse("9.2..54.31...63.255.84.7.6..263.9..1.57.1.29..9.67.53.24.53.6..7.52..3.4.8..4195.") // Very easy .CreateTheorem(ctx)); Print <SudokuAsArray>(SudokuAsArray .Parse("..48...1767.9.....5.8.3...43..74.1...69...78...1.69..51...8.3.6.....6.9124...15..") // Easy .CreateTheorem(ctx)); Print <SudokuAsArray>(SudokuAsArray .Parse("..6.......8..542...4..9..7...79..3......8.4..6.....1..2.3.67981...5...4.478319562") // Medium .CreateTheorem(ctx)); Print <SudokuAsArray>(SudokuAsArray .Parse("....9.4.8.....2.7..1.7....32.4..156...........952..7.19....5.1..3.4.....1.2.7....") // Hard .CreateTheorem(ctx)); // Solving Canibals & Missionaires var can = new MissionariesAndCannibals() { NbMissionaries = 3, SizeBoat = 2, Length = 50 }; Print <MissionariesAndCannibals>(can.Create(ctx)); } }