示例#1
0
def main(known):
    s = Solver()
    matrix = [[Int(f"m{x}{y}") for x in range(1, 10)] for y in range(1, 10)]
    for i in range(9):
        for j in range(9):
            v = matrix[i][j]
            if known[i][j]:
                s.add(v == known[i][j])
            else:
                s.add(v >= 1)
                s.add(v <= 9)
    for i in range(9):
        s.add(Distinct(*[matrix[i][j] for j in range(9)]))
        s.add(Distinct(*[matrix[j][i] for j in range(9)]))
    for i in range(3):
        for j in range(3):
            s.add(
                Distinct(*[
                    matrix[3 * i + k][3 * j + l] for k in range(3)
                    for l in range(3)
                ]))
    s.check()
    m = s.model()
    print("Solution:")
    for i in range(9):
        print(*[m[matrix[i][j]] for j in range(9)])
示例#2
0
    def __init__(self, component, assigns):
        self.component = component
        self.assigns = []
        self.bus_assigns = []
        self.constraints = []

        for bus_assign in assigns:
            if isinstance(bus_assign, Z3Assign):
                bus_assign = Z3BusAssign(bus_assign)

            self.constraints += bus_assign.constraints
            self.bus_assigns.append(bus_assign)

            for assign in bus_assign:
                assign.component_constraint(component)
                self.constraints += assign.constraints
                self.assigns.append(assign)

        # Each assignment needs a different Fun
        self.constraints.append(
            Distinct([assign.z3_fun for assign in self.assigns]))

        # Each assignment needs a different Pin
        self.constraints.append(
            Distinct([assign.z3_pin for assign in self.assigns]))

        # Each BusFun needs a different bus
        self.constraints.append(
            Distinct([bus_assign.z3_bus for bus_assign in self.bus_assigns]))
示例#3
0
    def solve_z3(self):

        print("[+] {}".format("Sovling using Z3\n"))

        symbols = {e: Int(e) for e in self.elements}

        # first we build a solver with the general constraints for sudoku puzzles:
        s = Solver()

        # assure that every cell holds a value of [1,9]
        for symbol in symbols.values():
            s.add(Or([symbol == int(i) for i in self.cols]))

        # assure that every row covers every value:
        for row in "ABCDEFGHI":
            s.add(Distinct([symbols[row + col] for col in "123456789"]))

        # assure that every column covers every value:
        for col in "123456789":
            s.add(Distinct([symbols[row + col] for row in "ABCDEFGHI"]))

        # assure that every block covers every value:
        for i in range(3):
            for j in range(3):
                s.add(
                    Distinct([
                        symbols["ABCDEFGHI"[m + i * 3] +
                                "123456789"[n + j * 3]] for m in range(3)
                        for n in range(3)
                    ]))

        # adding sum constraints if provided
        if self.constraints is not None:
            print("[+] {}\n{}".format("Applying constraints",
                                      self.constraints))
            sum_constr = self.get_constraints()
            for c in sum_constr:
                expr = []

                for i in c[0]:
                    expr.append("symbols['" + i + "']")

                s.add(eval("+".join(expr) + "==" + str(c[1])))

        # now we put the assumptions of the given puzzle into the solver:
        for elem, value in self.values.items():
            if value in "123456789":
                s.add(symbols[elem] == value)

        if not s.check() == sat:
            raise Exception("Unsolvable")

        model = s.model()
        values = {e: model.evaluate(s).as_string() for e, s in symbols.items()}

        self.solution = values
示例#4
0
def gen_latin_square_constraints(matrix, order):
    assert len(matrix) == order
    assert len(transpose(matrix)) == order
    numbers = itertools.chain(*matrix)
    range_c = [And(n >= 1, n <= order) for n in numbers]

    row_c = [Distinct(row) for row in matrix]
    col_c = [Distinct(row) for row in transpose(matrix)]

    return range_c + row_c + col_c
