Beispiel #1
0
    def test_int_payloads(self):
        lattice = get_square_lattice(3)
        sym = make_number_range_symbol_set(1, 9)
        sg = SymbolGrid(lattice, sym)

        sc = ShapeConstrainer(lattice, [
            Shape([
                (Vector(0, 0), 1),
                (Vector(0, 1), 2),
                (Vector(1, 0), 4),
            ]),
            Shape([
                (Vector(0, 1), 3),
                (Vector(1, 0), 5),
                (Vector(1, 1), 6),
                (Vector(2, 1), 9),
            ]),
            Shape([
                (Vector(0, 0), 7),
                (Vector(0, 1), 8),
            ]),
        ],
                              solver=sg.solver,
                              complete=True)

        for p in lattice.points:
            sg.solver.add(sg.cell_is(p, sc.shape_payload_grid[p]))

        self.assertTrue(sg.solve())
        solved_grid = sg.solved_grid()
        for p in lattice.points:
            self.assertEqual(solved_grid[p], lattice.point_to_index(p) + 1)
        self.assertTrue(sg.is_unique())
Beispiel #2
0
def main():
    """SLICY solver example."""
    sym = grilops.SymbolSet(["S", "L", "I", "C", "Y", ("W", " ")])
    lattice = PointyToppedHexagonalLattice([
        areas_row_col_to_point(r, c) for r in range(len(AREAS))
        for c in range(len(AREAS[r]))
    ])
    sg = grilops.SymbolGrid(lattice, sym)
    rc = grilops.regions.RegionConstrainer(lattice,
                                           solver=sg.solver,
                                           complete=True)
    sc = ShapeConstrainer(
        lattice,
        [
            # Note that the example shapes are shown as flat-topped hexagons, so
            # you need to turn the page sideways to see them as pointy-topped ones.
            Shape([Vector(0, 0),
                   Vector(1, 1),
                   Vector(1, 3),
                   Vector(2, 4)]),  # S
            Shape([Vector(0, 0),
                   Vector(0, 2),
                   Vector(0, 4),
                   Vector(-1, 5)]),  # L
            Shape([Vector(0, 0),
                   Vector(0, 2),
                   Vector(0, 4),
                   Vector(0, 6)]),  # I
            Shape([Vector(0, 0),
                   Vector(1, 1),
                   Vector(1, 3),
                   Vector(0, 4)]),  # C
            Shape([Vector(0, 0),
                   Vector(2, 0),
                   Vector(1, 1),
                   Vector(1, 3)]),  # Y
        ],
        solver=sg.solver,
        allow_rotations=True,
        allow_reflections=True,
        allow_copies=True)

    link_symbols_to_shapes(sym, sg, sc)
    add_area_constraints(lattice, sc)
    add_sea_constraints(sym, sg, rc)
    add_adjacent_tetrahex_constraints(lattice, sc)

    if sg.solve():
        sg.print()
        print()
        if sg.is_unique():
            print("Unique solution")
        else:
            print("Alternate solution")
            sg.print()
            print()
    else:
        print("No solution")
Beispiel #3
0
def main():
    """Shape solver example."""
    points = []
    for y, row in enumerate(GRID):
        for x, c in enumerate(row):
            if c == "O":
                points.append(Point(y, x))
    lattice = RectangularLattice(points)

    shapes = [
        Shape([Vector(0, 0),
               Vector(1, 0),
               Vector(2, 0),
               Vector(3, 0)]),  # I
        Shape([Vector(0, 0),
               Vector(1, 0),
               Vector(2, 0),
               Vector(2, 1)]),  # L
        Shape([Vector(0, 1),
               Vector(0, 2),
               Vector(1, 0),
               Vector(1, 1)]),  # S
    ]

    sym = grilops.SymbolSet([("B", chr(0x2588) * 2), ("W", "  ")])
    sg = grilops.SymbolGrid(lattice, sym)
    sc = ShapeConstrainer(lattice,
                          shapes,
                          sg.solver,
                          complete=False,
                          allow_rotations=True,
                          allow_reflections=True,
                          allow_copies=False)
    for p in points:
        sg.solver.add(sg.cell_is(p, sym.W) == (sc.shape_type_grid[p] == -1))
        for n in sg.vertex_sharing_neighbors(p):
            np = n.location
            sg.solver.add(
                Implies(
                    And(sc.shape_type_grid[p] != -1,
                        sc.shape_type_grid[np] != -1),
                    sc.shape_type_grid[p] == sc.shape_type_grid[np]))

    if sg.solve():
        sg.print()
        print()
        sc.print_shape_types()
        print()
        if sg.is_unique():
            print("Unique solution")
        else:
            print("Alternate solution")
            sg.print()
    else:
        print("No solution")
