Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using ClassLibrary1;
- using Microsoft.Z3;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- namespace WindowsFormsApplication11.Csp
- {
- public class PuzzleComposer
- {
- [Flags()]
- public enum SquareScalar : ulong
- {
- A1 = 0x1, B1 = 0x2, C1 = 0x4, D1 = 0x8,
- E1 = 0x10, F1 = 0x20, G1 = 0x40, H1 = 0x80,
- A2 = 0x100, B2 = 0x200, C2 = 0x400, D2 = 0x800,
- E2 = 0x1000, F2 = 0x2000, G2 = 0x4000, H2 = 0x8000,
- A3 = 0x10000, B3 = 0x20000, C3 = 0x40000, D3 = 0x80000,
- E3 = 0x100000, F3 = 0x200000, G3 = 0x400000, H3 = 0x800000,
- A4 = 0x1000000, B4 = 0x2000000, C4 = 0x4000000, D4 = 0x8000000,
- E4 = 0x10000000, F4 = 0x20000000, G4 = 0x40000000, H4 = 0x80000000,
- A5 = 0x100000000, B5 = 0x200000000, C5 = 0x400000000, D5 = 0x800000000,
- E5 = 0x1000000000, F5 = 0x2000000000, G5 = 0x4000000000, H5 = 0x8000000000,
- A6 = 0x10000000000, B6 = 0x20000000000, C6 = 0x40000000000, D6 = 0x80000000000,
- E6 = 0x100000000000, F6 = 0x200000000000, G6 = 0x400000000000, H6 = 0x800000000000,
- A7 = 0x1000000000000, B7 = 0x2000000000000, C7 = 0x4000000000000, D7 = 0x8000000000000,
- E7 = 0x10000000000000, F7 = 0x20000000000000, G7 = 0x40000000000000, H7 = 0x80000000000000,
- A8 = 0x100000000000000, B8 = 0x200000000000000, C8 = 0x400000000000000, D8 = 0x800000000000000,
- E8 = 0x1000000000000000, F8 = 0x2000000000000000, G8 = 0x4000000000000000, H8 = 0x8000000000000000
- }
- // TODO Split in north, south attack
- public UInt64 AttackVertical(UInt64 startingSquare)
- {
- int file, rank;
- PieceSquareSpec.BreakSquare((SquareScalar)startingSquare, out file, out rank);
- var spec = (ulong)PieceSquareSpec.Files[file];
- return spec & ~(startingSquare);
- }
- // TODO Split in west, east attack
- public UInt64 AttackHorizontal(UInt64 startingSquare)
- {
- int file, rank;
- PieceSquareSpec.BreakSquare((SquareScalar)startingSquare, out file, out rank);
- var spec = (ulong)PieceSquareSpec.Ranks[rank];
- return spec & ~(startingSquare);
- }
- // TODO Split in north-west, north-east, south-west, south-east attack
- public UInt64 AttackDiagonals(UInt64 startingSquare)
- {
- UInt64 r = 0;
- int centerFile, centerRank;
- PieceSquareSpec.BreakSquare((SquareScalar)startingSquare, out centerFile, out centerRank);
- for (int off = 1; off < 8; ++off)
- {
- var x_min = centerFile - off;
- var x_max = centerFile + off;
- var y_min = centerRank - off;
- var y_max = centerFile + off;
- // x_min, y_min
- if (x_min >= 0 && x_min < 8 && y_min >= 0 && y_min < 8)
- {
- r |= PieceSquareSpec.MakeSquare(x_min, y_min);
- }
- // x_min, y_max
- if (x_min >= 0 && x_min < 8 && y_max >= 0 && y_max < 8)
- {
- r |= PieceSquareSpec.MakeSquare(x_min, y_max);
- }
- // x_max, y_min
- if (x_max >= 0 && x_max < 8 && y_min >= 0 && y_min < 8)
- {
- r |= PieceSquareSpec.MakeSquare(x_max, y_min);
- }
- // x_max, y_max
- if (x_max >= 0 && x_max < 8 && y_max >= 0 && y_max < 8)
- {
- r |= PieceSquareSpec.MakeSquare(x_max, y_max);
- }
- }
- return r;
- }
- public void Test()
- {
- using(var x = new Microsoft.Z3.Context())
- {
- uint bitboardQueenAttacks = 0x0;
- var bitboardSort = x.MkBitVecSort(64);
- var piece = x.MkDatatypeSort("Piece", new[]{
- x.MkConstructor("Rook", ""),
- x.MkConstructor("Queen", ""),
- x.MkConstructor("Bishop", "")
- });
- var pieceRook = piece.Constructors[0];
- var pieceQueen = piece.Constructors[1];
- var pieceBishop = piece.Constructors[2];
- var bitboard_to_piece = x.MkFuncDecl("type_of", bitboardSort, piece);
- var f = x.MkFuncDecl("piece_bitboard_to_attacked", new Microsoft.Z3.Sort[] {
- piece,
- bitboardSort
- }, bitboardSort);
- //x.ParseSMTLIB2String("");
- var solver = x.MkSolver();
- //solver.Assert(x.MkEq());
- foreach (SquareScalar value in Enum.GetValues(typeof(SquareScalar)))
- {
- UInt64 bitboard = (UInt64)value;
- UInt64 orthogonal = AttackVertical(bitboard) | AttackHorizontal(bitboard);
- UInt64 diagonals = AttackDiagonals(bitboard);
- // rooks
- solver.Assert(x.MkEq(
- x.MkApp(f, pieceRook.Apply(), x.MkBV(bitboard, 64)),
- x.MkBV(orthogonal, 64)));
- // queens
- solver.Assert(x.MkEq(
- x.MkApp(f, pieceQueen.Apply(), x.MkBV(bitboard, 64)),
- x.MkBV(orthogonal | diagonals, 64)));
- // bishops
- solver.Assert(x.MkEq(
- x.MkApp(f, pieceBishop.Apply(), x.MkBV(bitboard, 64)),
- x.MkBV(diagonals, 64)));
- }
- //EightQueensProblem(bitboardSort, x, solver, f, pieceRook, pieceQueen, pieceBishop);
- SquaresProblem(bitboardSort, x, solver, f, pieceRook, pieceQueen, pieceBishop);
- var status = solver.Check();
- var model = solver.Model;
- ulong test = 0;
- foreach(var d in model.Decls)
- {
- if (d.Arity != 0) continue;
- var interpr = model.ConstInterp(d);
- System.Diagnostics.Debug.WriteLine(f.Name + " = " + interpr + " (" + string.Format("{0:X}", ulong.Parse(interpr.ToString())) + ")");
- test |= ulong.Parse(interpr.ToString());
- }
- System.Diagnostics.Debug.WriteLine(string.Format("{0:X}", test));
- }
- }
- private void SquaresProblem(Sort bitboardSort, Context x, Solver solver, FuncDecl f, FuncDecl pieceRook, FuncDecl pieceQueen, FuncDecl pieceBishop)
- {
- var p0 = x.MkConst("piece0", bitboardSort);
- var p1 = x.MkConst("piece1", bitboardSort);
- var p2 = x.MkConst("piece2", bitboardSort);
- // pieces cant overlap
- solver.Assert(x.MkDistinct(p0, p1, p2));
- var p0Attacked = x.MkApp(f, pieceQueen.Apply(), p0);
- var p1Attacked = x.MkApp(f, pieceRook.Apply(), p1);
- var p2Attacked = x.MkApp(f, pieceBishop.Apply(), p2);
- // pieces must not be 0
- solver.Assert(x.MkNot(x.MkEq(x.MkBV(0, 64), p0)));
- solver.Assert(x.MkNot(x.MkEq(x.MkBV(0, 64), p1)));
- solver.Assert(x.MkNot(x.MkEq(x.MkBV(0, 64), p2)));
- // the set of attacked squares by an arbitrary piece must not equal 0
- solver.Assert(x.MkNot(x.MkEq(x.MkBV(0, 64), p0Attacked)));
- solver.Assert(x.MkNot(x.MkEq(x.MkBV(0, 64), p1Attacked)));
- solver.Assert(x.MkNot(x.MkEq(x.MkBV(0, 64), p2Attacked)));
- // the piece bitboard must have one and only one bit set
- solver.Assert(x.MkEq(x.MkBV(0, 64), x.MkBVAND((Microsoft.Z3.BitVecExpr)p0, x.MkBVSub((Microsoft.Z3.BitVecExpr)p0, x.MkBV(1, 64)))));
- solver.Assert(x.MkEq(x.MkBV(0, 64), x.MkBVAND((Microsoft.Z3.BitVecExpr)p1, x.MkBVSub((Microsoft.Z3.BitVecExpr)p1, x.MkBV(1, 64)))));
- solver.Assert(x.MkEq(x.MkBV(0, 64), x.MkBVAND((Microsoft.Z3.BitVecExpr)p2, x.MkBVSub((Microsoft.Z3.BitVecExpr)p2, x.MkBV(1, 64)))));
- // place a rook queen and bishop in such a way that
- // the square a1 is attacked 3 times
- // the square h1 is attacked 2 times
- // the square f4 is attacked 1 time
- var checkA1_0 = x.MkITE(x.MkEq(x.MkBV(1, 64), x.MkBVAND((BitVecExpr)p0Attacked, x.MkBV((ulong)SquareScalar.A1, 64))), x.MkInt(1), x.MkInt(0));
- var checkA1_1 = x.MkITE(x.MkEq(x.MkBV(1, 64), x.MkBVAND((BitVecExpr)p1Attacked, x.MkBV((ulong)SquareScalar.A1, 64))), x.MkInt(1), x.MkInt(0));
- var checkA1_2 = x.MkITE(x.MkEq(x.MkBV(1, 64), x.MkBVAND((BitVecExpr)p2Attacked, x.MkBV((ulong)SquareScalar.A1, 64))), x.MkInt(1), x.MkInt(0));
- solver.Assert(x.MkEq(x.MkInt(3), x.MkAdd((ArithExpr)checkA1_0, (ArithExpr)checkA1_1, (ArithExpr)checkA1_2)));
- // TODO pieces cant be in each others way!!!
- }
- private void EightQueensProblem(Sort bitboardSort, Context x, Solver solver, FuncDecl f, FuncDecl pieceRook, FuncDecl pieceQueen, FuncDecl pieceBishop)
- {
- var p0 = x.MkConst("piece0", bitboardSort);
- var p1 = x.MkConst("piece1", bitboardSort);
- var p2 = x.MkConst("piece2", bitboardSort);
- var p3 = x.MkConst("piece3", bitboardSort);
- var p4 = x.MkConst("piece4", bitboardSort);
- var p5 = x.MkConst("piece5", bitboardSort);
- var p6 = x.MkConst("piece6", bitboardSort);
- var p7 = x.MkConst("piece7", bitboardSort);
- // pieces cant overlap
- solver.Assert(x.MkDistinct(p0, p1, p2, p3, p4, p5, p6, p7));
- // pieces must not be 0
- solver.Assert(x.MkNot(x.MkEq(x.MkBV(0, 64), p0)));
- solver.Assert(x.MkNot(x.MkEq(x.MkBV(0, 64), p1)));
- solver.Assert(x.MkNot(x.MkEq(x.MkBV(0, 64), p2)));
- solver.Assert(x.MkNot(x.MkEq(x.MkBV(0, 64), p3)));
- solver.Assert(x.MkNot(x.MkEq(x.MkBV(0, 64), p4)));
- solver.Assert(x.MkNot(x.MkEq(x.MkBV(0, 64), p5)));
- solver.Assert(x.MkNot(x.MkEq(x.MkBV(0, 64), p6)));
- solver.Assert(x.MkNot(x.MkEq(x.MkBV(0, 64), p7)));
- // the set of attacked squares by an arbitrary piece must not equal 0
- solver.Assert(x.MkNot(x.MkEq(x.MkBV(0, 64), x.MkApp(f, pieceQueen.Apply(), p0))));
- solver.Assert(x.MkNot(x.MkEq(x.MkBV(0, 64), x.MkApp(f, pieceQueen.Apply(), p1))));
- solver.Assert(x.MkNot(x.MkEq(x.MkBV(0, 64), x.MkApp(f, pieceQueen.Apply(), p2))));
- solver.Assert(x.MkNot(x.MkEq(x.MkBV(0, 64), x.MkApp(f, pieceQueen.Apply(), p3))));
- solver.Assert(x.MkNot(x.MkEq(x.MkBV(0, 64), x.MkApp(f, pieceQueen.Apply(), p4))));
- solver.Assert(x.MkNot(x.MkEq(x.MkBV(0, 64), x.MkApp(f, pieceQueen.Apply(), p5))));
- solver.Assert(x.MkNot(x.MkEq(x.MkBV(0, 64), x.MkApp(f, pieceQueen.Apply(), p6))));
- solver.Assert(x.MkNot(x.MkEq(x.MkBV(0, 64), x.MkApp(f, pieceQueen.Apply(), p7))));
- // the piece bitboard must have one and only one bit set
- solver.Assert(x.MkEq(x.MkBV(0, 64), x.MkBVAND((Microsoft.Z3.BitVecExpr)p0, x.MkBVSub((Microsoft.Z3.BitVecExpr)p0, x.MkBV(1, 64)))));
- solver.Assert(x.MkEq(x.MkBV(0, 64), x.MkBVAND((Microsoft.Z3.BitVecExpr)p1, x.MkBVSub((Microsoft.Z3.BitVecExpr)p1, x.MkBV(1, 64)))));
- solver.Assert(x.MkEq(x.MkBV(0, 64), x.MkBVAND((Microsoft.Z3.BitVecExpr)p2, x.MkBVSub((Microsoft.Z3.BitVecExpr)p2, x.MkBV(1, 64)))));
- solver.Assert(x.MkEq(x.MkBV(0, 64), x.MkBVAND((Microsoft.Z3.BitVecExpr)p3, x.MkBVSub((Microsoft.Z3.BitVecExpr)p3, x.MkBV(1, 64)))));
- solver.Assert(x.MkEq(x.MkBV(0, 64), x.MkBVAND((Microsoft.Z3.BitVecExpr)p4, x.MkBVSub((Microsoft.Z3.BitVecExpr)p4, x.MkBV(1, 64)))));
- solver.Assert(x.MkEq(x.MkBV(0, 64), x.MkBVAND((Microsoft.Z3.BitVecExpr)p5, x.MkBVSub((Microsoft.Z3.BitVecExpr)p5, x.MkBV(1, 64)))));
- solver.Assert(x.MkEq(x.MkBV(0, 64), x.MkBVAND((Microsoft.Z3.BitVecExpr)p6, x.MkBVSub((Microsoft.Z3.BitVecExpr)p6, x.MkBV(1, 64)))));
- solver.Assert(x.MkEq(x.MkBV(0, 64), x.MkBVAND((Microsoft.Z3.BitVecExpr)p7, x.MkBVSub((Microsoft.Z3.BitVecExpr)p7, x.MkBV(1, 64)))));
- Microsoft.Z3.Expr expr;
- Microsoft.Z3.Expr expr1;
- {
- expr = x.MkBVOR(
- (Microsoft.Z3.BitVecExpr)p0,
- (Microsoft.Z3.BitVecExpr)p1);
- expr = x.MkBVOR(
- (Microsoft.Z3.BitVecExpr)expr,
- (Microsoft.Z3.BitVecExpr)p2);
- expr = x.MkBVOR(
- (Microsoft.Z3.BitVecExpr)expr,
- (Microsoft.Z3.BitVecExpr)p3);
- expr = x.MkBVOR(
- (Microsoft.Z3.BitVecExpr)expr,
- (Microsoft.Z3.BitVecExpr)p4);
- expr = x.MkBVOR(
- (Microsoft.Z3.BitVecExpr)expr,
- (Microsoft.Z3.BitVecExpr)p5);
- expr = x.MkBVOR(
- (Microsoft.Z3.BitVecExpr)expr,
- (Microsoft.Z3.BitVecExpr)p6);
- expr = x.MkBVOR(
- (Microsoft.Z3.BitVecExpr)expr,
- (Microsoft.Z3.BitVecExpr)p7);
- }
- {
- expr1 = x.MkBVOR(
- (Microsoft.Z3.BitVecExpr)x.MkApp(f, pieceQueen.Apply(), p0),
- (Microsoft.Z3.BitVecExpr)x.MkApp(f, pieceQueen.Apply(), p1));
- expr1 = x.MkBVOR(
- (Microsoft.Z3.BitVecExpr)expr1,
- (Microsoft.Z3.BitVecExpr)x.MkApp(f, pieceQueen.Apply(), p2));
- expr1 = x.MkBVOR(
- (Microsoft.Z3.BitVecExpr)expr1,
- (Microsoft.Z3.BitVecExpr)x.MkApp(f, pieceQueen.Apply(), p3));
- expr1 = x.MkBVOR(
- (Microsoft.Z3.BitVecExpr)expr1,
- (Microsoft.Z3.BitVecExpr)x.MkApp(f, pieceQueen.Apply(), p4));
- expr1 = x.MkBVOR(
- (Microsoft.Z3.BitVecExpr)expr1,
- (Microsoft.Z3.BitVecExpr)x.MkApp(f, pieceQueen.Apply(), p5));
- expr1 = x.MkBVOR(
- (Microsoft.Z3.BitVecExpr)expr1,
- (Microsoft.Z3.BitVecExpr)x.MkApp(f, pieceQueen.Apply(), p6));
- expr1 = x.MkBVOR(
- (Microsoft.Z3.BitVecExpr)expr1,
- (Microsoft.Z3.BitVecExpr)x.MkApp(f, pieceQueen.Apply(), p7));
- }
- // pieces dont attack one another
- solver.Assert(x.MkEq(x.MkBV(0, 64), x.MkBVAND((Microsoft.Z3.BitVecExpr)expr, (Microsoft.Z3.BitVecExpr)expr1)));
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement