Example #1
0
        public static Theorem <SudokuTable> Create(Z3Context context)
        {
            var sudokuTheorem = context.NewTheorem <SudokuTable>();

            var cells = typeof(SudokuTable).GetProperties();

            foreach (var cell in cells)
            {
                sudokuTheorem = sudokuTheorem.Where(Between1And9(cell));
            }

            sudokuTheorem = sudokuTheorem.Where(DistinctRows(cells));
            sudokuTheorem = sudokuTheorem.Where(DistinctColumns(cells));

            sudokuTheorem = sudokuTheorem.Where(t => Z3Methods.Distinct(t.Cell11, t.Cell12, t.Cell13, t.Cell21, t.Cell22, t.Cell23, t.Cell31, t.Cell32, t.Cell33));
            sudokuTheorem = sudokuTheorem.Where(t => Z3Methods.Distinct(t.Cell14, t.Cell15, t.Cell16, t.Cell24, t.Cell25, t.Cell26, t.Cell34, t.Cell35, t.Cell36));
            sudokuTheorem = sudokuTheorem.Where(t => Z3Methods.Distinct(t.Cell17, t.Cell18, t.Cell19, t.Cell27, t.Cell28, t.Cell29, t.Cell37, t.Cell38, t.Cell39));
            sudokuTheorem = sudokuTheorem.Where(t => Z3Methods.Distinct(t.Cell41, t.Cell42, t.Cell43, t.Cell51, t.Cell52, t.Cell53, t.Cell61, t.Cell62, t.Cell63));
            sudokuTheorem = sudokuTheorem.Where(t => Z3Methods.Distinct(t.Cell44, t.Cell45, t.Cell46, t.Cell54, t.Cell55, t.Cell56, t.Cell64, t.Cell65, t.Cell66));
            sudokuTheorem = sudokuTheorem.Where(t => Z3Methods.Distinct(t.Cell47, t.Cell48, t.Cell49, t.Cell57, t.Cell58, t.Cell59, t.Cell67, t.Cell68, t.Cell69));
            sudokuTheorem = sudokuTheorem.Where(t => Z3Methods.Distinct(t.Cell71, t.Cell72, t.Cell73, t.Cell81, t.Cell82, t.Cell83, t.Cell91, t.Cell92, t.Cell93));
            sudokuTheorem = sudokuTheorem.Where(t => Z3Methods.Distinct(t.Cell74, t.Cell75, t.Cell76, t.Cell84, t.Cell85, t.Cell86, t.Cell94, t.Cell95, t.Cell96));
            sudokuTheorem = sudokuTheorem.Where(t => Z3Methods.Distinct(t.Cell77, t.Cell78, t.Cell79, t.Cell87, t.Cell88, t.Cell89, t.Cell97, t.Cell98, t.Cell99));

            return(sudokuTheorem);
        }
Example #2
0
        /// <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 <SudokuAsArray> Create(Z3Context context)
        {
            var sudokuTheorem = context.NewTheorem <SudokuAsArray>();

            // 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);
        }
Example #3
0
        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());
            }
        }
Example #4
0
        ///// <summary>
        ///// The array property is to be used in linq to Z3
        ///// </summary>
        //public int[] Cells
        //{
        //   get => CellsList.ToArray();
        //   set => CellsList = new List<int>(value);
        //}

        /// <summary>
        /// Creates a Z3 theorem to solve the sudoku, adding the general constraints, and the mask constraints for this particular Sudoku
        /// </summary>
        /// <param name="context">The linq to Z3 context wrapping Z3</param>
        /// <returns>a theorem with all constraints compounded</returns>
        public Theorem <SudokuAsArray> CreateTheorem(Z3Context context)
        {
            var toReturn = Create(context);

            for (int i = 0; i < 81; i++)
            {
                if (Cells[i] != 0)
                {
                    var idx       = i;
                    var cellValue = Cells[i];
                    toReturn = toReturn.Where(sudoku => sudoku.Cells[idx] == cellValue);
                }
            }

            return(toReturn);
        }
Example #5
0
        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);
            }
        }
Example #6
0
        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);
            }


            // Sudoku Extension Usage (Z3.LinqBinding.Sudoku)
            using (var ctx = new Z3Context())
            {
                var theorem = 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);
                var result = theorem.Solve();
                Console.WriteLine(result);
                theorem = 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);
                result = theorem.Solve();
                Console.WriteLine(result);
                theorem = SudokuAsArray
                          .Parse("..6.......8..542...4..9..7...79..3......8.4..6.....1..2.3.67981...5...4.478319562") // Medium
                          .CreateTheorem(ctx);
                result = theorem.Solve();
                Console.WriteLine(result);
                theorem = 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);
                result = theorem.Solve();
                Console.WriteLine(result);
            }



            // Solving Canibals & Missionaires

            using (var ctx = new Z3Context())
            {
                var can = new MissionariesAndCannibals()
                {
                    NbMissionaries = 3, SizeBoat = 2, Length = 50
                };
                var startTime = stopwatch.Elapsed;
                var minimal   = MissionariesAndCannibals.SearchMinimal(can);
                var endTime   = stopwatch.Elapsed;
                Console.WriteLine("Minimal Solution to missionaries and cannibals through Binary search");
                Console.WriteLine(minimal == null ? "none" : minimal.ToString());
                Console.WriteLine($"Time to solve: {endTime - startTime}");

                var theorem = can.Create(ctx);
                startTime = stopwatch.Elapsed;
                minimal   = theorem.Optimize(Optimization.Minimize, objMnC => objMnC.Length);
                endTime   = stopwatch.Elapsed;
                Console.WriteLine("Minimal Solution to missionaries and cannibals through Z3 optimization");
                Console.WriteLine(minimal == null ? "none" : minimal.ToString());
                Console.WriteLine($"Time to solve: {endTime - startTime}");
            }

            // Testing simplification

            using (var ctx = new Z3Context())
            {
                //ctx.Log = Console.Out;
                var can = new MissionariesAndCannibals()
                {
                    NbMissionaries = 3, SizeBoat = 2, Length = 30
                };

                Console.WriteLine($"Non simplified version");
                Console.WriteLine();
                var theorem = can.Create(ctx);
                theorem.SimplifyLambdas = false;
                var startTime = stopwatch.Elapsed;
                var minimal   = theorem.Optimize(Optimization.Minimize, objMnC => objMnC.Length);
                var endTime   = stopwatch.Elapsed;
                Console.WriteLine("Minimal Solution to missionaries and cannibals non simplified through Z3 optimization");
                Console.WriteLine($"Time to solve: {endTime - startTime}");
                Console.WriteLine($"simplified version");
                Console.WriteLine();
                theorem.SimplifyLambdas = true;
                startTime = stopwatch.Elapsed;
                minimal   = theorem.Optimize(Optimization.Minimize, objMnC => objMnC.Length);
                endTime   = stopwatch.Elapsed;
                Console.WriteLine("Minimal Solution to missionaries and cannibals simplified through Z3 optimization");
                Console.WriteLine($"Time to solve: {endTime - startTime}");
            }


            //AllSamplesInSameContext();

            Console.Read();
        }
Example #7
0
        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));
            }
        }