Beispiel #4
0
def main():
    """LITS solver example."""
    sym = grilops.SymbolSet(["L", "I", "T", "S", ("W", " ")])
    lattice = grilops.get_rectangle_lattice(HEIGHT, WIDTH)
    sg = grilops.SymbolGrid(lattice, sym)
    rc = grilops.regions.RegionConstrainer(lattice, solver=sg.solver)
    sc = ShapeConstrainer(
        lattice,
        [
            Shape([Vector(0, 0),
                   Vector(1, 0),
                   Vector(2, 0),
                   Vector(2, 1)]),  # L
            Shape([Vector(0, 0),
                   Vector(1, 0),
                   Vector(2, 0),
                   Vector(3, 0)]),  # I
            Shape([Vector(0, 0),
                   Vector(0, 1),
                   Vector(0, 2),
                   Vector(1, 1)]),  # T
            Shape([Vector(0, 0),
                   Vector(1, 0),
                   Vector(1, 1),
                   Vector(2, 1)]),  # S
        ],
        solver=sg.solver,
        allow_rotations=True,
        allow_reflections=True,
        allow_copies=True)

    link_symbols_to_shapes(sym, sg, sc)
    add_area_constraints(lattice, sc)
    add_nurikabe_constraints(sym, sg, rc)
    add_adjacent_tetronimo_constraints(lattice, sc)

    if sg.solve():
        sg.print()
        print()
        sc.print_shape_types()
        print()
        sc.print_shape_instances()
        print()
        if sg.is_unique():
            print("Unique solution")
        else:
            print("Alternate solution")
            sg.print()
            print()
            sc.print_shape_types()
            print()
            sc.print_shape_instances()
            print()
    else:
        print("No solution")
Beispiel #5
0
def main():
    """Status Park (Loop) solver example."""
    for row in GIVENS:
        for cell in row:
            sys.stdout.write(cell)
        print()

    points = []
    for y, row in enumerate(GIVENS):
        for x, c in enumerate(row):
            if c != X:
                points.append(Point(y, x))
    lattice = RectangularLattice(points)

    sym = grilops.loops.LoopSymbolSet(lattice)
    sym.append("EMPTY", " ")

    sg = grilops.SymbolGrid(lattice, sym)
    grilops.loops.LoopConstrainer(sg, single_loop=True)
    sc = ShapeConstrainer(
        lattice, [Shape([Vector(y, x) for y, x in shape]) for shape in SHAPES],
        solver=sg.solver,
        allow_rotations=True,
        allow_reflections=True,
        allow_copies=False)

    for p in points:
        if GIVENS[p.y][p.x] == W:
            # White circles must be part of the loop.
            sg.solver.add(sym.is_loop(sg.grid[p]))
        elif GIVENS[p.y][p.x] == B:
            # Black circles must be part of a shape.
            sg.solver.add(sc.shape_type_grid[p] != -1)

        # A cell is part of the loop if and only if it is not part of
        # any shape.
        sg.solver.add(sym.is_loop(sg.grid[p]) == (sc.shape_type_grid[p] == -1))

        # Orthogonally-adjacent cells must be part of the same shape.
        for n in sg.edge_sharing_neighbors(p):
            np = n.location
            sg.solver.add(
                Implies(
                    And(sc.shape_type_grid[p] != -1,
                        sc.shape_type_grid[np] != -1),
                    sc.shape_type_grid[p] == sc.shape_type_grid[np]))

    if sg.solve():
        sg.print()
        print()
        sc.print_shape_types()
        print()
        if sg.is_unique():
            print("Unique solution")
        else:
            print("Alternate solution")
            sg.print()
    else:
        print("No solution")
