示例#1
0
文件: main.py 项目: ryolate/pe
def solve(problem: List[str]) -> int:
    X = [[z3.Int(f"x{i}{j}") for j in range(9)] for i in range(9)]
    solver = z3.Solver()

    for i in range(9):
        for j in range(9):
            solver.add(1 <= X[i][j], X[i][j] <= 9)
    for i in range(9):
        solver.add(z3.Distinct(X[i]))
    for j in range(9):
        solver.add(z3.Distinct([X[i][j] for i in range(9)]))
    for i in range(0, 9, 3):
        for j in range(0, 9, 3):
            solver.add(z3.Distinct(
                [X[i + d // 3][j + d % 3] for d in range(9)]))

    for i in range(9):
        for j in range(9):
            if problem[i+1][j] != '0':
                solver.add(X[i][j] == ord(problem[i+1][j]) - ord('0'))

    if solver.check() != z3.sat:
        print(f"{problem[0]} unsat")
        return 0
    return solver.model().evaluate(X[0][0] * 100 + X[0][1] * 10 + X[0][2]).as_long()
示例#2
0
def classic_constraints(s, cells):
    """Adds the classic sudoku constraints to a z3 solver.

    Args:
        s: z3.Solver instance.
        cells: a 9x9 list of lists, where each element is a z3.Int instance.
    """
    # All values must be 1 <= x <= 9.
    for r in rows():
        for c in cols():
            v = cells[r][c]
            s.add(v >= 1)
            s.add(v <= 9)

    # All cells on the same row must be distinct.
    for r in rows():
        s.add(z3.Distinct(cells[r]))

    # All cells on the same column must be distinct.
    for c in cols():
        col = [cells[r][c] for r in rows()]
        s.add(z3.Distinct(col))

    # All cells in a 3x3 matrix must be distinct.
    offsets = list(itertools.product(range(0, 3), range(0, 3)))
    for r in range(0, 9, 3):
        for c in range(0, 9, 3):
            group_cells = []
            for dy, dx in offsets:
                group_cells.append(cells[r + dy][c + dx])
            s.add(z3.Distinct(group_cells))
    def visitCompare(self, node):
        children = node.getChildren()
        if len(children) == 3:
            left = node.getChildren()[0]
            op = str(node.getChildren()[1])
            if op == "==" or op == "!=":
                right = node.getChildren()[2]
                left_z3 = self.visit(left)
                right_z3 = self.visit(right)
                if z3.is_string(left_z3) and z3.is_string(
                        right_z3) or z3.is_bool(left_z3) and z3.is_bool(
                            right_z3):
                    if op == "==":
                        result = z3.simplify(
                            z3.Not(z3.Distinct(left_z3, right_z3)))
                        return result
                    elif op == "!=":
                        # sys.stderr.write("%s != %s\n" % (left_z3, right_z3))
                        result = z3.simplify(z3.Distinct(left_z3, right_z3))
                        return result
                # elif z3.is_string(left_z3) and z3.is_bool(right_z3):
                #   if op == "==":
                #     pass
                #   elif op == "!=":
                #     pass
                # elif z3.is_bool(left_z3) and z3.is_string(right_z3):
                #   if op == "==":
                #     pass
                #   elif op == "!=":
                #     pass

        # this expression is not supported, so make a predicate variable for it
        predicate = str(node)
        return z3.Bool("PREDICATE_%s" % (predicate))
示例#4
0
def get_diag_constraint(n, queens_x, queens_y):
    queens = list(zip(queens_x, queens_y))
    main_diag_distances = [q[0] - q[1] for q in queens]
    main_diag_constraint = z3.Distinct(main_diag_distances)
    second_diag_distances = [(n - q[0]) - q[1] for q in queens]
    second_diag_constraint = z3.Distinct(second_diag_distances)
    constraint = z3.And(main_diag_constraint, second_diag_constraint)
    return constraint
示例#5
0
文件: grids.py 项目: dplepage/puztool
def unique_rowcols(m):
    '''Returns uniqueness constraints on each row and column of m.

    m can be a Z3Matrix or a numpy array of variables.
    '''
    if isinstance(m, Z3Matrix):
        m = m.M
    h, w = m.shape
    for r in range(h):
        yield z3.Distinct(*m[r, :])
    for c in range(w):
        yield z3.Distinct(*m[:, c])
示例#6
0
def puzzle_2(all_ingredients, all_allergens, inert_ingredients):
    possible_ingredients = list(
        set(all_ingredients.keys()) - inert_ingredients)
    possible_allergens = list(set(all_allergens.keys()))

    solver = z3.Solver()

    assignments = z3.IntVector('allergen', len(possible_allergens))
    for assignment in assignments:
        solver.add(0 <= assignment)
        solver.add(assignment < len(possible_allergens))
    solver.add(z3.Distinct(assignments))

    for ai, allergen in enumerate(possible_allergens):
        conditions = []
        for ii, ingredient in enumerate(possible_ingredients):
            if all_ingredients[ingredient] >= all_allergens[allergen]:
                conditions.append(assignments[ii] == ai)
        solver.add(z3.Or(conditions))

    solver.check()
    model = solver.model()

    matches = []
    for ii, _ in enumerate(assignments):
        matches.append(
            (possible_allergens[model.evaluate(assignments[ii]).as_long()],
             possible_ingredients[ii]))

    matches.sort()
    return (','.join(match[1] for match in matches))
示例#7
0
文件: z3py_test.py 项目: google/pyctr
    def test_eight_queens(self):
        # See https://ericpony.github.io/z3py-tutorial/guide-examples.htm

        def test_fn(queens):
            diagonals = []
            for i in range(8):
                for j in range(i):
                    result = None
                    if i == j:
                        result = True
                    else:
                        result = queens[i] - queens[j] != i - j and queens[
                            i] - queens[j] != j - 1

                    diagonals.append(result)

            return diagonals

        queens = [z3.Int('queens_%i' % (i + 1)) for i in range(8)]
        ranks = [z3.And(1 <= queens[i], queens[i] <= 8) for i in range(8)]
        files = [z3.Distinct(queens)]
        converted_fn = conversion.convert(
            test_fn, z3py, [logical_ops, variables, control_flow])
        diagonals = converted_fn(queens)
        self.assertTrue(can_solve(ranks + files + diagonals))
示例#8
0
    def _synthesize(self, m):
        cm = self.cond.synthesize(m)
        tm = self.exptrue.synthesize(m)
        fm = self.expfalse.synthesize(m)

        cm.clearCache()
        cz3 = cm.toZ3()

        S = z3.Solver()
        S.add(cz3)
        if S.check() == z3.unsat:
            fm.clearCache()
            return fm

        S = z3.Solver()
        S.add(z3.Not(cz3))
        if S.check() == z3.unsat:
            tm.clearCache()
            return tm

        S = z3.Solver()
        tm.clearCache()
        fm.clearCache()
        tz3 = tm.toZ3()
        fz3 = fm.toZ3()
        S.add(z3.Distinct(tz3, fz3))
        if S.check() == z3.unsat:
            tm.clearCache()
            return tm

        obj_ = If(cm, tm, fm)
        return obj_
示例#9
0
def _convert_expr(e, variables_dict):
    if isinstance(e, (bool, int)):
        return e
    if not isinstance(e, Expr):
        raise TypeError()
    if isinstance(e, (BoolVar, IntVar)):
        return variables_dict[e.id]
    else:
        operands = list(
            map(lambda x: _convert_expr(x, variables_dict), e.operands))
        if e.op == Op.NEG:
            return -operands[0]
        elif e.op == Op.ADD:
            ret = operands[0]
            for i in range(1, len(operands)):
                ret = ret + operands[i]
            return ret
        elif e.op == Op.SUB:
            ret = operands[0]
            for i in range(1, len(operands)):
                ret = ret - operands[i]
            return ret
        elif e.op == Op.MUL:
            ret = operands[0]
            for i in range(1, len(operands)):
                ret = ret * operands[i]
            return ret
        elif e.op == Op.MOD:
            ret = operands[0]
            for i in range(1, len(operands)):
                ret = ret % operands[i]
            return ret
        elif e.op == Op.EQ:
            return operands[0] == operands[1]
        elif e.op == Op.NE:
            return operands[0] != operands[1]
        elif e.op == Op.LE:
            return operands[0] <= operands[1]
        elif e.op == Op.LT:
            return operands[0] < operands[1]
        elif e.op == Op.GE:
            return operands[0] >= operands[1]
        elif e.op == Op.GT:
            return operands[0] > operands[1]
        elif e.op == Op.NOT:
            return z3.Not(operands[0])
        elif e.op == Op.AND:
            return z3.And(operands)
        elif e.op == Op.OR:
            return z3.Or(operands)
        elif e.op == Op.XOR:
            return z3.Xor(operands[0], operands[1])
        elif e.op == Op.IFF:
            return operands[0] == operands[1]
        elif e.op == Op.IMP:
            return z3.Or(z3.Not(operands[0]), operands[1])
        elif e.op == Op.IF:
            return z3.If(operands[0], operands[1], operands[2])
        elif e.op == Op.ALLDIFF:
            return z3.Distinct(operands)
示例#10
0
 def to_z3(self):
     z3_constraints = []
     for predicate_name in self.program.get_idb_predicate_names():
         self.reset_fresh_vars()
         predicate = self.get_predicate(predicate_name, self.unroll_limit)
         z3_head_vars = []
         for var_id in range(predicate.arity()):
             z3_fresh_var = self.get_fresh_var(predicate.domain(var_id))
             z3_head_vars.append(z3_fresh_var)
         (z3_body_free_vars,
          z3_body_constraint) = self.pred_to_z3(predicate_name,
                                                self.unroll_limit,
                                                z3_head_vars)
         if DISTINCT_CONSTRAINT:
             vertex_variables = [
                 var for var in z3_head_vars + z3_body_free_vars
                 if var.sort() == VERTEX
             ]
             if vertex_variables:
                 z3_body_constraint = z3.And(z3.Distinct(vertex_variables),
                                             z3_body_constraint)
         z3_constraint = z3.ForAll(
             z3_head_vars,
             predicate(z3_head_vars) == (
                 z3_body_constraint if len(z3_body_free_vars) == 0 else
                 z3.Exists(z3_body_free_vars, z3_body_constraint)))
         z3_constraints.append(z3_constraint)
     return z3_constraints
示例#11
0
def solve(mask, compromise):

    shiftlen = 64 - popcount(mask) - compromise

    bb = z3.BitVec("bb", 64)
    masked_bb = [z3.BitVec(f"masked_bb_{i}", 64) for i in range(2 ** popcount(mask))]
    magic_number = z3.BitVec("magic_number", 64)
    imul_tmp = [z3.BitVec(f"imul_tmp_{i}", 64) for i in range(2 ** popcount(mask))]
    result_index_short = [z3.BitVec(f"result_index_{i}", popcount(mask) + compromise) for i in range(2 ** popcount(mask))]
    
    s = z3.Solver()
    for i in range(2 ** popcount(mask)):
        s.add(masked_bb[i] == pdep(i, mask))
        s.add(imul_tmp[i] == masked_bb[i] * magic_number)
        s.add(result_index_short[i] == z3.Extract(63, 63 - popcount(mask) - compromise + 1, imul_tmp[i]))
    s.add(z3.Distinct(result_index_short))
    # for i in range(2 ** popcount(mask)):
    #     for j in range(i + 1, 2 ** popcount(mask)):
    #         s.add(result_index_short[i] != result_index_short[j])
    s.add(magic_number >= 1)
    time_start = time.time()
    result = s.check()
    time_end = time.time()

    print(f"mask = {hex64(mask)}")
    print(f"compromise = {compromise}")
    print(f"result = {result}")
    print(f"elapsed time = {int(time_end - time_start)} second")

    if result == z3.unsat:
        return False

    print(f"magic_number = {hex64(s.model()[magic_number].as_long())}")

    return True
示例#12
0
def solve(s1, s2, s3):
    global vars
    vars = dict()
    s = set()
    X1 = sep(s, s1)
    X2 = sep(s, s2)
    X3 = sep(s, s3)
    X = [z3.Int('%s' % i) for i in s]
    solver = z3.Solver()
    for i in X:
        solver.add(i >= 0, i <= 9)
    t1 = z3.Int('t1')
    t1 = 0
    t2 = z3.Int('t2')
    t2 = 0
    t3 = z3.Int('t3')
    t3 = 0
    t1 = Ath(t1, X1)
    t2 = Ath(t2, X2)
    t3 = Ath(t3, X3)
    solver.add(t1 + t2 == t3)
    solver.add(z3.Distinct(X))
    res = solver.check()
    if res == z3.sat:
        m = solver.model()
        return (Num(m, X1), Num(m, X2), Num(m, X3))
    elif res == z3.unsat:
        print 'unsat'
    else:
        print 'unknown'
示例#13
0
def solve_z3py(sudoku_problem: str, known_answer=None):
    # http://ericpony.github.io/z3py-tutorial/guide-examples.htm

    s = z3.Solver()
    
    # ソルバーに与える変数を用意する。9*9個の整数であり、特定の座標に入る数字を意味する。
    vals = [[z3.Int(f"val({y},{x})") for y in range(9)] for x in range(9)]

    # 入る数字は1以上9以下であるという制約。
    s.add([z3.And(1 <= vals[y][x], vals[y][x] <= 9) for y in range(9) for x in range(9)])

    # 各々の行には各々の数字がちょうど一つだけ入るという制約。
    s.add([z3.Distinct(vals[y]) for y in range(9)])

    # 各々の列には各々の数字がちょうど一つだけ入るという制約。
    s.add([z3.Distinct([vals[y][x] for y in range(9)]) for x in range(9)])

    # 各々の枠(3*3に区切られた領域)には各々の数字がちょうど一つだけ入るという制約。
    s.add([z3.Distinct([vals[y+i][x+j] for i in range(3) for j in range(3)]) for y in range(0,9,3) for x in range(0,9,3)])

    # 問題文で与えられたヒント(最初から埋まっている数字)も制約として与える。
    for y in range(9):
        for x in range(9):
            if sudoku_problem[y*9+x] != ".":
                n = int(sudoku_problem[y*9+x])
                s.add(vals[y][x] == n)

    # 第2引数で既知の解が与えられている場合、それ以外の解を探索したい。
    # そのため、「既知の解と完全一致してはいけない」という制約を与える。
    if known_answer is not None:
        if re.fullmatch(r"[1-9]{81}", known_answer) is None:
            raise ValueError("error: known_answer is invalid format.")
        s.add(z3.Not(z3.And([vals[y][x] == int(known_answer[y*9+x]) for y in range(9) for x in range(9)])))

    # 充足可能か調べる。充足可能ならば、答えを得てstrにまとめて返す。
    if s.check() == z3.sat:
        m = s.model()
        sudoku_answer_list = list(sudoku_problem)
        for y in range(9):
            for x in range(9):
                sudoku_answer_list[y*9+x] = m.evaluate(vals[y][x]).as_string()
                if sudoku_problem[y*9+x] != ".":
                    assert sudoku_answer_list[y*9+x] == sudoku_problem[y*9+x]
        return "".join(sudoku_answer_list)

    #充足不可能だったので問題文をそのまま返す。
    return sudoku_problem
示例#14
0
def add_killer_cage(s, cage_coords, cage_sum):
    '''Add a single killer sudoku cage.
    Takes a list of (row, col) coordinates and the sum
    '''
    cagecells = [X[i][j] for i, j in cage_coords]
    # Digits dont repeat within cages
    s.add(z3.Distinct(cagecells))
    s.add(z3.Sum(cagecells) == cage_sum)
示例#15
0
    def add_cage_constraints(self, cage):
        cage_sum = int(cage[:2])
        cage_vars = []
        for r, c in zip(cage[2::2], cage[3::2]):
            cage_vars.append(self._grid[int(r) - 1][int(c) - 1])

        self._solver.add(z3.Distinct(cage_vars))
        self._solver.add(z3.Sum(cage_vars) == cage_sum)
示例#16
0
文件: grids.py 项目: dplepage/puztool
 def constraints(self):
     yield from super().constraints()
     for _, subgrid in iter_blocks(self.M, self.shape.sqrt()):
         yield z3.Distinct(*subgrid.flat)
     if self.clues is not None:
         for p, v in index(self.clues):
             if v is not None:
                 yield self.M[p] == v
示例#17
0
def make_sbox(s, vecs):
    upper_half, lower_half = vecs
    #rows and columns
    for i in range(MAXVAL):
        #upper
        s.add(z3.Distinct(*(upper_half(i, j) for j in range(MAXVAL))))
        s.add(z3.Distinct(*(upper_half(j, i) for j in range(MAXVAL))))
        #lower
        s.add(z3.Distinct(*(lower_half(i, j) for j in range(MAXVAL))))
        s.add(z3.Distinct(*(lower_half(j, i) for j in range(MAXVAL))))
        #distinct link
        s.add(z3.Distinct(*(lower_half(j,upper_half(i,j)) \
            for j in range(MAXVAL))))
    #get model
    if s.check() == z3.unsat:
        print z3.unsat
        exit()
    m = s.model()
    #fix upper_half
    resolved_upper = [[m.eval(upper_half(i,j)).as_long() \
        for j in range(MAXVAL)] for i in range(MAXVAL)]
    fixed_upper = [[0 for _ in range(MAXVAL)] for _ in range(MAXVAL)]
    for i in range(MAXVAL):
        for j in range(MAXVAL):
            fixed_upper[j][resolved_upper[i][j]] = i
    #reassemble
    flat = (z3.Concat(z3.BitVecVal(fixed_upper[i][j],MAXBITS), lower_half(i,j)) \
       for j in range(MAXVAL) for i in range(MAXVAL))
    sbox = [m.eval(x, model_completion=True).as_long() for x in flat]

    #print sbox
    def lb642sb64(x):
        x = int(''.join(map(lambda x: bin(x)[2:].zfill(MAXBITS * 2), x)), 2)
        x = hex(x)[2:].replace('L', '')
        return x.zfill(
            (len(x) + 1) // 2 * 2).decode('hex').encode('base64').strip()

    b64_sbox = lb642sb64(sbox)
    print b64_sbox
    fmt_sbox = map(fmt, sbox)
    for row in grouper(fmt_sbox, MAXVAL):
        print row
    with open('/tmp/save.txt', 'w') as f:
        f.write(''.join(b64_sbox))
    return sbox
示例#18
0
def place_constraints_2d(comps, fab_dims, wire_lengths, pack=True):
    '''
        place_constraints :: {Component} -> (int, int) -> [int] -> Bool? -> z3.z3.BoolRef
    '''
    nnode = len(comps)

    frows, fcols = fab_dims

    constraints = []
    if pack:

        def _get_x(bv):
            return z3.Extract(frows + fcols - 1, frows, bv)

        def _get_y(bv):
            return z3.Extract(frows - 1, 0, bv)

        for comp in comps:
            comp.pos = z3.BitVec(comp.name, frows + fcols)
        constraints.append(
            z3.simplify(z3.Distinct(*(c.pos for c in comps)),
                        ':blast-distinct', True))

    else:

        def _get_x(bv):
            return bv[0]

        def _get_y(bv):
            return bv[1]

        for comp in comps:
            comp.pos = (z3.BitVec(comp.name + '_x',
                                  frows), z3.BitVec(comp.name + '_y', fcols))
        constraints.append(
            z3.simplify(
                z3.Distinct(*(z3.Concat(c.pos[0], c.pos[1]) for c in comps)),
                ':blast-distinct', True))

    for comp in comps:
        constraints.append(zu.hamming(_get_x(comp.pos)) == __COMP_X)
        constraints.append(zu.hamming(_get_y(comp.pos)) == __COMP_Y)

    return z3.And(constraints)
示例#19
0
  def solve(self):
    self.cells = [
      [self.cell_var(self.data[j][i], i, j) for i in range(6)]
    for j in range(6)]

    for i in range(6):
      self.solver.add(z3.Distinct(self.cells[i]))
    for j in range(6):
      self.solver.add(z3.Distinct([row[j] for row in self.cells]))

    for i in [0,2,4]:
      for j in [0,3]:
         self.solver.add(z3.Distinct([c for row in self.cells[i:i+2] for c in row[j:j+3]]))

    if self.solver.check() == z3.sat:
      self.model = self.solver.model()
      self.print_answer()
    else:
      print("failed to solve")
示例#20
0
    def add_classic_constraints(self):
        # Digits from 1-9
        for r in range(9):
            for c in range(9):
                v = self._grid[r][c]
                self._solver.add(v >= 1)
                self._solver.add(v <= 9)

        # Distinct digits in row/column
        for i in range(9):
            self._solver.add(z3.Distinct(self._grid[i]))  # Row
            self._solver.add(z3.Distinct([self._grid[r][i]
                                          for r in range(9)]))  # Column

        # Distinct digits in boxes
        offset = list(itertools.product(range(0, 3), range(0, 3)))
        for r in range(0, 9, 3):
            for c in range(0, 9, 3):
                box = [self._grid[r + dy][c + dx] for dy, dx in offset]
                self._solver.add(z3.Distinct(box))
示例#21
0
 def setup_line(self, x0, y0, dx, dy, sum):
     if sum == 0:
         return
     vs = []
     x, y = x0 + dx, y0 + dy
     while (x, y) in self.cells:
         vs.append(self.cells[x, y])
         x += dx
         y += dy
     self.solver.add(z3.Distinct(vs))
     self.solver.add(z3.Sum(vs) == sum)
示例#22
0
def solve_board(B, max_sols):
    """Finds all solutions for a given sudoku board."""
    sz = int(len(B)**.5)
    box = int(sz**.5)

    # initialize z3 objects
    X = [z3.Int('x%s%s' % (1 + (i % sz), 1 + (i // sz))) for i in range(sz**2)]
    s = z3.Solver()

    # load in the unsolved board to z3
    for i in range(len(B)):
        if B[i] == 0:
            s.add(z3.And(0 < X[i], X[i] <= sz))
        else:
            s.add(X[i] == B[i])

    # horizontal and vertical constraints
    s.add([z3.Distinct([X[j + sz * i] for i in range(sz)]) for j in range(sz)])
    s.add([z3.Distinct([X[i + sz * j] for i in range(sz)]) for j in range(sz)])

    # box constraints
    for b in range(sz):
        box_ind = []
        for i in range(box):
            ind = box * (1 + (b % box)) + box * sz * (b // box)
            box_ind += [x + i * sz for x in range(ind - box, ind)]
        s.add(z3.Distinct([X[i] for i in box_ind]))

    num_sols = 0
    Sols = []

    # build that board
    while s.check() == z3.sat:
        num_sols += 1
        m = s.model()
        s.add(z3.Or([i != m[i] for i in X]))
        Sols.append([m[x].as_long() for x in X])
        if max_sols and num_sols >= max_sols:
            break

    return Sols, num_sols
示例#23
0
    def _set_restriction(self):
        N = Z3Solver.GRID_SIZE
        B = Z3Solver.GRID_SIZE // Z3Solver.SUB_GRID_SIZE
        SUB_GRID_SIZE = Z3Solver.SUB_GRID_SIZE

        self.add(*[1 <= grid(i, j) for i, j in product(range(N), repeat=2)])
        self.add(*[grid(i, j) <= 9 for i, j in product(range(N), repeat=2)])

        for row in range(N):
            self.add(z3.Distinct([grid(row, col) for col in range(N)]))

        for col in range(N):
            self.add(z3.Distinct([grid(row, col) for row in range(N)]))

        for row in range(B):
            for col in range(B):
                block = [
                    grid(B * row + i, B * col + j)
                    for i, j in product(range(SUB_GRID_SIZE), repeat=2)
                ]
                self.add(z3.Distinct(block))
示例#24
0
文件: z3py_test.py 项目: google/pyctr
        def test_fn():
            queens = [z3.Int('queens_%i' % (i + 1)) for i in range(8)]
            ranks = [1 <= queens[i] and queens[i] <= 8 for i in range(8)]
            files = [z3.Distinct(queens)]
            diagonals = []
            for i in range(8):
                for j in range(i):
                    if i != j:
                        diagonals.append(
                            abs(queens[i] - queens[j]) != abs(i - j))

            return ranks, files, diagonals
示例#25
0
def part_2_z3():
    foods = get_foods()
    hypoallergenic = get_hypoallergenic_ingredients(foods)

    allergens = set()
    ingredients = set()
    foods_by_allergen = collections.defaultdict(set)
    foods_by_ingredient = collections.defaultdict(set)

    for food in foods:
        for allergen in food.allergens:
            foods_by_allergen[allergen].add(food)
            allergens.add(allergen)

        for ingredient in food.ingredients:
            foods_by_ingredient[ingredient].add(food)
            ingredients.add(ingredient)

    allergens = list(allergens)
    ingredients = list(ingredients - hypoallergenic)

    # List of variables representing possible assignment of ingredient to allergen
    assignments = z3.IntVector('assignment', len(ingredients))
    solver = z3.Solver()

    for assignment in assignments:
        solver.add(0 <= assignment)
        solver.add(assignment < len(allergens))

    solver.add(z3.Distinct(assignments))

    for i, allergen in enumerate(allergens):
        candidates = []

        for j, ingredient in enumerate(ingredients):
            # If set of foods that we know contain allergen_i is a subset of foods containing ingredient_j,
            # then ingredient_j = allergen_i is a possible assignment
            if foods_by_allergen[allergen] <= foods_by_ingredient[ingredient]:
                candidates.append(assignments[j] == i)

        solver.add(z3.Or(candidates))

    assert solver.check() == z3.sat

    model = solver.model()
    matches = []

    for i, assignment in enumerate(assignments):
        assignment = model.evaluate(assignment).as_long()
        matches.append((allergens[assignment], ingredients[i]))

    print(','.join(ingredient for _, ingredient in sorted(matches)))
示例#26
0
文件: z3py_test.py 项目: google/pyctr
        def naive_sudoku():
            # 9x9 matrix of integer variables
            x = [[z3.Int('x_%s_%s' % (i + 1, j + 1)) for j in range(9)]
                 for i in range(9)]

            # each cell contains a value in {1, ..., 9}
            cells_c = [
                1 <= x[i][j] and x[i][j] <= 9 for i in range(9)
                for j in range(9)
            ]

            # each row contains a digit at most once
            rows_c = [z3.Distinct(x[i]) for i in range(9)]

            # each column contains a digit at most once
            cols_c = [
                z3.Distinct([x[i][j] for i in range(9)]) for j in range(9)
            ]

            # each 3x3 square contains a digit at most once
            sq_c = [
                z3.Distinct([
                    x[3 * i0 + i][3 * j0 + j] for i in range(3)
                    for j in range(3)
                ]) for i0 in range(3) for j0 in range(3)
            ]

            sudoku_c = cells_c + rows_c + cols_c + sq_c
            instance = get_instance()
            instance_c = []

            for i in range(9):
                for j in range(9):
                    if instance[i][j] == 0:
                        instance_c.append(True)
                    else:
                        instance_c.append(x[i][j] == instance[i][j])

            return sudoku_c + instance_c
示例#27
0
    def solve(self):
        start_time = time.time()
        # First, create all the symbols the pyramid
        self.walk_pyramid(self.add_constraints)
        # All symbols are distinct
        self.solver.add([z3.Distinct([sym for sym in self.syms.values()])])
        # All symbols range from 1 to sigma(rows)
        self.solver.add(
            [z3.And(s >= 1, s <= len(self.data)) for s in self.syms.values()])

        nb_sols = 0
        total_time = 0
        while self.solver.check() == z3.sat:
            # Get the solution for this model
            model = self.solver.model()
            for n in self.syms.keys():
                sym = model[self.get_sym(n)]
                val = sym.as_long()
                self.data[n - 1] = val

            # Finished timing this solution
            end_time = time.time()

            nb_sols += 1
            self.print_pyramid()
            print("\nSolution #%d took %2.3f second(s)" %
                  (nb_sols, end_time - start_time))

            # Reset the timing
            total_time += end_time - start_time
            start_time = time.time()

            # Add the previous solution as the new constraints
            for n in self.syms.keys():
                sym = model[self.get_sym(n)]
                self.solver.add(sym != sym.as_long())

            # Find the next solution...

        if nb_sols == 0:
            end_time = time.time()
            print("\nNo solutions found! Spent, %2.3f second(s)" %
                  (end_time - start_time))
        else:
            print("Found %d total solution(s) and spent %2.3f second(s)" %
                  (nb_sols, total_time))

        return False

        return True
示例#28
0
文件: z3py_test.py 项目: google/pyctr
        def z3_sudoku():
            # See https://ericpony.github.io/z3py-tutorial/guide-examples.htm
            # 9x9 matrix of integer variables
            x = [[z3.Int('x_%s_%s' % (i + 1, j + 1)) for j in range(9)]
                 for i in range(9)]

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

            # each row contains a digit at most once
            rows_c = [z3.Distinct(x[i]) for i in range(9)]

            # each column contains a digit at most once
            cols_c = [
                z3.Distinct([x[i][j] for i in range(9)]) for j in range(9)
            ]

            # each 3x3 square contains a digit at most once
            sq_c = [
                z3.Distinct([
                    x[3 * i0 + i][3 * j0 + j] for i in range(3)
                    for j in range(3)
                ]) for i0 in range(3) for j0 in range(3)
            ]

            sudoku_c = cells_c + rows_c + cols_c + sq_c
            instance = get_instance()
            instance_c = [
                z3.If(instance[i][j] == 0, True, x[i][j] == instance[i][j])
                for i in range(9) for j in range(9)
            ]

            return sudoku_c + instance_c
 def solveSAT(self, problem):
     """
     args:
         problem : 9×9のintのarray、数独の問題
     return:
         ans : 9×9のintのarray、数独の解答
     """
     solver = z3.Solver()
     x = [[0] * 9 for i in range(9)]
     for i in range(9):
         for j in range(9):
             x[i][j] = z3.Int(str(9 * i + j))
             if problem[i][j] > 0:
                 solver.add(x[i][j] == problem[i][j])
             else:
                 solver.add(x[i][j] > 0)
                 solver.add(x[i][j] < 10)
     for i in range(9):
         solver.add(z3.Distinct(x[i]))
         solver.add(z3.Distinct([row[i] for row in x]))
         solver.add(z3.Distinct(x[1][0], x[2][0]))
         solver.add(
             z3.Distinct([
                 x[i // 3 * 3 + j // 3][i % 3 * 3 + j % 3] for j in range(9)
             ]))
     ans = [[0] * 9 for i in range(9)]
     state = solver.check()
     if state == z3.sat:
         res = solver.model()
         for i in range(9):
             for j in range(9):
                 ans[i][j] = res[x[i][j]].as_long()
     else:
         print(state)
         ans = None
     return ans
示例#30
0
def solve(s1, s2, s3):
    global vars
    vars = dict()
    list1 = list(s1)  #list=[s,e,n,d]
    list2 = list(s2)
    list3 = list(s3)
    #initial list in z3
    for i in list1:
        mk_var(i)

    for i in list2:
        mk_var(i)

    for i in list3:
        mk_var(i)
    #equation
    lhs1 = reduce(lambda a, b: 10 * a + vars[b], list1, 0)
    lhs2 = reduce(lambda a, b: 10 * a + vars[b], list2, 0)
    rhs1 = reduce(lambda a, b: 10 * a + vars[b], list3, 0)

    solver = z3.Solver()
    #distinct
    solver.add(z3.Distinct(get_vars()))
    #equation
    solver.add(lhs1 + lhs2 == rhs1)
    solver.add(vars[list1[0]] != 0)
    solver.add(vars[list2[0]] != 0)
    solver.add(vars[list3[0]] != 0)
    #digital range
    for x in vars:
        solver.add(vars[x] >= z3.IntVal(0))
        solver.add(vars[x] <= z3.IntVal(9))

    res = solver.check()
    if res == z3.sat:
        model = solver.model()

        result = []
        result.append(
            int(reduce(lambda a, b: "%s%s" % (a, model[vars[b]]), list1, '')))
        result.append(
            int(reduce(lambda a, b: "%s%s" % (a, model[vars[b]]), list2, '')))
        result.append(
            int(reduce(lambda a, b: "%s%s" % (a, model[vars[b]]), list3, '')))

        return result
    else:
        return None