def addStepCompressedConstraints(self): self.noneVars = [] clauses = [] # None at the step has to be true unless some task is true at # the step. for i in range(len(self.tasks)): self.noneVars.append(z3.Bool("None@" + str(i))) clauses.append(Or(self.noneVars[i],\ *[varTable[i] for var, varTable in self.taskVars.items()])) # If none is true at the step, then no task can be # true. Together, these two sets of constraints make up # bi-implication between the none variable, and no tasks being # accomplished at this step. for t in range(len(self.tasks)): for taskVar, varTable in self.taskVars.items(): clauses.append(Or(Not(self.noneVars[t]),\ Not(varTable[t]))) # If any none variable is true, then the one after it is # true. Because of transitivity, this means that all none # variables after it are true. for i in range(len(self.tasks) - 1): clauses.append(Or(Not(self.noneVars[i]), self.noneVars[i + 1])) for clause in clauses: if self.debugPrint: print "adding clause " + str(clause) self.solver.add(clause)
def addUniqueTaskStepConstraint(self): uniqueTaskStepConstraints = [] # There is at most one task accomplished at any given # timestep. for t in range(len(self.tasks)): tasksLeft = list(self.tasks) while len(tasksLeft) > 0: task = tasksLeft.pop() for otherTask in tasksLeft: uniqueTaskStepConstraints.append(Or(Not(self.taskVars[task][t]), \ Not(self.taskVars[otherTask][t]))) # Each task is accomplished at at most one timestep. for task in self.tasks: timesLeft = range(len(self.tasks)) while len(timesLeft) > 0: time = timesLeft.pop() for otherTime in timesLeft: uniqueTaskStepConstraints.append(Or(Not(self.taskVars[task][time]),\ Not(self.taskVars[task][otherTime]))) for constraint in uniqueTaskStepConstraints: self.solver.add(constraint) if self.debugPrint: print "Added unique task step contraints: " + str( uniqueTaskStepConstraints)
def _test_gate(self, gate, ctrl_ones, trgtvar): """use z3 sat solver to determine triviality of gate Args: gate (Gate): gate to inspect ctrl_ones (BoolRef): z3 condition asserting all control qubits to 1 trgtvar (list(BoolRef)): z3 variables corresponding to latest state of target qubits Returns: bool: if gate is trivial """ trivial = False self.solver.push() try: triv_cond = gate._trivial_if(*trgtvar) except AttributeError: self.solver.add(ctrl_ones) trivial = self.solver.check() == unsat else: if isinstance(triv_cond, bool): if triv_cond and len(trgtvar) == 1: self.solver.add(Not(And(ctrl_ones, trgtvar[0]))) sol1 = self.solver.check() == unsat self.solver.pop() self.solver.push() self.solver.add(And(ctrl_ones, trgtvar[0])) sol2 = self.solver.check() == unsat trivial = sol1 or sol2 else: self.solver.add(And(ctrl_ones, Not(triv_cond))) trivial = self.solver.check() == unsat self.solver.pop() return trivial
def add_nurikabe_constraints(sym, sg, rc): """Add the nurikabe constraints (one connected sea with no 2x2 regions).""" # There must be only one sea, containing all black cells. sea_id = Int("sea-id") for p in sg.lattice.points: sg.solver.add(sg.cell_is(p, sym.W) == (rc.region_id_grid[p] != sea_id)) # Constrain sea_id to be the index of one of the points in # the smallest area, among those areas of size greater than 4. area_to_points = defaultdict(list) for p in sg.lattice.points: area_to_points[AREAS[p.y][p.x]].append(p) area_points = min((ps for ps in area_to_points.values() if len(ps) > 4), key=len) sg.solver.add( Or(*[sea_id == sg.lattice.point_to_index(p) for p in area_points])) # The sea is not allowed to contain 2x2 areas of black cells. for sy in range(HEIGHT - 1): for sx in range(WIDTH - 1): pool_cells = [ sg.grid[Point(y, x)] for y in range(sy, sy + 2) for x in range(sx, sx + 2) ] sg.solver.add( Not(And(*[Not(cell == sym.W) for cell in pool_cells])))
def addTaskConstraints(self): htConstraints = [] for task in self.tasks: # Aggregate the variables indicating this task got done at # a particular time. taskAtTimes = [] for t in range(len(self.tasks)): intervalVars = [] # Did we do the task in any of our intervals? for i, (start, end) in enumerate(task.intervals): # Create a variable for getting done in the interval. intervalVar = z3.Bool( str(task) + "@" + str(t) + "_for_" + str(i)) # The task must be contained within the interval. htConstraints.append(Or(Not(intervalVar),\ self.timeVars[t] >= start)) htConstraints.append(Or(Not(intervalVar),\ self.timeVars[t] + self.world.duration(task.ID) <= end)) intervalVars.append(intervalVar) # For a task to get done at a particular time, that # time must be within one of our intervals. htConstraints.append(Or(Not(self.taskVars[task][t]),\ *intervalVars)) taskAtTimes.append(self.taskVars[task][t]) # For a task to get done at all, it has to get done at # some time. htConstraints.append(Or(Not(self.taskVars[task][-1]), *taskAtTimes)) for constraint in htConstraints: self.solver.add(constraint) if self.debugPrint: print "Added hard task constraints: " + str(htConstraints)
def addDistinctRule(myBools, x, numColors, graph): n = len(graph.items()) for i in range(0, n): # each row for c in range(0, numColors): # each color for c2 in range(c + 1, numColors): # each color x.add(Or(Not(myBools[i][c]), Not(myBools[i][c2]))) # this cell cant be both these colors return x
def _get_sink_phi_zero_formula(self): vars_in_range = self.get_bounds_formula() not_goal = Not(self.goal_expr) no_guard_active = And([ Not(command.guard) for command in self.input_program.module.commands ]) return Implies(And(vars_in_range, not_goal, no_guard_active), 0 == self.env.apply_to_state_valuation(self.phi))
def _get_frame_zero_formula(self): not_goal = Not(self.goal_expr) no_guard_active = And([ Not(command.guard) for command in self.input_program.module.commands ]) return self.env.forall( Implies(And(not_goal, no_guard_active), 0 == self.env.apply_to_state_valuation(self.frame)))
def addAdjacentRule(myBools, x, numColors, graph): n = len(graph.items()) for i in range(0, n): # each row for j in range(0, len(graph[i])): for c in range(0, numColors): # each color if i < graph[i][j]: x.add(Or(Not(myBools[i][c]), Not(myBools[graph[i][j]][c]))) # this cell cant be both these colors return x
def turn(): m = yield {'block': orientation != 0} while True: if gv.action // 10 == 1: direction = 2 * (gv.action % 10) - 1 new_orientation = (m[orientation] + direction) % 4 m = yield {'block': Not(orientation == new_orientation)} else: m = yield {'block': Not(orientation == m[orientation])}
def __init__( self, list_of_tasks, nb_tasks_to_schedule, list_of_time_intervals, kind: Optional[str] = "exact", optional: Optional[bool] = False, ) -> None: super().__init__(optional) problem_function = {"min": PbGe, "max": PbLe, "exact": PbEq} # first check that all tasks from the list_of_optional_tasks are # actually optional if not isinstance(list_of_tasks, list): raise TypeError("list_of_task must be a list") if not isinstance(list_of_time_intervals, list): raise TypeError("list_of_time_intervals must be a list of list") # count the number of tasks that re scheduled in this time interval all_bools = [] for task in list_of_tasks: # for this task, the logic expression is that any of its start or end must be # between two consecutive intervals bools_for_this_task = [] for time_interval in list_of_time_intervals: task_in_time_interval = Bool( "InTimeIntervalTask_%s_%i" % (task.name, uuid.uuid4().int) ) lower_bound, upper_bound = time_interval cstrs = [ task.start >= lower_bound, task.end <= upper_bound, Not( And(task.start < lower_bound, task.end > lower_bound) ), # overlap at start Not( And(task.start < upper_bound, task.end > upper_bound) ), # overlap at end Not(And(task.start < lower_bound, task.end > upper_bound)), ] # full overlap asst = Implies(task_in_time_interval, And(cstrs)) self.set_z3_assertions(asst) bools_for_this_task.append(task_in_time_interval) # only one maximum bool to True from the previous possibilities asst_tsk = PbLe([(scheduled, True) for scheduled in bools_for_this_task], 1) self.set_z3_assertions(asst_tsk) all_bools.extend(bools_for_this_task) # we also have to exclude all the other cases, where start or end can be between two intervals # then set the constraint for the number of tasks to schedule asst_pb = problem_function[kind]( [(scheduled, True) for scheduled in all_bools], nb_tasks_to_schedule ) self.set_z3_assertions(asst_pb)
def findConfig(ships, observations, dimensions=(10, 10)): (M, N) = dimensions NS = len(ships) s = Solver() W = map(lambda (w, h): w, ships) H = map(lambda (w, h): h, ships) (xs, ys, ds) = ([], [], []) for k in range(NS): xs.append(Int('x_%d' % k)) ys.append(Int('y_%d' % k)) ds.append(Bool('d_%d' % k)) #assert that x,y are in the dimensions' range s.add(xs[k] < M, xs[k] >= 0, ys[k] < N, ys[k] >= 0) occupied = dict() observe = dict() for i in range(M): occupied[i] = dict() observe[i] = dict() for j in range(N): occupied[i][j] = dict() observe[i][j] = False for k in range(NS): rect1 = rect(xs[k], ys[k], W[k], H[k], i, j) rect2 = rect(xs[k], ys[k], H[k], W[k], i, j) occupied[i][j][k] = Or(And(ds[k], rect1), And(Not(ds[k]), rect2)) observe[i][j] = Or(occupied[i][j][k], observe[i][j]) sumvar = 0 for ((i, j), hit) in observations: if hit: s.add(observe[i][j]) else: s.add(Not(observe[i][j])) for i in range(M): for j in range(N): sumvar = If(observe[i][j], 1, 0) + sumvar s.add(sumvar == getAreaCount(ships)) if s.check() == sat: model = s.model() output = [] for k in range(NS): output.append((model[xs[k]].as_long(), model[ys[k]].as_long(), is_true(model[ds[k]]))) return output else: #print "UNSAT!" return "UNSAT"
def move(): m = yield {'block': Not(And(x == 1, y == 1))} while True: if gv.action // 10 == 2: if m[orientation] == 0: m = yield {'block': y != m[y] + 1} elif m[orientation] == 1: m = yield {'block': x != m[x] + 1} elif m[orientation] == 2: m = yield {'block': y != m[y] - 1} elif m[orientation] == 3: m = yield {'block': x != m[x] - 1} else: m = yield {'block': Not(And(y == m[y], x == m[x]))}
def generate_reaching_constraints(self): visitor = ConditionVisitor() for (start, end), reaching_condition in self.reaching_conditions.items(): or_exprs = [] for condition in reaching_condition: and_exprs = [] for edge in condition: if edge.type == BranchType.UnconditionalBranch: continue if edge.type == BranchType.TrueBranch: and_exprs.append( visitor.simplify(edge.source[-1].condition)) elif edge.type == BranchType.FalseBranch: and_exprs.append( simplify( Not(visitor.simplify( edge.source[-1].condition)))) if and_exprs: or_exprs.append(reduce(And, and_exprs)) if or_exprs: self._reaching_constraints[(start, end)] = simplify( reduce(Or, or_exprs))
def find_if_else_for_node(self, header: MediumLevelILBasicBlock, nodes: list): nodes_to_check = list(nodes) nodes_to_remove = [] while nodes_to_check: ni = nodes_to_check.pop() if not isinstance(ni, MediumLevelILAstCondNode): continue for nj in nodes_to_check: if not isinstance(nj, MediumLevelILAstCondNode): continue if ni.start == nj.start: continue cni = ni.condition cnj = nj.condition if is_true(simplify(cni == Not(cnj))): if cni.decl().name() == 'not': self._make_if_else(nj, ni) nodes_to_check.remove(nj) nodes_to_remove.append(ni) else: self._make_if_else(ni, nj) nodes_to_check.remove(nj) nodes_to_remove.append(nj) break return nodes_to_remove
def is_byte_swap(self): try: self.model_variable() except ModelIsConstrained: return False # Figure out if this might be a byte swap byte_values_len = len(self.byte_values) #print self.byte_values if 1 < byte_values_len <= self.var.src.var.type.width: var = create_BitVec(self.var.src, self.var.src.var.type.width) ordering = list(reversed([ self.byte_values[x] for x in sorted(self.byte_values.keys()) ])) reverse_var = Concat( *reversed([ Extract(i-1, i-8, var) for i in range(len(ordering) * 8, 0, -8) ]) ) if len(ordering) < 4: reverse_var = Concat( Extract( 31, len(ordering)*8, var ), reverse_var ) reversed_ordering = reversed(ordering) reversed_ordering = Concat(*reversed_ordering) # The idea here is that if we add the negation of this, if it's # not satisfiable, then that means there is no value such that # the equivalence does not hold. If that is the case, then this # should be a byte-swapped value. self.solver.add( Not( And( var == ZeroExt( var.size() - len(ordering)*8, Concat(*ordering) ), reverse_var == ZeroExt( reverse_var.size() - reversed_ordering.size(), reversed_ordering ) ) ) ) if self.solver.check() == unsat: return True return False
def _add_postconditions(self, gate, ctrl_ones, trgtqb, trgtvar): """create boolean variables for each qubit the gate is applied to and apply the relevant post conditions. a gate rotating out of the z-basis will not have any valid post-conditions, in which case the qubit state is unknown Args: gate (Gate): gate to inspect ctrl_ones (BoolRef): z3 condition asserting all control qubits to 1 trgtqb (list((QuantumRegister, int))): list of target qubits trgtvar (list(BoolRef)): z3 variables corresponding to latest state of target qubits """ new_vars = [] for qbt in trgtqb: new_vars.append(self._gen_variable(qbt)) try: self.solver.add( Implies(ctrl_ones, gate._postconditions(*(trgtvar + new_vars)))) except AttributeError: pass for i, tvar in enumerate(trgtvar): self.solver.add(Implies(Not(ctrl_ones), new_vars[i] == tvar))
def load_puzzle( url: str) -> Tuple[SymbolGrid, Optional[Callable[[Point, int], str]]]: params = url.split('/') height = int(params[-2]) width = int(params[-3]) givens: PuzzleGivens = parse_url(url) lattice = get_rectangle_lattice(height, width) sym = LoopSymbolSet(lattice) sym.append('EMPTY', chr(0x25AE)) sg = SymbolGrid(lattice, sym) lc = LoopConstrainer(sg, single_loop=True) set_loop_order_zero = False # Construct puzzle from URL for p in sg.lattice.points: if givens[p]: sg.solver.add(sg.cell_is(p, sym.EMPTY)) else: sg.solver.add(Not(sg.cell_is(p, sym.EMPTY))) # Restrict loop order to an empty cell if not set_loop_order_zero: sg.solver.add(lc.loop_order_grid[p] == 0) set_loop_order_zero = True return sg, None
def entails(S, claim): """ Checking the validity of S => claim """ if __debug__: assert isinstance(S, Solver), S assert is_expr(claim), claim logger.debug('premise:\n{}\n'.format(S)) logger.debug('claim:\n{}\n'.format(claim)) # print 'entail' # print S # print claim S.push() S.add(Not(claim)) check_rs = S.check() if check_rs == sat: r = False, S.model() elif check_rs == unsat: r = True, None #unsat, no model elif check_rs == unknown: logger.warn('unknown for {}'.format(S)) r = unknown, None #unknown, error else: raise AssertionError('result: {} for\n{}'.format(check_rs, S)) S.pop() return r
def elimination_ordering(self, n): ord = lambda p, q: self.literal(self.ord[p][q]) if p < q else Not( self.literal(self.ord[q][p])) tord = lambda p, q: 'ord_{p}{q}'.format( p=p, q=q) if p < q else '(not ord_{q}{p})'.format(p=p, q=q) logging.info('Ordering') for i in range(1, n + 1): for j in range(1, n + 1): if i == j: continue for l in range(1, n + 1): if i == l or j == l: continue C = [ -self.ord[i][j] if i < j else self.ord[j][i], -self.ord[j][l] if j < l else self.ord[l][j], self.ord[i][l] if i < l else -self.ord[l][i] ] self.add_clause(C) logging.info('Edges') for e in self.hypergraph.edges(): # PRIMAL GRAPH CONSTRUCTION for i, j in combinations(self.hypergraph.get_edge(e), 2): if i > j: i, j = j, i if i < j: # AS CLAUSE self.add_clause([self.ord[i][j], self.arc[j][i]]) self.add_clause([-self.ord[i][j], self.arc[i][j]]) logging.info('Edges Elimintation') for i in range(1, n + 1): for j in range(1, n + 1): if i == j: continue for l in range(j + 1, n + 1): if i == l: continue # AS CLAUSE self.add_clause([ -self.arc[i][j], -self.arc[i][l], -self.ord[j][l], self.arc[j][l] ]) self.add_clause([ -self.arc[i][j], -self.arc[i][l], self.ord[j][l], self.arc[l][j] ]) # redunant self.add_clause([ -self.arc[i][j], -self.arc[i][l], self.arc[j][l], self.arc[l][j] ]) logging.info('Forbid Self Loops') # forbid self loops for i in range(1, n + 1): # self.stream.write("(assert (not arc_{i}_{i}))\n".format(i=i)) self.add_clause([-self.arc[i][i]])
def add_constraints(self, s, X, t, HOPS, GRID_SZ): nx, ny = self.x, self.y while t < HOPS+1: if((0 <= nx < GRID_SZ) and (0 <= ny < GRID_SZ)): s.add(Not(X[t][nx][ny])) nx, ny = self.next_move() t += 1
def to_z3(node): """Translate a (quantifier-free) ATLAS property to a Z3 constraint """ if isinstance(node, OfNode): raise ValueError if isinstance(node, BinOp): ops = { "=": lambda x, y: x == y, "!=": lambda x, y: x != y, ">": lambda x, y: x > y, ">=": lambda x, y: x >= y, "<": lambda x, y: x < y, "<=": lambda x, y: x <= y, "%": lambda x, y: x % y, "or": lambda x, y: Or(x, y), "and": lambda x, y: And(x, y) } return ops[node.op](to_z3(node.e1), to_z3(node.e2)) elif isinstance(node, BuiltIn): funs = { "abs": lambda x: abs(x[0]), "max": lambda x: symMax(x), "min": lambda x: symMin(x), "not": lambda x: Not(x[0]) } args = [to_z3(a) for a in node.args] return funs[node.fn](args) elif isinstance(node, Nary): ops = {"and": lambda x: And(*x), "or": lambda x: Or(*x)} return ops[node.fn]([to_z3(a) for a in node.args]) else: return node
def not_expr(self, expr): val = expr.value.convert(self) (hit, result) = self.checkCache("Not", [val]) if hit: return result else: return self.cache(Not(val), result)
def no_intersections(belt1: Belt, belt2: Belt): assert isinstance(belt1, Belt) assert isinstance(belt2, Belt) i,j = Consts("i j", IntSort()) return ForAll([i,j], Implies(And(0 <= i, i < belt1.belt_len, 0 <=j, j < belt2.belt_len), Not(belt1[i] == belt2[j])))
def consecutive(cells, hint): return Or([ And([ cell if i <= j < i + hint else Not(cell) for j, cell in enumerate(cells) ]) for i in range(len(cells) - hint + 1) ])
def encodeTarget(target): if target in BOOL_VARS.keys(): return BOOL_VARS[target] elif target[0] in ENUM_VARS.keys(): attrName = target[0] var = ENUM_VARS[attrName] values = target[2] disjunctions = [] for val in values: disjunctions.append( ENUM_VARS[attrName] == ENUM_VALUES[attrName][val]) return Or(disjunctions) elif target[0] in NUMERIC_VARS.keys(): var = NUMERIC_VARS[target[0]] _min = int(target[2][0]) _max = int(target[2][1]) return And(var >= _min, var <= _max) elif target[0] == 'not': return Not(encodeTarget(target[1])) elif target[0] == 'and': return And([encodeTarget(x) for x in target[1:]]) elif target[0] == 'or': return Or([encodeTarget(x) for x in target[1:]]) elif target[0] == '=>': return Implies(encodeTarget(target[1]), encodeTarget(target[2])) elif target == 'true': return True elif target == 'false': return False else: raise NameError( 'could not convert propositional formula to the Z3 format')
def is_tautology(a, solver=None): """ Check if claim is a tautology (always True) EXAMPLES: >>> from z3 import * >>> x,y = Bools('x y') >>> is_tautology(Implies(x,x)) True >>> is_tautology(Implies(x,y)) False >>> is_tautology(x==(x==TRUE)) True >>> is_tautology(Not(x)==(x==FALSE)) True >>> assert is_tautology(TRUE) >>> assert not is_tautology(FALSE) >>> pre_x = Bool('pre_x') >>> f = And(Not(pre_x == FALSE), x == FALSE) >>> g = And(Not(pre_x == TRUE), x == TRUE) >>> assert not is_tautology(Or(f,g),Solver()) """ return check_sat(Not(a), solver) == unsat
def D(self, i, s): """ Return a formula expressing state s_i is different than states [0, s_0, s_1, ..., s_(i-1)]. If s is None then the returned formula expresses state i different than states [0 ... i-1] """ if __debug__: assert i >= 2, 'i ({}) must start from 2!'.format(i) if len(self.state_vars) == 0: return None def S(i, s): """ Return a set (list) consisting of the variables at state i. I.e. x_1i, x_2i, ... """ return [self._at_state(v, i, s) for v in self.state_vars] cur_state = S(i, s) #states s_0 ... s_(j-1) pre_states = [S(i_, s) for i_ in range(i)] if s: #D(s,s+i) = s_i # [0,s_0,s_1,..,s_(i-1)] pre_states = [S(0, None)] + pre_states f = [ Not(self.state_eq(cur_state, pre_state)) for pre_state in pre_states ] return myAnd(f)
def encode_eq(eq, Y): expr = eq.left == eq.right if eq.negated: expr = Not(expr) A = c.as_constraint(expr) B = c.And(*(fp.is_empty() for fp in Y.all_fps())) return as_split_constraints(A, B, eq)
def command_specific_forall(self, z3_formula: z3.ExprRef) -> z3.ExprRef: """ See `ForallMode` documentation. """ if self.forall_mode == ForallMode.FORALL_QUANTIFIER: return ForAll(self._z3_local_var_list, substitute(z3_formula, *self._z3_local_subst)) elif self.forall_mode in [ForallMode.FORALL_MACRO, ForallMode.FORALL_GLOBALS]: result = [] for command in self.input_module.commands: # For every command, we add a conjunct # "No goal" AND "guard of command" >= (conjunction of substituted formulae for corresponding frame variables) result.append(Implies(And(Not(self.smt_program.goal_expr), command.guard), And([ substitute(z3_formula, substitution) for substitution in self.command_to_substs[command] ]) )) return And(result) else: raise ValueError("invalid forall_mode: %s" % self.forall_mode)