Beispiel #6
0
    def test_datatype_payloads(self):
        lattice = get_square_lattice(3)
        sym = make_number_range_symbol_set(0, 2)
        row_grid = SymbolGrid(lattice, sym)
        col_grid = SymbolGrid(lattice, sym, solver=row_grid.solver)

        RowCol = Datatype("RowCol")
        RowCol.declare("row_col", ("row", IntSort()), ("col", IntSort()))
        RowCol = RowCol.create()

        sc = ShapeConstrainer(lattice, [
            Shape([
                (Vector(0, 0), RowCol.row_col(0, 0)),
                (Vector(0, 1), RowCol.row_col(0, 1)),
                (Vector(1, 0), RowCol.row_col(1, 0)),
            ]),
            Shape([
                (Vector(0, 1), RowCol.row_col(0, 2)),
                (Vector(1, 0), RowCol.row_col(1, 1)),
                (Vector(1, 1), RowCol.row_col(1, 2)),
                (Vector(2, 1), RowCol.row_col(2, 2)),
            ]),
            Shape([
                (Vector(0, 0), RowCol.row_col(2, 0)),
                (Vector(0, 1), RowCol.row_col(2, 1)),
            ]),
        ],
                              solver=row_grid.solver,
                              complete=True)

        for p in lattice.points:
            row_grid.solver.add(
                row_grid.cell_is(p, RowCol.row(sc.shape_payload_grid[p])))
            col_grid.solver.add(
                col_grid.cell_is(p, RowCol.col(sc.shape_payload_grid[p])))

        self.assertTrue(row_grid.solve())
        solved_row_grid = row_grid.solved_grid()
        solved_col_grid = col_grid.solved_grid()
        for p in lattice.points:
            self.assertEqual(solved_row_grid[p], p.y)
            self.assertEqual(solved_col_grid[p], p.x)
        self.assertTrue(row_grid.is_unique())
Beispiel #7
0
    def test_no_payloads(self):
        lattice = get_square_lattice(3)
        sym = make_number_range_symbol_set(0, 2)
        sg = SymbolGrid(lattice, sym)

        sc = ShapeConstrainer(lattice, [
            Shape([
                Vector(0, 0),
                Vector(0, 1),
                Vector(1, 0),
            ]),
            Shape([
                Vector(0, 1),
                Vector(1, 0),
                Vector(1, 1),
                Vector(2, 1),
            ]),
            Shape([
                Vector(0, 0),
                Vector(0, 1),
            ]),
        ],
                              solver=sg.solver,
                              complete=True)

        for p in lattice.points:
            sg.solver.add(sg.cell_is(p, sc.shape_type_grid[p]))

        self.assertTrue(sg.solve())
        solved_grid = sg.solved_grid()
        expected = [
            [0, 0, 1],
            [0, 1, 1],
            [2, 2, 1],
        ]
        for p in lattice.points:
            self.assertEqual(solved_grid[p], expected[p.y][p.x])
        self.assertTrue(sg.is_unique())
