def solve(grid): """ . . . .1.1. . .3. """ s = z3.Solver() # Construct atoms to represent the dots Dot = z3.Datatype("Dot") for d in grid.dots(): Dot.declare("dot_{}".format(d)) Dot = Dot.create() dot_atom = {d: getattr(Dot, "dot_{}".format(d)) for d in grid.dots()} # Booleans for each of the points dot = {d: z3.Bool("dot-{}".format(d)) for d in grid.dots()} # Booleans for each of the connectors line = {l: z3.Bool("line-{}".format(l)) for l in grid.lines()} # For each point: if it is on, it must have precisely two adjoining lines activated # If it's off, then there are zero adjoining lines activated bool_to_int = z3.Function("bool_to_int", z3.BoolSort(), z3.IntSort()) s.add(bool_to_int(True) == 1) s.add(bool_to_int(True) != 0) s.add(bool_to_int(False) == 0) s.add(bool_to_int(False) != 1) for d in grid.dots(): # Get all lines coming out of this dot ls = [line[l] for l in d.lines()] sm = z3.Sum(*(bool_to_int(l) for l in ls)) s.add(z3.Implies(dot[d], sm == 2)) s.add(z3.Implies(z3.Not(dot[d]), sm == 0)) # For each line: if it is activated, then the points at both ends are activated for l in line: d1, d2 = l.ends() s.add(z3.Implies(line[l], z3.And(dot[d1], dot[d2]))) # "Is connected to" relationship connected = z3.Function("connected", Dot, Dot, z3.BoolSort()) # For each line: # The Dot at each end is connected to the other iff the line is activated for d1 in grid.dots(): for d2 in grid.dots(): a = dot_atom[d1] b = dot_atom[d2] if (l := grid.line(d1, d2)) is None: # These dots are never connected s.add(connected(a, b) != True) else: s.add(z3.Implies(line[l], connected(a, b))) s.add(z3.Implies(z3.Not(line[l]), z3.Not(connected(a, b))))
def solve(self): self.lamps = {(x,y): self.int01(x,y) for x in range(self.xsize) for y in range(self.ysize)} # No lamps on walls # Numbers count lamps next to node (diagonals don't count) for y in range(self.ysize): for x in range(self.xsize): if self.data[x,y] != ".": self.solver.add(self.lamps[x,y] == 0) if self.data[x,y] in "01234": self.solver.add(z3.Sum(self.lamps_next_to_cell(x,y)) == int(self.data[x,y])) # Every cell is in raycast of a lamp # No lamp is in raycast of another lamp for y in range(self.ysize): for x in range(self.xsize): raycast = z3.Sum(self.raycast_cells(x,y)) self.solver.add(z3.Implies(self.lamps[x,y] == 0, raycast >= 1)) self.solver.add(z3.Implies(self.lamps[x,y] == 1, raycast == 0)) if self.solver.check() == z3.sat: self.model = self.solver.model() self.print_answer() else: print("failed to solve")
def _add_firing_constraints_places(petrinet, marking, solver, variables, backward=False): tag = "bl" if backward else "fl" global _unique_tag places_variables = [z3.Int("{}_{}_{}".format(tag, _unique_tag, p)) for p in range(petrinet.num_places())] _unique_tag += 1 for p in range(petrinet.num_places()): var = places_variables[p] preset = petrinet.transitions_preset({p}, reverse=backward) constraints = [] for t in preset: t_preset = petrinet.places_preset({t}, reverse=backward) constraint = z3.And(variables[t] > 0, z3.And([z3.And(places_variables[q] > 0, var > places_variables[q]) for q in t_preset])) constraints.append(constraint) solver.add(z3.Implies(marking[p] > 0, var == 1)) solver.add(z3.Implies(marking[p] == 0, z3.Implies(var > 0, z3.Or(constraints)))) for t in range(petrinet.num_transitions()): places = petrinet.places_set({t}, pre=True, post=True, reverse=backward) places_reachable = z3.And([places_variables[p] > 0 for p in places]) solver.add(z3.Implies(variables[t] > 0, places_reachable))
def spec_lemma_nr_dmapages_refcnt(kernelstate): conj = [] pid = util.FreshBitVec('pid', dt.pid_t) dmapn = util.FreshBitVec('dmapn', dt.dmapn_t) # General invariant -- a free dma page has no owner conj.append( z3.ForAll([dmapn], z3.Implies( is_dmapn_valid(dmapn), is_pid_valid(kernelstate.dmapages[dmapn].owner) == ( kernelstate.dmapages[dmapn].type != dt.page_type.PAGE_TYPE_FREE)))) # PROC_UNUSED state implies refcount is 0 (sys_clone needs this) conj.append( z3.ForAll( [pid], z3.Implies( is_pid_valid(pid), z3.Implies( kernelstate.procs[pid].state == dt.proc_state.PROC_UNUSED, kernelstate.procs[pid].nr_dmapages() == z3.BitVecVal( 0, dt.size_t))))) # # Correctness definition for `permutation` based refcount kernelstate.procs.nr_dmapages.check( conj, is_owner_valid=is_pid_valid, is_owned_valid=is_dmapn_valid, max_refs=dt.NDMAPAGE, ownerfn=lambda dmapn: kernelstate.dmapages[dmapn].owner) return z3.And(*conj)
def spec_lemma_nr_devs_refcnt(kernelstate): conj = [] pid = util.FreshBitVec('pid', dt.pid_t) devid = util.FreshBitVec('devid', dt.devid_t) # unused procs don't own any devices conj.append( z3.ForAll([devid], z3.Implies( is_pid_valid(kernelstate.pci[devid].owner), kernelstate.procs[kernelstate.pci[devid].owner].state != dt.proc_state.PROC_UNUSED))) conj.append( z3.ForAll( [pid], z3.Implies( kernelstate.procs[pid].state == dt.proc_state.PROC_UNUSED, kernelstate.procs[pid].nr_devs() == z3.BitVecVal(0, dt.size_t)))) # Correctness definition for `permutation` based refcount kernelstate.procs.nr_devs.check( conj, is_owner_valid=is_pid_valid, is_owned_valid=lambda n: z3.BoolVal(True), max_refs=2**dt.devid_t.size(), ownerfn=lambda devid0: kernelstate.pci[devid0].owner) return z3.And(*conj)
def _firewallSendRules(self): p_0 = z3.Const('%s_firewall_send_p_0' % (self.fw), self.ctx.packet) p_1 = z3.Const('%s_firewall_send_p_1' % (self.fw), self.ctx.packet) n_0 = z3.Const('%s_firewall_send_n_0' % (self.fw), self.ctx.node) n_1 = z3.Const('%s_firewall_send_n_1' % (self.fw), self.ctx.node) t_0 = z3.Int('%s_firewall_send_t_0' % (self.fw)) t_1 = z3.Int('%s_firewall_send_t_1' % (self.fw)) t_2 = z3.Int('%s_firewall_send_t_2' % (self.fw)) self.acl_func = z3.Function('%s_acl_func' % (self.fw), self.ctx.packet, z3.BoolSort()) self.constraints.append(z3.ForAll([n_0, p_0, t_0], z3.Implies(self.ctx.send(self.fw, n_0, p_0, t_0), \ z3.Exists([n_1, t_1], \ z3.And(self.ctx.recv(n_1, self.fw, p_0, t_1),\ t_1 < t_0))))) self.constraints.append(z3.ForAll([n_0, p_0, t_0], z3.Implies(\ z3.And(self.ctx.send(self.fw, n_0, p_0, t_0), \ z3.Not(self.acl_func(p_0))), \ z3.Exists([n_1, p_1, t_1], \ z3.And(self.ctx.send(self.fw, n_1, p_1, t_1), \ t_1 + 1 <= t_0, \ self.acl_func(p_1), \ self.ctx.packet.src(p_0) == self.ctx.packet.dest(p_1), \ self.ctx.packet.dest(p_0) == self.ctx.packet.src(p_1), \ self.ctx.src_port(p_0) == self.ctx.dest_port(p_1), \ self.ctx.dest_port(p_0) == self.ctx.src_port(p_1), \ )))))
def assert_any_transition(s: Solver, t: Z3Translator, state_index: int, allow_stutter: bool = False) -> None: prog = syntax.the_program uid = str(state_index) tids = [] for transition in prog.transitions(): tid = z3.Bool(get_transition_indicator(uid, transition.name)) tids.append(tid) s.add( z3.Implies( tid, t.translate_expr( New(transition.as_twostate_formula(prog.scope), state_index)))) if allow_stutter: tid = z3.Bool(get_transition_indicator(uid, '$stutter')) tids.append(tid) frame = syntax.And(*DefinitionDecl._frame(prog.scope, mods=())) s.add(z3.Implies(tid, t.translate_expr(New(frame, state_index)))) s.add(z3.Or(*tids))
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 """ import z3 new_vars = [] for qbt in trgtqb: new_vars.append(self._gen_variable(qbt)) try: self.solver.add( z3.Implies(ctrl_ones, gate._postconditions(*(trgtvar + new_vars)))) except AttributeError: pass for i, tvar in enumerate(trgtvar): self.solver.add(z3.Implies(z3.Not(ctrl_ones), new_vars[i] == tvar))
def merge_queries_new_pred(clauses, queries, decls): if len(queries) > 1: false1 = z3.Bool("CHC_COMP_FALSE") decls.add(false1.decl()) for query in queries: assert (z3.is_quantifier(query) and query.is_forall()) qvars = [ z3.Const(query.var_name(n), query.var_sort(n)) for n in range(0, query.num_vars()) ] body = query.body() assert (body.decl().kind() == z3.Z3_OP_IMPLIES) kids = body.children() assert (kids[1] == z3.BoolVal(False)) newBody = z3.Implies(kids[0], false1) newClause = z3.ForAll(qvars, newBody) clauses.append(newClause) queries.clear() queries.append( z3.ForAll(z3.Bool("CHC_COMP_UNUSED"), z3.Implies(z3.And(false1), z3.BoolVal(False))))
def string_indexOf(x, args): if z3.is_array(x): if str(x.decl()) not in ARRAY_LENGTHS: raise Exception('We do not know how large the underlying array should be thus we cannot include on it') helper_int = z3.Int('__ignore_arr_indexOf_helper_' + randomString()) search_string = createZ3ExpressionFromConstraint(args[0], {}) all = [] presentImplications = [] for i in range(ARRAY_LENGTHS[str(x.decl())]): conditional = z3.Select(x, i) == search_string all.append(conditional) true_imply = z3.Implies(conditional, helper_int <= i) false_imply = z3.Implies(z3.Not(conditional), helper_int > i) presentImplications.append(true_imply) presentImplications.append(false_imply) all = z3.Or(all) GLOBAL_CONSTRAINTS.append(z3.And(z3.Implies(all, z3.And(presentImplications)), z3.Implies(all, helper_int >= 0), z3.Implies(z3.mk_not(all), helper_int == -1))) return helper_int else: if len(args) > 1: return z3.IndexOf(x, createZ3ExpressionFromConstraint(args[0], {}), createZ3ExpressionFromConstraint(args[1], {})) else: return z3.IndexOf(x, createZ3ExpressionFromConstraint(args[0], {}), 0)
def construct_axioms(variables): # List[StatVar] _axioms = [] for var in variables: # A variable must be continuous or categorical, but not both. _axioms.append( z3.And( z3.Or(continuous(var).__z3__, categorical(var).__z3__), z3.Not(z3.And(continuous(var).__z3__, categorical(var).__z3__)))) # If a variable is an explanatory variable and all explanatory variables are categorical, # then the variable must be categorical. # It isn't clear how to reason about whether a variable is an explanatory or explained variable. # _axioms.append(z3.Implies(all_x_variables_categorical(var).__z3__, categorical(var).__z3__)) # Not sure how to reason about test properties like one_x_variable and one_y_variable. # _axioms.append(z3.Not(z3.And(one_x_variable(var).__z3__, one_y_variable(var).__z3__))) # If a variable is normal, then it cannot be categorical. _axioms.append( z3.Implies(normal(var).__z3__, z3.Not(categorical(var).__z3__))) # If a variable is continuous or ordinal, it must be continuous. _axioms.append( z3.Implies( continuous_or_ordinal(var).__z3__, continuous(var).__z3__)) # If a variable has two categories, then it must be categorical. # _axioms.append(z3.Implies(two_x_variable_categories(var).__z3__, categorical(var).__z3__)) return _axioms
def spec_lemma_nr_pages_refcnt(kernelstate): conj = [] pid = util.FreshBitVec('pid', dt.pid_t) # PROC_UNUSED state implies refcount is 0 (sys_clone needs this) conj.append( z3.ForAll( [pid], z3.Implies( is_pid_valid(pid), z3.Implies( kernelstate.procs[pid].state == dt.proc_state.PROC_UNUSED, kernelstate.procs[pid].nr_pages() == z3.BitVecVal( 0, dt.size_t))))) # Correctness definition for `permutation` based refcount kernelstate.procs.nr_pages.check( conj, is_owner_valid=is_pid_valid, is_owned_valid=is_pn_valid, max_refs=dt.NPAGE, ownerfn=lambda pn: kernelstate.pages[pn].owner) return z3.And(*conj)
def _constraints(self): #self.count_func = z3.Function('count_%s'%(self.node), self.ctx.address, self.ctx.address, \ #z3.IntSort(), z3.IntSort()) p0 = z3.Const('_counter_p0_%s' % (self.node), self.ctx.packet) p1 = z3.Const('_counter_p1_%s' % (self.node), self.ctx.packet) n0 = z3.Const('_counter_n0_%s' % (self.node), self.ctx.node) n1 = z3.Const('_counter_n1_%s' % (self.node), self.ctx.node) n2 = z3.Const('_counter_n2_%s' % (self.node), self.ctx.node) t0 = z3.Int('_counter_t0_%s' % (self.node)) t1 = z3.Int('_counter_t1_%s' % (self.node)) a0 = z3.Const('_counter_a0_%s' % (self.node), self.ctx.address) a1 = z3.Const('_counter_a1_%s' % (self.node), self.ctx.address) # Make sure all packets sent were first recved self.constraints.append(z3.ForAll([n0, p0], \ z3.Implies(self.ctx.send(self.node, n0, p0), \ z3.And( \ z3.Exists([n1], \ z3.And (self.ctx.recv(n1, self.node, p0), \ n0 != n1)), \ z3.Not(z3.Exists([n2], \ z3.And(self.ctx.send(self.node, n2, p0), \ n2 != n0))), \ self.ctx.etime(self.node, p0, self.ctx.send_event) > \ self.ctx.etime(self.node, p0, self.ctx.recv_event))))) # Make sure packets go one at a time self.constraints.append(z3.ForAll([p0, t0], \ z3.Implies(z3.And(self.ctx.etime(self.node, p0, self.ctx.send_event) == t0, \ t0 != 0), \ z3.ForAll([p1], \ z3.Or(p0 == p1, \ self.ctx.etime(self.node, p1, \ self.ctx.send_event) != \ t0)))))
def spec_lemma_nr_ports_refcnt(kernelstate): conj = [] pid = util.FreshBitVec('pid', dt.pid_t) port = util.FreshBitVec('port', dt.uint16_t) # unused procs don't own any ports # valid([port:pid]) ==> [port:pid].state != UNUSED conj.append( z3.ForAll([port], z3.Implies( is_pid_valid(kernelstate.io[port].owner), kernelstate.procs[kernelstate.io[port].owner].state != dt.proc_state.PROC_UNUSED))) # pid.state == UNUSED ==> pid.nr_ports == 0 conj.append( z3.ForAll( [pid], z3.Implies( kernelstate.procs[pid].state == dt.proc_state.PROC_UNUSED, kernelstate.procs[pid].nr_ports() == z3.BitVecVal( 0, dt.size_t)))) # Correctness definition for `permutation` based refcount kernelstate.procs.nr_ports.check( conj, is_owner_valid=is_pid_valid, is_owned_valid=lambda n: z3.BoolVal(True), max_refs=2**dt.uint16_t.size(), ownerfn=lambda port0: kernelstate.io[port0].owner) return z3.And(*conj)
def spec_corollary_pgwalk(kernelstate): pid = util.FreshBitVec('pid', dt.pid_t) va = dt.FreshVA() pml4 = kernelstate.procs[pid].page_table_root # Abstract model of a page_walk starting from some root page, writable, present = page_walk(kernelstate, pml4, *va) # If a four level page-walk from some pid returns a page, # that page must be exclusively owned by the pid. # furthermore, if the page is writable, # it has to be a frame. isolation = util.Implies( present, kernelstate.pages[page].owner == pid, z3.Implies( writable, kernelstate.pages[page].type == dt.page_type.PAGE_TYPE_FRAME)) # valid(pid) & pid.state == active & valid(va) ==> page.owner == pid && page.type == FRAME (active is either EMBRYO, RUNNABLE or RUNNING) return z3.ForAll([pid] + va, z3.Implies( z3.And( is_pid_valid(pid), is_status_live(kernelstate.procs[pid].state), is_va_valid(va), ), isolation))
def _populateLoadBalancerConstraints(self): self.hash_function = z3.Function( 'load_balancer_hash_%s' % (self.balancer), z3.IntSort(), z3.IntSort(), z3.IntSort()) p0 = z3.Const('_load_balancer_p0_%s' % (self.balancer), self.ctx.packet) p1 = z3.Const('_load_balancer_p1_%s' % (self.balancer), self.ctx.packet) n0 = z3.Const('_load_balancer_n0_%s' % (self.balancer), self.ctx.node) n1 = z3.Const('_load_balancer_n1_%s' % (self.balancer), self.ctx.node) n2 = z3.Const('_load_balancer_n2_%s' % (self.balancer), self.ctx.node) hash_same = [self.ctx.packet.src(p0) == self.ctx.packet.src(p1), \ self.ctx.packet.dest(p0) == self.ctx.packet.dest(p1), \ self.hash_function(self.ctx.src_port(p0), self.ctx.dest_port(p0)) == \ self.hash_function(self.ctx.src_port(p1), self.ctx.dest_port(p1)), \ self.ctx.send(self.balancer, n0, p0), \ self.ctx.send(self.balancer, n1, p1) ] self.constraints.append(z3.ForAll([n0, p0, n1, p1], \ z3.Implies(z3.And(hash_same), \ n0 == n1))) self.constraints.append(z3.ForAll([n0, p0], \ z3.Implies(\ self.ctx.send(self.balancer, n0, p0), \ z3.And( \ z3.Exists([n1], \ z3.And(self.ctx.recv(n1, self.balancer, p0), \ n1 != n0)), \ z3.Not(z3.Exists([n2], \ z3.And(n2 != n0, \ self.ctx.send(self.balancer, n2, p0)))), \ self.ctx.etime(self.balancer, p0, self.ctx.send_event) > \ self.ctx.etime(self.balancer, p0, self.ctx.recv_event)))))
def elim_bool_ite(exp): if z3.is_quantifier(exp): (qvars, matrix) = strip_qblock(exp) matrix = elim_bool_ite(matrix) if exp.is_forall(): e = z3.ForAll(qvars, matrix) else: e = z3.Exists(qvars, matrix) return e if not z3.is_bool(exp): return exp if z3.is_true(exp) or z3.is_false(exp): return exp assert z3.is_app(exp) decl = exp.decl() args = map(elim_bool_ite, exp.children()) # need to worry about And and Or because they can take >2 args and # decl(*args) doesn't seem to work with the py interface if z3.is_and(exp): return z3.And(*args) elif z3.is_or(exp): return z3.Or(*args) elif is_ite(exp): impl1 = z3.Implies(args[0], args[1]) impl2 = z3.Implies(z3.Not(args[0]), args[2]) return z3.And(impl1, impl2) else: return decl(*args)
def pages_equiv(conj, ctx, kernelstate): pn = util.FreshBitVec('pn', dt.pn_t) idx = util.FreshBitVec('page_index', 64) conj.append( z3.ForAll([pn, idx], z3.Implies( z3.And(is_pn_valid(pn), z3.ULT(idx, 512)), util.global_to_uf_dict(ctx, '@pages')[()]( util.i64(0), pn, idx) == kernelstate.pages[pn].data(idx)))) conj.append( z3.ForAll( [pn], z3.Implies( is_pn_valid(pn), util.global_field_element(ctx, '@page_desc_table', 'pid', pn) == kernelstate.pages[pn].owner))) conj.append( z3.ForAll( [pn], z3.Implies( is_pn_valid(pn), util.global_field_element(ctx, '@page_desc_table', 'type', pn) == kernelstate.pages[pn].type)))
def check_move(move): """ Given a move, use Z3 to check if it is good or bad. The move is encodeed as a 36-size bit vector as described above. Assumes no player has already won. """ # Initialize and introduce z3 constants solver = z3.Solver() z3_board = [ z3.Const("board_state_" + str(i), z3.BoolSort()) for i in range(27) ] z3_board_res = [ z3.Const("res_board_state_" + str(i), z3.BoolSort()) for i in range(27) ] # Add constraints for input for z3_const, cond in zip(z3_board, move[:27]): solver.add(z3_const if cond else z3.Not(z3_const)) # Add constraints for the fact that z3_board_res is obtained via move on z3_board solver.add(encode_move(z3_board, z3_board_res, move[27:], 1)) # If player one can win, move must be winnig solver.add( z3.Implies(encode_has_winning_move(z3_board, 1), encode_has_won(z3_board_res, 1))) # If player one cannot win, player one should not win in next round solver.add( z3.Implies(z3.Not(encode_has_winning_move(z3_board, 1)), z3.Not(encode_has_winning_move(z3_board_res, 2)))) # Finally, check sat return solver.check() == z3.sat
def finalizePiFun( self, rf_force={} ): # rf_force is a dict of rf-relation: read (KEY) <- write # print log rf_force_local = rf_force.copy( ) # make a copy because we will modify it if DEBUG: mm.printPossibleReadFrom(self._logcat(), self.PiVarList.values(), self.TsThatWritesVar) # add PI function for sname, piVar, ts in self.PiVarList.values(): # k timestamp = ts.timestamp writerTraceSteps = self.TsThatWritesVar[ sname] #mm.possibleRFts(TsThatWritesVar, sname, ts) OrClauses = [] # lookup if the read is registered as a special rf relation read_relId_tuple = self.TsNameToRelLookup[ts.name] if read_relId_tuple in rf_force_local: # ts->tuple->lookup in rf_force (find the write)->back to ref writeTsRef = self.relTsLookupDict[ rf_force_local[read_relId_tuple]] #print writeTsRef.name,ts.name assert writeTsRef is not ts constraint = mm.build_rf_constraint(sname, piVar, self.TsThatWritesVar, read=ts, write=writeTsRef) if ONLY_CONSTRAINT_ON_READABLE_PI: constraint = z3.Implies(ts.decodeExpr, constraint) OrClauses = [constraint] del rf_force_local[read_relId_tuple] else: for traceStep in writerTraceSteps: # i if traceStep is ts: continue constraint = mm.build_rf_constraint(sname, piVar, self.TsThatWritesVar, read=ts, write=traceStep) if ONLY_CONSTRAINT_ON_READABLE_PI: constraint = z3.Implies(ts.decodeExpr, constraint) OrClauses.append(constraint) # special case: # read from initial (rf_init) if len(OrClauses) == 0: print '<E>: no writer for state: ', sname, '. It should at least appear in the init steps.' assert False elif len(OrClauses) == 1: self.ConstraintList.append(OrClauses[0]) else: self.ConstraintList.append(z3.Or(OrClauses))
def wp(self, Q): """ wp(while[inv](b){s},Q) == inv and (inv and b => (wp(s,inv))) and (inv and not b => Q) See lec7.pdf """ f2 = z3.Implies(z3.And(self.inv, self.b), self.s.wp(self.inv)) f3 = z3.Implies(z3.And(self.inv, z3.Not(self.b)), Q) return z3.simplify(z3.And([self.inv, f2, f3]))
def check_valid(bounds, bound2s, ref, ref2, pre, lc, rec, s): s.add( z3.Not( z3.And( z3.Implies(pre, z3.And(*bounds, z3.And(*ref))), z3.Implies(z3.And(*bounds, z3.And(*ref), lc, rec), z3.And(*bound2s, z3.And(*ref2)))))) res = s.check() return res
def walk_ite(self, formula, args): i = args[0] t = args[1] e = args[2] if self._get_type(formula) == types.BOOL: return z3.And(z3.Implies(i, t), z3.Implies(z3.Not(i), e)) else: return z3.If(i, t, e)
def walk_ite(self, formula, args, **kwargs): i = args[0] t = args[1] e = args[2] if self._get_type(formula).is_bool_type(): return z3.And(z3.Implies(i, t), z3.Implies(z3.Not(i), e)) else: return z3.If(i, t, e)
def solve(self): # get puzzle dimensions num_rows = len(self.input_grid) num_cols = len(self.input_grid[0]) # declaring matrix of Bool variables X = [[z3.Bool("x_%s_%s" % (i, j)) for i in range(num_rows)] for j in range(num_cols)] # boundary conditions instance_c = [z3.If(self.input_grid[i][j] == None, True, X[i][j] == self.input_grid[i][j]) for i in range(num_rows) for j in range(num_cols)] # sur chaque colonne ou ligne de la grille, il ne peut y avoir plus de deux 0 ou deux 1 consécutifs row_combo = [z3.Implies(X[i][j] == X[i][j + 1], z3.Not(X[i][j + 2] == X[i][j])) for j in range(num_cols - 2) for i in range(num_rows)] ''' TODO not working row_combo = [ z3.And( z3.Or(z3.Not(X[i][j+1]), z3.Not(X[i][j+2])), z3.Or(X[i][j], X[i][j+1], z3.Not(X[i][j+2])), z3.Or(z3.Not(X[i][j]), z3.Not(X[i][j+1]), X[i][j+2]), z3.Or(X[i][j+1], X[i][j+2]) ) for j in range(num_cols-2) for i in range(num_rows)] ''' col_combo = [z3.Implies(X[i][j] == X[i + 1][j], z3.Not(X[i + 2][j] == X[i][j])) for i in range(num_cols - 2) for j in range(num_rows)] # il y a le même nombre de 0 et de 1 sur chaque ligne et chaque colonne combs = set(itertools.permutations( [0 for _ in range(num_rows // 2)] + [1 for _ in range(num_rows // 2)], r=num_rows)) row_par = [z3.Or([z3.And([X[i][j] if coefs[j] == 1 else z3.Not(X[i][j]) for j in range(num_cols)]) for coefs in combs]) for i in range(num_rows)] col_par = [True] # il n’y a pas deux lignes (ou deux colonnes) remplies identiquement row_eg = [True] col_eg = [True] # add condition to the solver binero_c = row_combo + col_combo + row_par + col_par + row_eg + col_eg self.solver.add(instance_c + binero_c) # solve if self.solver.check() == z3.sat: m = self.solver.model() r = [[m.evaluate(X[i][j]) for j in range(num_cols)] for i in range(num_rows)] output_grid = [[1 if r[i][j] == True else 0 for j in range(num_cols)] for i in range(num_rows)] BineroIO.write_binero(self.PATH + "/output/" + self.filename, output_grid) else: print("failed to solve")
def _float_binary_operator(self, term, op): logger.debug('_fbo: %s\n%s', term, self.attrs[term]) x = self.eval(term.x) y = self.eval(term.y) z = op(x, y) conds = [] if 'nnan' in self.attrs[term]: df = z3.And(z3.Not(z3.fpIsNaN(x)), z3.Not(z3.fpIsNaN(y)), z3.Not(z3.fpIsNaN(z))) conds.append(z3.Implies(self.attrs[term]['nnan'], df)) elif 'nnan' in term.flags: conds += [ z3.Not(z3.fpIsNaN(x)), z3.Not(z3.fpIsNaN(y)), z3.Not(z3.fpIsNaN(z)) ] if 'ninf' in self.attrs[term]: df = z3.And(z3.Not(z3.fpIsInf(x)), z3.Not(z3.fpIsInf(y)), z3.Not(z3.fpIsInf(z))) conds.append(z3.Implies(self.attrs[term]['ninf'], df)) elif 'ninf' in term.flags: conds += [ z3.Not(z3.fpIsInf(x)), z3.Not(z3.fpIsInf(y)), z3.Not(z3.fpIsInf(z)) ] if 'nsz' in self.attrs[term] or 'nsz' in term.flags: # NOTE: this will return a different qvar for each (in)direct reference # to this term. Is this desirable? b = self.fresh_bool() self.add_qvar(b) z = op(x, y) c = z3.fpIsZero(z) if 'nsz' in self.attrs[term]: c = z3.And(self.attrs[term]['nsz'], c) s = _ty_sort(self.type(term)) z = z3.If(c, z3.If(b, 0, z3.fpMinusZero(s)), z) if isinstance(term, FDivInst): c = [z3.Not(z3.fpIsZero(x)), z3.fpIsZero(y)] if 'nsz' in self.attrs[term]: c.append(self.attrs[term]['nsz']) z = z3.If( z3.And(c), z3.If(b, z3.fpPlusInfinity(s), z3.fpMinusInfinity(s)), z) return self._conditional_value(conds, z, term.name)
def split_query(self): """Split query if it is not simple into a query and a rule""" assert (self.is_query()) if self.is_simple_query(): return (self, None) q = z3.Bool("simple!!query") query = HornRule(z3.Implies(q, z3.BoolVal(False))) rule = HornRule( z3.ForAll(self._bound_constants, z3.Implies(z3.And(*self.body()), q))) return query, rule
def _consistency_constraints(self): conjuncts = [] for v in self._domain: if (v.unique): expr = z3.Implies(Formula._id(v), Formula._id(v.opposite())) else: expr = z3.Implies(z3.Not(Formula._id(v)), z3.Not(Formula._id(v.opposite()))) conjuncts.append(expr) return z3.And(conjuncts)
def z3_check_implies(e1, e2, for_all=False): """Check whether there is a solution to the implication of the two expressions""" solver.push() if for_all: solver.add(z3.Not(z3.Implies(e1, e2))) else: solver.add(z3.Implies(e1, e2)) result = solver.check() solver.pop() if for_all: return result.r == z3.Z3_L_FALSE else: return result.r == z3.Z3_L_TRUE
def _idsSendRules(self): p_0 = z3.Const('%s_p_0' % (self.node), self.ctx.packet) n_0 = z3.Const('%s_n_0' % (self.node), self.ctx.node) n_1 = z3.Const('%s_n_1' % (self.node), self.ctx.node) t_0 = z3.Int('%s_t_0' % self.node) t_1 = z3.Int('%s_t_1' % self.node) self.constraints.append(z3.ForAll([n_0, p_0, t_0], z3.Implies(self.ctx.send(self.node, n_0, p_0, t_0), \ z3.Exists([n_1, t_1], \ z3.And(self.ctx.recv(n_1, self.node, p_0, t_1), \ t_1 < t_0))))) self.constraints.append(z3.ForAll([n_0, p_0, t_0], \ z3.Implies(z3.And(self.ctx.send(self.node, n_0, p_0, t_0), \ self.suspicious(p_0)), \ n_0 == self.shunt)))