示例#5
0
def main():
    """Skyscraper solver example."""
    lattice = grilops.get_square_lattice(SIZE)
    directions = {d.name: d for d in lattice.edge_sharing_directions()}
    sg = grilops.SymbolGrid(lattice, SYM)

    # Each row and each column contains each building height exactly once.
    for y in range(SIZE):
        sg.solver.add(Distinct(*[sg.grid[Point(y, x)] for x in range(SIZE)]))
    for x in range(SIZE):
        sg.solver.add(Distinct(*[sg.grid[Point(y, x)] for y in range(SIZE)]))

    # We'll use the sightlines accumulator to keep track of a tuple storing:
    #   the tallest building we've seen so far
    #   the number of visible buildings we've encountered
    Acc = Datatype("Acc")  # pylint: disable=C0103
    Acc.declare("acc", ("tallest", IntSort()), ("num_visible", IntSort()))
    Acc = Acc.create()  # pylint: disable=C0103

    def accumulate(a, height):
        return Acc.acc(
            If(height > Acc.tallest(a), height, Acc.tallest(a)),
            If(height > Acc.tallest(a),
               Acc.num_visible(a) + 1, Acc.num_visible(a)))

    for x, c in enumerate(GIVEN_TOP):
        sg.solver.add(c == Acc.num_visible(
            grilops.sightlines.reduce_cells(sg, Point(0, x), directions["S"],
                                            Acc.acc(0, 0), accumulate)))
    for y, c in enumerate(GIVEN_LEFT):
        sg.solver.add(c == Acc.num_visible(
            grilops.sightlines.reduce_cells(sg, Point(y, 0), directions["E"],
                                            Acc.acc(0, 0), accumulate)))
    for y, c in enumerate(GIVEN_RIGHT):
        sg.solver.add(c == Acc.num_visible(
            grilops.sightlines.reduce_cells(sg, Point(
                y, SIZE - 1), directions["W"], Acc.acc(0, 0), accumulate)))
    for x, c in enumerate(GIVEN_BOTTOM):
        sg.solver.add(c == Acc.num_visible(
            grilops.sightlines.reduce_cells(sg, Point(
                SIZE - 1, x), directions["N"], Acc.acc(0, 0), accumulate)))

    if sg.solve():
        sg.print()
        print()
        if sg.is_unique():
            print("Unique solution")
        else:
            print("Alternate solution")
            sg.print()
    else:
        print("No solution")
示例#6
0
文件: z3.py 项目: flakas/puzlogic-bot
    def require_unique_row_and_column_cells(self, board):
        constraints = []
        rows = set([x for (x, _, _, _) in board])
        columns = set([y for (_, y, _, _) in board])

        for row in rows:
            cells = [c for (x, _, _, c) in board if x == row]
            constraints.append(Distinct(*cells))

        for column in columns:
            cells = [c for (_, y, _, c) in board if y == column]
            constraints.append(Distinct(*cells))

        return constraints