Beispiel #8
0
def main():
    """Battleship solver example."""
    sg = grilops.SymbolGrid(LATTICE, SYM)
    sc = ShapeConstrainer(LATTICE, [
        Shape([Vector(0, i) for i in range(4)]),
        Shape([Vector(0, i) for i in range(3)]),
        Shape([Vector(0, i) for i in range(3)]),
        Shape([Vector(0, i) for i in range(2)]),
        Shape([Vector(0, i) for i in range(2)]),
        Shape([Vector(0, i) for i in range(2)]),
        Shape([Vector(0, i) for i in range(1)]),
        Shape([Vector(0, i) for i in range(1)]),
        Shape([Vector(0, i) for i in range(1)]),
    ],
                          solver=sg.solver,
                          allow_rotations=True)

    # Constrain the given ship segment counts and ship segments.
    for y, count in enumerate(GIVENS_Y):
        sg.solver.add(
            PbEq([(Not(sg.cell_is(Point(y, x), SYM.X)), 1)
                  for x in range(WIDTH)], count))
    for x, count in enumerate(GIVENS_X):
        sg.solver.add(
            PbEq([(Not(sg.cell_is(Point(y, x), SYM.X)), 1)
                  for y in range(HEIGHT)], count))
    for p, s in GIVENS.items():
        sg.solver.add(sg.cell_is(p, s))

    for p in LATTICE.points:
        shape_type = sc.shape_type_grid[p]
        shape_id = sc.shape_instance_grid[p]
        touching_types = [
            n.symbol
            for n in LATTICE.vertex_sharing_neighbors(sc.shape_type_grid, p)
        ]
        touching_ids = [
            n.symbol for n in LATTICE.vertex_sharing_neighbors(
                sc.shape_instance_grid, p)
        ]

        # Link the X symbol to the absence of a ship segment.
        sg.solver.add((sc.shape_type_grid[p] == -1) == sg.cell_is(p, SYM.X))

        # Ship segments of different ships may not touch.
        and_terms = []
        for touching_id in touching_ids:
            and_terms.append(
                Implies(shape_id >= 0,
                        Or(touching_id == shape_id, touching_id == -1)))
        sg.solver.add(And(*and_terms))

        # Choose the correct symbol for each ship segment.
        touching_count_terms = [(c == shape_type, 1) for c in touching_types]
        sg.solver.add(
            Implies(And(shape_type >= 0, PbEq(touching_count_terms, 2)),
                    sg.cell_is(p, SYM.B)))
        sg.solver.add(
            Implies(And(shape_type >= 0, PbEq(touching_count_terms, 0)),
                    sg.cell_is(p, SYM.O)))
        for n in sg.edge_sharing_neighbors(p):
            sg.solver.add(
                Implies(
                    And(shape_type >= 0, PbEq(touching_count_terms, 1),
                        sc.shape_type_grid[n.location] == shape_type),
                    sg.cell_is(p, DIR_TO_OPPOSITE_SYM[n.direction])))

    if sg.solve():
        sg.print()
        print()
        sc.print_shape_instances()
        print()
        if sg.is_unique():
            print("Unique solution")
        else:
            print("Alternate solution")
            sg.print()
            print()
            sc.print_shape_instances()
            print()
    else:
        print("No solution")
Beispiel #9
0
LetterColor.declare("letter_color", ("letter", IntSort()),
                    ("color", IntSort()))
LetterColor = LetterColor.create()


def letter_color(letter: str, color: Color) -> ExprRef:
    """Creates a LetterColor z3 constant."""
    return LetterColor.letter_color(SYM[letter],
                                    color.value)  # type: ignore[attr-defined]


SHAPES: List[Shape] = [
    Shape([
        (Vector(0, 1), letter_color("R", Color.BLUE)),
        (Vector(1, 0), letter_color("R", Color.BLUE)),
        (Vector(1, 1), letter_color("E", Color.BLUE)),
        (Vector(1, 2), letter_color("V", Color.BLUE)),
        (Vector(2, 1), letter_color("R", Color.BLUE)),
    ]),
    Shape([
        (Vector(0, 0), letter_color("E", Color.WHITE)),
        (Vector(0, 1), letter_color("R", Color.WHITE)),
        (Vector(0, 2), letter_color("S", Color.YELLOW)),
        (Vector(1, 0), letter_color("A", Color.BLUE)),
        (Vector(1, 2), letter_color("O", Color.BLUE)),
    ]),
    Shape([
        (Vector(0, 0), letter_color("C", Color.YELLOW)),
        (Vector(0, 1), letter_color("L", Color.YELLOW)),
        (Vector(1, 1), letter_color("F", Color.YELLOW)),
        (Vector(1, 2), letter_color("E", Color.BLUE)),