示例#7
0
def add_sudoku_constraints(sg):
    """Add constraints for the normal Sudoku rules."""
    for y in range(9):
        sg.solver.add(Distinct(*[sg.grid[Point(y, x)] for x in range(9)]))
    for x in range(9):
        sg.solver.add(Distinct(*[sg.grid[Point(y, x)] for y in range(9)]))
    for z in range(9):
        top = (z // 3) * 3
        left = (z % 3) * 3
        cells = [
            sg.grid[Point(y, x)] for y in range(top, top + 3)
            for x in range(left, left + 3)
        ]
        sg.solver.add(Distinct(*cells))
示例#8
0
def killer_sudoku(cages: List[str], cage_sum_grid: List[List[int]]) -> str:
    """Solver for Killer Sudoku minipuzzles."""
    sym = grilops.make_number_range_symbol_set(1, SIZE)
    sg = grilops.SymbolGrid(LATTICE, sym)
    shifter = Shifter(sg.solver)

    # Add normal sudoku constraints.
    for y in range(SIZE):
        sg.solver.add(Distinct(*[sg.grid[Point(y, x)] for x in range(SIZE)]))
    for x in range(SIZE):
        sg.solver.add(Distinct(*[sg.grid[Point(y, x)] for y in range(SIZE)]))
    for z in range(9):
        top = (z // 3) * 3
        left = (z % 3) * 3
        cells = [
            sg.grid[Point(y, x)] for y in range(top, top + 3)
            for x in range(left, left + 3)
        ]
        sg.solver.add(Distinct(*cells))

    # Build a map from each cage label to the cells within that cage.
    cage_cells = defaultdict(list)
    for p in LATTICE.points:
        cage_cells[cages[p.y][p.x]].append(sg.grid[p])

    # The digits used in each cage must be unique.
    for cells_in_cage in cage_cells.values():
        sg.solver.add(Distinct(*cells_in_cage))

    cage_sums = {}
    for p in LATTICE.points:
        cage_sum = cage_sum_grid[p.y][p.x]
        if cage_sum > 0:
            shifted_cage_sum = shifter.given(p, cage_sum)
            cage_label = cages[p.y][p.x]
            assert cage_label not in cage_sums
            cage_sums[cage_label] = shifted_cage_sum

    # Add constraints for cages with given sums.
    for cage_label, shifted_cage_sum in cage_sums.items():
        sg.solver.add(Sum(*cage_cells[cage_label]) == shifted_cage_sum)

    assert sg.solve()
    sg.print()
    print()
    shifter.print_shifts()
    print()
    return shifter.eval_binary()
示例#9
0
def boxes_distinct(g):
    dx = dy = 3
    for j in range(g.height // dy):
        for i in range(g.width // dx):
            g.add(
                Distinct(*(g.digit(x + i * dx, y + j * dy) for y in range(dy)
                           for x in range(dx))))
示例#10
0
文件: loops.py 项目: jaylorch/grilops
    def __add_single_loop_constraints(self):
        solver = self.__symbol_grid.solver
        sym: LoopSymbolSet = self.__symbol_grid.symbol_set

        cell_count = len(self.__symbol_grid.grid)

        for p in self.__symbol_grid.grid:
            v = Int(f"log-{LoopConstrainer._instance_index}-{p.y}-{p.x}")
            solver.add(v >= -cell_count)
            solver.add(v < cell_count)
            self.__loop_order_grid[p] = v

        solver.add(Distinct(*self.__loop_order_grid.values()))

        for p, cell in self.__symbol_grid.grid.items():
            li = self.__loop_order_grid[p]

            solver.add(If(sym.is_loop(cell), li >= 0, li < 0))

            for idx, d1, d2 in self.__all_direction_pairs():
                pi = p.translate(d1)
                pj = p.translate(d2)
                if pi in self.__loop_order_grid and pj in self.__loop_order_grid:
                    solver.add(
                        Implies(
                            And(cell == idx, li > 0),
                            Or(self.__loop_order_grid[pi] == li - 1,
                               self.__loop_order_grid[pj] == li - 1)))
示例#11
0
 def _add_block_conditions(self):
     for i, j in product(range(3), repeat=2):
         blocks = [
             self.symbols[self.rows[m + 3 * i] + self.cols[n + 3 * j]]
             for m, n in product(range(3), repeat=2)
         ]
         self.solver.add(Distinct(blocks))
示例#12
0
def skyscraper(givens: Dict[Direction, List[int]]) -> str:
    """Solver for Skyscraper minipuzzles."""
    sym = grilops.make_number_range_symbol_set(1, SIZE)
    sg = grilops.SymbolGrid(LATTICE, sym)
    shifter = Shifter(sg.solver)

    # Each row and each column contains each building height exactly once.
    for y in range(SIZE):
        sg.solver.add(Distinct(*[sg.grid[Point(y, x)] for x in range(SIZE)]))
    for x in range(SIZE):
        sg.solver.add(Distinct(*[sg.grid[Point(y, x)] for y in range(SIZE)]))

    # We'll use the sightlines accumulator to keep track of a tuple storing:
    #   the tallest building we've seen so far
    #   the number of visible buildings we've encountered
    Acc = Datatype("Acc")  # pylint: disable=C0103
    Acc.declare("acc", ("tallest", IntSort()), ("num_visible", IntSort()))
    Acc = Acc.create()  # pylint: disable=C0103

    def accumulate(a, height):
        return Acc.acc(
            If(height > Acc.tallest(a), height, Acc.tallest(a)),
            If(height > Acc.tallest(a),
               Acc.num_visible(a) + 1, Acc.num_visible(a)))

    for d, gs in givens.items():
        for i, g in enumerate(gs):
            if d.vector.dy != 0:
                g = g - shifter.col_shifts.get(i, 0)
                p = Point(0 if d.vector.dy < 0 else SIZE - 1, i)
            elif d.vector.dx != 0:
                g = g - shifter.row_shifts.get(i, 0)
                p = Point(i, 0 if d.vector.dx < 0 else SIZE - 1)
            sg.solver.add(g == Acc.num_visible(  # type: ignore[attr-defined]
                grilops.sightlines.reduce_cells(
                    sg,
                    p,
                    LATTICE.opposite_direction(d),
                    Acc.acc(0, 0),  # type: ignore[attr-defined]
                    accumulate)))

    assert sg.solve()
    sg.print()
    print()
    shifter.print_shifts()
    print()
    return shifter.eval_binary()
示例#13
0
def init_solver(cols):
    s = Solver()
    for col in cols:
        cond = And(col >= 0,
                   col < len(COLORS))  #possible values for each column
        s.add(cond)
    cond_unicity = Distinct(cols)  #each column is different
    s.add(cond_unicity)
    return s
示例#14
0
def abc_different():
    """
    R(A),R(B),R(C) must all have distinct values.

    Returns
    -------
    Formula
    """
    return Distinct([R(A), R(B), R(C)])
示例#15
0
def main():
  """Sudoku solver example."""
  givens = [
      [5, 3, 0, 0, 7, 0, 0, 0, 0],
      [6, 0, 0, 1, 9, 5, 0, 0, 0],
      [0, 9, 8, 0, 0, 0, 0, 6, 0],
      [8, 0, 0, 0, 6, 0, 0, 0, 3],
      [4, 0, 0, 8, 0, 3, 0, 0, 1],
      [7, 0, 0, 0, 2, 0, 0, 0, 6],
      [0, 6, 0, 0, 0, 0, 2, 8, 0],
      [0, 0, 0, 4, 1, 9, 0, 0, 5],
      [0, 0, 0, 0, 8, 0, 0, 7, 9],
  ]

  sym = grilops.make_number_range_symbol_set(1, 9)
  sg = grilops.SymbolGrid(grilops.get_square_lattice(9), sym)

  for y, given_row in enumerate(givens):
    for x, given in enumerate(given_row):
      if given != 0:
        sg.solver.add(sg.cell_is(Point(y, x), sym[given]))

  for y in range(9):
    sg.solver.add(Distinct(*[sg.grid[Point(y, x)] for x in range(9)]))

  for x in range(9):
    sg.solver.add(Distinct(*[sg.grid[Point(y, x)] for y in range(9)]))

  for z in range(9):
    top = (z // 3) * 3
    left = (z % 3) * 3
    cells = [sg.grid[Point(y, x)] for y in range(top, top + 3) for x in range(left, left + 3)]
    sg.solver.add(Distinct(*cells))

  if sg.solve():
    sg.print()
    print()
    if sg.is_unique():
      print("Unique solution")
    else:
      print("Alternate solution")
      sg.print()
  else:
    print("No solution")
示例#16
0
def freedom_search(language: Language, space, generate_rules_only=False,
                   distinct=False,
                   can_be_same=True):
    rules = set()
    names = language.all_card_names()
    all_vars = list(map(z3.Int, names))

    print(names)
    print(all_vars)

    for cut1 in tqdm(space(1)):
        for cut2 in space(2, cut1):
            for cut3 in space(3, cut1, cut2):
                for sequence in permutations(range(4)):
                    cuts = (cut1, cut2, cut3)
                    rule = freedom_of_spelling(all_vars, cuts, sequence, language, can_be_same)
                    rules.add(rule)

    if distinct:
        rules.add(Distinct(all_vars))
    else:
        for position in range(0, 52):
            at_starting_point = [card == position for card in all_vars]
            rule = AtMost(*at_starting_point, 1)
            rules.add(rule)

    rules.add(rules_all_cards_on_deck(all_vars))

    if generate_rules_only:
        return

    print(len(rules))

    s = Solver()
    s.set('smt.arith.random_initial_value', True)

    # random_seed (unsigned int) random seed (default: 0)
    s.set('random_seed', random.randint(0, 2 ** 8))

    # seed (unsigned int) random seed. (default: 0)
    s.set('seed', random.randint(0, 2 ** 8))

    s.add(rules)
    r = s.check()
    if r == unsat:
        print("no solution")
    elif r == unknown:
        print("failed to solve")
        try:
            print(s.reason_unknown())
            print(s.model())
        except Z3Exception:
            return
    else:
        print(s.model())
示例#17
0
def solve(grid):

    values = parseGrid(grid)
    elements = squares
    symbols = {e: Int(e) for e in elements}

    s = Solver()

    #Each square should have a value in the interval [1,9]
    for element in symbols.values():
        s.add(Or([element == i for i in range(1, 10)]))

    #Then every row should cover every value
    for row in "ABCDEFGHI":
        s.add(Distinct([symbols[row + col] for col in "123456789"]))

    #Then every column should cover every value
    for column in "123456789":
        s.add(Distinct([symbols[row + column] for row in "ABCDEFGHI"]))

    #  Finally every block neighborhood should cover every value
    for i in range(3):
        for j in range(3):
            s.add(
                Distinct([
                    symbols["ABCDEFGHI"[m + i * 3] + "123456789"[n + j * 3]]
                    for m in range(3) for n in range(3)
                ]))

    #Now we fill in the given intial puzzle
    for element, value in values.items():
        if value in "123456789":
            s.add(symbols[element] == value)

    if not s.check() == sat:
        raise Exception("unsolvable")

    model = s.model()
    values = {e: model.evaluate(s).as_string() for e, s in symbols.items()}
    #for key in values:
    #	print(key,'--->', values[key])
    return values
示例#18
0
def _get_variables_and_constraints(grid):
    n = grid.n

    # a variable for each cell
    X = [[Int("x_%s_%s" % (i + 1, j + 1)) for j in range(n)] for i in range(n)]

    # each cell contains a value in {1, ..., n}
    cells_c = [
        And(1 <= X[i][j], X[i][j] <= n) for i in range(n) for j in range(n)
    ]

    # each row contains distinct values
    rows_c = [Distinct(X[i]) for i in range(n)]

    # each column contains distinct values
    cols_c = [Distinct([X[i][j] for i in range(n)]) for j in range(n)]

    # add constraints for inequalities
    ineq_c = []
    for i, row in enumerate(grid.values):
        for j, _ in enumerate(row):
            if j < n - 1:
                ineq = grid.across[i, j]
                if ineq == -1:
                    ineq_c.append(X[i][j] < X[i][j + 1])
                elif ineq == 1:
                    ineq_c.append(X[i][j] > X[i][j + 1])
        if i < n - 1:
            for j, _ in enumerate(row):
                ineq = grid.down[i, j]
                if ineq == -1:
                    ineq_c.append(X[i][j] < X[i + 1][j])
                elif ineq == 1:
                    ineq_c.append(X[i][j] > X[i + 1][j])

    # add constraints for any values provided
    instance_c = [
        X[i][j] == int(grid.values[i, j]) for i in range(n) for j in range(n)
        if grid.values[i, j] != 0
    ]

    return X, cells_c + rows_c + cols_c + ineq_c + instance_c
示例#19
0
def main():
    """Hex kakuro solver example."""
    points = []
    points.extend([Point(1, i) for i in range(-3, 4, 2)])
    points.extend([Point(2, i) for i in range(-4, 5, 2)])
    points.extend([Point(3, -5), Point(3, -3), Point(3, 3), Point(3, 5)])
    points.extend([
        Point(4, -6),
        Point(4, -4),
        Point(4, -2),
        Point(4, 2),
        Point(4, 4),
        Point(4, 6)
    ])
    points.extend([Point(5, -5), Point(5, -3), Point(5, 3), Point(5, 5)])
    points.extend([Point(6, i) for i in range(-4, 5, 2)])
    points.extend([Point(7, i) for i in range(-3, 4, 2)])
    lattice = PointyToppedHexagonalLattice(points)
    sym = grilops.make_number_range_symbol_set(1, 9)
    sg = grilops.SymbolGrid(lattice, sym)

    dirs_by_name = dict(sg.lattice.edge_sharing_directions())
    for entry in SUMS:
        (y, x), dirname, given = entry
        d = dirs_by_name[dirname]
        s = grilops.sightlines.count_cells(sg,
                                           Point(y, x),
                                           d,
                                           count=lambda c: c)
        sg.solver.add(given == s)

    for p in lattice.points:
        for d in [Vector(0, 2), Vector(1, 1), Vector(1, -1)]:
            if p.translate(d.negate()) not in sg.grid:
                q = p
                ps = []
                while q in sg.grid:
                    ps.append(sg.grid[q])
                    q = q.translate(d)
                sg.solver.add(Distinct(*ps))

    if sg.solve():
        sg.print()
        print()
        if sg.is_unique():
            print("Unique solution")
        else:
            print("Alternate solution")
            sg.print()
    else:
        print("No solution")
def Z3Solving(sudoku):
    from z3 import Solver, Int, Or, Distinct, sat

    elements = cross("ABCDEFGHI", "123456789")
    symbols = {e: Int(e) for e in elements}

    # first we build a solver with the general constraints for sudoku puzzles:
    s = Solver()

    # assure that every cell holds a value of [1,9]
    for symbol in symbols.values():
        s.add(Or([symbol == i for i in range(1, 10)]))

    # assure that every row covers every value:
    for row in "ABCDEFGHI":
        s.add(Distinct([symbols[row + col] for col in "123456789"]))

    # assure that every column covers every value:
    for col in "123456789":
        s.add(Distinct([symbols[row + col] for row in "ABCDEFGHI"]))

    # assure that every block covers every value:
    for i in range(3):
        for j in range(3):
            s.add(Distinct([symbols["ABCDEFGHI"[m + i * 3] + "123456789"[n + j * 3]] for m in range(3) for n in range(3)]))

    # now we put the assumptions of the given puzzle into the solver:
    for elem, value in sudoku.values.items():
        if value in "123456789":
            s.add(symbols[elem] == value)

    if not s.check() == sat:
        raise Exception("unsolvable")

    model = s.model()
    values = {e: model.evaluate(s).as_string() for e, s in symbols.items()}
    return Sudoku(values)
示例#21
0
  def __add_single_loop_constraints(self):
    """Internal: There must be exactly one loop in the grid.
    
    This method uses the concept of a 'loop order'. """
    solver = self.__symbol_grid.solver
    sym: LoopSymbolSet = self.__symbol_grid.symbol_set

    cell_count = len(self.__symbol_grid.grid)

    # Loop orders are constrained in [-cell_count, cell_count)
    for p in self.__symbol_grid.grid:
      v = Int(f"log-{LoopConstrainer._instance_index}-{p.y}-{p.x}")
      solver.add(v >= -cell_count)
      solver.add(v < cell_count)
      self.__loop_order_grid[p] = v

    # All loop orders must be distinct
    solver.add(Distinct(*self.__loop_order_grid.values()))

    for p, cell in self.__symbol_grid.grid.items():
      li = self.__loop_order_grid[p]

      # Cells on the loop have positive loop order, cells not on the loop
      # have negative loop order.
      solver.add(If(sym.is_loop(cell), li >= 0, li < 0))

      # Look at all possible cells that can come before / after on the path.
      for idx, d1, d2 in self.__all_direction_pairs():
        pi = p.translate(d1)
        pj = p.translate(d2)
        if pi in self.__loop_order_grid and pj in self.__loop_order_grid:
          # If the cell is using this direction pair (cell == idx)
          # AND the cell is on the loop (and not 0), one of the cells before /
          # after must be offset by 1 from this cell. Imagine indicating the
          # 'start' of the loop with loop order 0. This forces a
          # 'directionality' on the loop. Start at any arbitrary point on the
          # loop, this condition means that you must be able to descend towards
          # 0, while remaining on the loop. By descent, every cell must reach
          # 0 while remaining on the loop, so every cell must be part of the
          # same loop.

          solver.add(Implies(
              And(cell == idx, li > 0),
              Or(
                  self.__loop_order_grid[pi] == li - 1,
                  self.__loop_order_grid[pj] == li - 1
              )
          ))
示例#22
0
def find_queens():
    from z3 import Int, And, Distinct, Solver

    queens = [Int(f"Q{i+1}") for i in range(8)]
    columns = [And(1 <= q, q <= 8) for q in queens]
    distinct = [Distinct(queens)]
    diags = [
        And(queens[i] - queens[j] != i - j, queens[i] - queens[j] != j - i)
        for i in range(8) for j in range(i)
    ]

    solver = Solver()
    solver.add(columns + distinct + diags)
    solver.check()
    m = solver.model()
    return m
示例#23
0
def main():
    s = Solver()

    X = Int('X')
    Y = Int('Y')
    Z = Int('Z')

    # X, Y, Z: 1-9
    s.add(*[And(cur >= 1, cur <= 9) for cur in (X, Y, Z)])
    s.add(Distinct(X, Y, Z))

    given_number = as_number(X, Y, Z)
    reversed_number = as_number(Z, Y, X)

    high_min_low = symbolic_max(given_number, reversed_number) - symbolic_min(
        given_number, reversed_number)

    high_min_low_rev = as_number(digit_at_pos(high_min_low, 0),
                                 digit_at_pos(high_min_low, 1),
                                 digit_at_pos(high_min_low, 2))

    s.push()
    # Check that it always holds/there is no counterexample:
    total = high_min_low + high_min_low_rev
    s.add(total != 1089)
    res = s.check()

    if res.r == -1:
        print("unsat -> it holds. Example:")
        s.pop()
        s.add(total == 1089)
        s.check()

        mod = s.model()

        print(f"given number: {mod.eval(given_number)}")
        print(f"reversed: {mod.eval(reversed_number)}")
        print(
            f"highest - lowest: {mod.eval(high_min_low)}, reversed: {mod.eval(high_min_low_rev)}"
        )
        print(f"sums to: {mod.eval(total)}")
    else:
        print("sat.")
        print(s.model())
示例#24
0
文件: z38qgamev2.py 项目: pymivn/news
def find_queens():
    from z3 import Int, And, Distinct, Solver, sat, Or

    queens = [Int(f"Q{i+1}") for i in range(8)]
    columns = [And(1 <= q, q <= 8) for q in queens]
    distinct = [Distinct(queens)]
    diags = [
        And(queens[i] - queens[j] != i - j, queens[i] - queens[j] != j - i)
        for i in range(8) for j in range(i)
    ]

    solver = Solver()
    solver.add(columns + distinct + diags)
    while solver.check() == sat:
        m = solver.model()
        yield m

        block = []
        for var in m:
            v = var()
            block.append(v != m[v])

        solver.add(Or(block))
示例#25
0
    inums = []
    for i in inames:
        if i not in ingredients:
            n_i += 1
            ingredients[i] = n_i
        inums.append(ingredients[i])
    all_inums += inums
    # Make SAT clauses for allergens:
    # "a b c (contains x, y)"  =>  (x=a or x=b or x=c) and (y=a or y=b or y=c)
    for a in anames:
        if a not in allergens:
            allergens[a] = Int(a)
        solver.add(Or([allergens[a] == i for i in inums]))

# All variables are distinct ("Each ingredient contains zero or one allergen",
# i.e. no ingredient occurs twice or more among the solution.)
solver.add(Distinct(list(allergens.values())))

# Merry Christmas!!!!!!!!!!!!
solver.check()
m = solver.model()

# *
bad_ingredients = {m[a].as_long() for a in m}
print('*  ', sum(i not in bad_ingredients for i in all_inums))

# ** Oh no, we need the ingredient names again, dfgjh ok
lookup = {v: k for k, v in ingredients.items()}
answer = [(a.name(), lookup[m[a].as_long()]) for a in m]
print('** ', ','.join(i for (a, i) in sorted(answer)))
示例#26
0
def solve(data):
    men_str = data['men_str']
    women_str = data['women_str']
    men_prefer = data['men']
    women_prefer = data['women']

    s = Solver()
    size = len(men_prefer)
    size_range = range(size)
    men_choice = [Int(f'men_choice_{i}') for i in size_range]
    women_choice = [Int(f'women_choice_{i}') for i in size_range]

    for i in size_range:
        s.add(And(men_choice[i] >= 0, men_choice[i] <= size - 1))
        s.add(And(women_choice[i] >= 0, women_choice[i] <= size - 1))

    s.add(Distinct(men_choice))

    for i in size_range:
        s.add(women_choice[i] == _if_x(men_choice, i, 0))

    men_own_choice = [Int(f'men_own_choice_{i}') for i in size_range]
    women_own_choice = [Int(f'women_own_choice_{i}') for i in size_range]

    for m in size_range:
        s.add(men_own_choice[m] == _if_xy(men_choice[m], men_prefer[m], 0))

    for w in size_range:
        s.add(
            women_own_choice[w] == _if_xy(women_choice[w], women_prefer[w], 0))

    men_want = [[Bool(f'men_want_{m}_{w}') for w in size_range]
                for m in size_range]
    women_want = [[Bool(f'women_want_{w}_{m}') for m in size_range]
                  for w in size_range]

    for m in size_range:
        for w in men_prefer[m]:
            s.add(
                men_want[m][w] == (men_prefer[m].index(w) < men_own_choice[m]))

    for w in size_range:
        for m in women_prefer[w]:
            s.add(women_want[w][m] == (
                women_prefer[w].index(m) < women_own_choice[w]))

    for m in size_range:
        for w in size_range:
            s.add(Not(And(men_want[m][w], women_want[w][m])))

    if s.check() != sat:
        raise Exception('not a valid input')

    with open('z3_input.txt', 'w') as f:
        f.write(s.sexpr())

    mdl = s.model()
    with open('z3_model.txt', 'w') as f:
        f.write(str(mdl))
    return {
        women_str[mdl[men_choice[m]].as_long()]: men_str[m]
        for m in size_range
    }
示例#27
0
def main():
    """Greater Than Killer Sudoku solver example."""

    cages = [
        "AABCCDDEE",
        "FFBGGHIJK",
        "FLMNHHIJK",
        "LLMNNOIPP",
        "QQRNSOTTU",
        "VWRSSXTUU",
        "VWYYSXZaa",
        "bccddXZee",
        "bbbdffZgg",
    ]

    cage_sums = {
        "B": 6,
        "D": 16,
        "F": 14,
        "H": 17,
        "I": 9,
        "J": 12,
        "K": 9,
        "L": 20,
        "M": 13,
        "N": 29,
        "O": 4,
        "R": 8,
        "S": 12,
        "V": 8,
        "W": 14,
        "Y": 17,
        "b": 11,
        "d": 11,
        "e": 8,
    }

    sym = grilops.make_number_range_symbol_set(1, 9)
    lattice = grilops.get_square_lattice(9)
    sg = grilops.SymbolGrid(lattice, sym)

    add_sudoku_constraints(sg)

    # Build a map from each cage label to the cells within that cage.
    cage_cells = defaultdict(list)
    for p in lattice.points:
        cage_cells[cages[p.y][p.x]].append(sg.grid[p])

    # The digits used in each cage must be unique.
    for cells_in_cage in cage_cells.values():
        sg.solver.add(Distinct(*cells_in_cage))

    # Add constraints for cages with given sums.
    for cage_label, cage_sum in cage_sums.items():
        sg.solver.add(Sum(*cage_cells[cage_label]) == cage_sum)

    # Add constraints between cage sums.
    def cage_sum_greater(a, b):
        sg.solver.add(Sum(*cage_cells[a]) > Sum(*cage_cells[b]))

    def cage_sum_equal(a, b):
        sg.solver.add(Sum(*cage_cells[a]) == Sum(*cage_cells[b]))

    cage_sum_equal("C", "G")
    cage_sum_greater("J", "E")
    cage_sum_greater("E", "K")
    cage_sum_greater("W", "c")
    cage_sum_greater("c", "b")
    cage_sum_greater("f", "d")
    cage_sum_greater("X", "f")

    if sg.solve():
        sg.print()
        print()
        if sg.is_unique():
            print("Unique solution")
        else:
            print("Alternate solution")
            sg.print()
    else:
        print("No solution")
示例#28
0
from z3 import Solver, EnumSort, Const, Distinct

s = Solver()
Color, (red, green, blue) = EnumSort('Color', ['red', 'green', 'blue'])

a = Const('a', Color)
b = Const('b', Color)
s.add(Distinct(a, b))

s.check()
print(s.model())
# [b = green, a = red]
示例#29
0
 def constraint_distinct(self, iterable):
     """ All elements are different.  """
     self.solver.add(Distinct([self.symbols[elem] for elem in iterable]))
示例#30
0
except IndexError:
    help()

n = check_count_device(superstring)
d = {}
l = []
s = Optimize()

for i in range(n):
    d[abc[i]] = Int(abc[i])
    globals()[abc[i]] = Int(abc[i])
    l.append(abc[i])
    s.add(And(d[abc[i]] >= 0, d[abc[i]] <= n - 1))

s.add(Distinct([d[x] for x in l]))

for i in superstring.split(' '):
    s.add(
        Int('diff_{0}_{1}'.format(i[0], i[1])) == diff(d.get(i[0]), d.get(
            i[1])))
    try:
        final_sum += Int('diff_{0}_{1}'.format(i[0], i[1])) * int(i[2])
    except NameError:
        final_sum = Int('diff_{0}_{1}'.format(i[0], i[1])) * int(i[2])

final_sum2 = Int("final_sum2")
s.add(final_sum == final_sum2)
s.minimize(final_sum)
s.check()
m = s.model()