def all_persons_have_different_roles(): """ Encode ∀x, y : Xor(x = y, R(x) ≠ R(y)) Either the two Persons x,y are the same or they have different roles. This is an alternative to `abc_different`. Returns ------- Formula """ # We need to declare the variables fist. x = Const('x', Person) # This x defined on the domain of Person y = Const('y', Person) # And this is y return ForAll([x, y],Xor(x == y, R(x) != R(y))) # ForAll expression
def protein_variables( T: CodeRef, seq_variables: Sequence[NucleotideRef], part: Part, offset: int = 0, amino_sort: AminoSort = AminoBitVecSort, ) -> List[AminoRef]: """ A function that generates z3 variables corresponding to the amino acid sequence of the translated Part """ begin = part.location.start - offset end = part.location.end - offset codons = get_codons(seq_variables[begin:end]) if isinstance(T, dict): prot_seq = [ Const(f"{part.name}_{i}", amino_sort) for i, _ in enumerate(codons) ] elif isinstance(T, FuncDeclRef): prot_seq = [ decode(T, codon) for codon in codons ] else: raise TypeError(f"T is not of type CodeRef") return prot_seq
def mk_var(name, vsort): """ Create a variable of type vsort. Examples: >>> from z3 import * >>> v = mk_var('real_v', Real('x').sort()) >>> print v real_v """ if vsort.kind() == Z3_INT_SORT: v = Int(name) elif vsort.kind() == Z3_REAL_SORT: v = Real(name) elif vsort.kind() == Z3_BOOL_SORT: v = Bool(name) elif vsort.kind() == Z3_DATATYPE_SORT: v = Const(name, vsort) else: raise AssertionError,\ 'Cannot handle this sort (s: {}, {})'\ .format(vsort, vsort.kind()) return v
def postgraph_constraints(pregraph, action, postgraph): """ Create a list of assertions that constrain the postgraph's nodes, links, and parent-child relationships appropriately, according to what the graph and action contain. """ i = Const('i', Node) j = Const('j', Node) assertions = [ ForAll( i, Iff( postgraph.has(i), Or( And(graph.has(i), Not(action.has(AtomicAction.rem_action(i)))), action.has(AtomicAction.add_action(i))))), ForAll([i, j], Iff( self.links(i, j), Or( And( And( graph.links(i, j), Not(action.has(AtomicAction.unlink_action(i, j)))), And(Not(action.has(AtomicAction.rem_action(i))), Not(action.has(AtomicAction.rem_action(j))))), action.has(AtomicAction.link_action(i, j))))), ForAll( [i, j], Iff( postgraph.parents(i, j), Or( And( And( graph.parents(i, j), Not(action.has(AtomicAction.unparent_action(i, j)))), And(Not(action.has(AtomicAction.rem_action(i))), Not(action.has(AtomicAction.rem_action(j))))), action.has(AtomicAction.parent_action(i, j))))) ] return assertions
def add_observation_constraints(self, s, planner, ground_actions, length, observations): obsSort = DeclareSort('Obs') orderObs = Function('orderObs', obsSort, IntSort()) orderExec = Function('orderExec', obsSort, IntSort()) obsConsts = [] for i in range(0, len(observations)): o = Const(str(observations[i]), obsSort) obsConsts.append(o) s.add(orderObs(o) == i) for t in range(0, length): # forced_obs = [] for action in ground_actions: index = observations.index_of(action.signature()) if index > -1: obsC = obsConsts[index] # forced_obs.append(planner.action_prop_at(action, t)) s.add( Implies(planner.action_prop_at(action, t), orderExec(obsC) == t)) # s.add(Or(*forced_obs)) x = Const('x', obsSort) y = Const('y', obsSort) # orderSync = Function('order-sync', BoolSort()) s.add( ForAll([x, y], Implies( orderObs(x) < orderObs(y), orderExec(x) < orderExec(y)))) s.add( ForAll([x, y], Implies( orderObs(x) == orderObs(y), orderExec(x) == orderExec(y)))) s.add( ForAll([x, y], Implies( orderObs(x) > orderObs(y), orderExec(x) > orderExec(y))))
def non_intersecting_seg_belt_diag_seg(belt: SegmentedBelt, dseg: Segment): """ all segments of a belt must not intersect a given ordered diagonal segment """ assert isinstance(belt, SegmentedBelt) assert isinstance(dseg, Segment) assert dseg.is_diag i = Const("i", IntSort()) return ForAll([i], Implies(And(0 <= i, i < belt.num_segs), Or(Max(belt.segment(i).p1.x, belt.segment(i).p2.x) < dseg.p1.x, Min(belt.segment(i).p1.x, belt.segment(i).p2.x) > dseg.p2.x, Max(belt.segment(i).p1.y, belt.segment(i).p2.y) < dseg.p1.y, Min(belt.segment(i).p1.y, belt.segment(i).p2.y) > dseg.p2.y)))
def __init__(self, max_segs=None): self.corners_x = Function(f'seg_belt{self._IDX}_x', IntSort(), IntSort()) self.corners_y = Function(f'seg_belt{self._IDX}_y', IntSort(), IntSort()) self.num_segs = Const(f'seg_belt{self._IDX}_num_segs', IntSort()) SOL.add(self.num_segs > 0) if max_segs: SOL.add(self.num_segs <= max_segs) i,j = Consts("i j", IntSort()) SOL.add(ForAll([i], Implies(And(0 <= i, i < self.num_segs), Or(self.segment(i).horizontal(), self.segment(i).vertical())))) self.__class__._IDX += 1
def dna_variables( loc: Location, nucleotide_sort: NucleotideSort = NucleotideBitVecSort ) -> List[NucleotideRef]: """ Creates dna variables for each nucleotide at Location loc: :param loc: :param nucleotide_sort: :return dna_variables: """ return [Const(f"dna_{i}", nucleotide_sort) for i in range(loc.start, loc.end)]
def knights_tell_truths(): """ Encodes 'Knights always tell the truth'. In other terms: for all persons, being a knight implies telling the truth. Returns ------- Formula """ # We need to declare the variables fist. x = Const('x', Person) # This x defined on the domain of Person return ForAll([x], Implies(R(x) == Knight, S(x)))
def code_dict(codons: Sequence[CodonRef] = triplet_dna_codons, amino_sort: AminoSort = AminoBitVecSort) -> CodeRef: """ A function that returns a python Dict[str -> AminoRef] mapping DNA codons to amino acids :param codons: :param amino_sort: :return code: """ return { codon: Const(f"T({codon})", amino_sort) for codon in codons }
def __init__(self): self.belt_x = Function(f'belt{self._IDX}_x', IntSort(), IntSort()) self.belt_y = Function(f'belt{self._IDX}_y', IntSort(), IntSort()) self.belt_len = Const(f'belt{self._IDX}_len', IntSort()) SOL.add(self.belt_len > 0) i,j = Consts("i j", IntSort()) # neighbor condition SOL.add(ForAll([i], Implies(And(i < self.belt_len - 1, i >= 0), neighs(self[i], self[i+1])))) # no intersections SOL.add(ForAll([i, j], Implies(And(i >= 0, i < j, j < self.belt_len), Not(self[i] == self[j])))) self.__class__._IDX += 1
def quantified(self): """ Returns a list of Z3 variables, one for each parameter of this type. """ if self._qf is not None: return self._qf res = [] if isinstance(self.name, tuple): for i, arg in enumerate(self.name[1:]): sort = self.type_sort if not arg.endswith( 'defaults_args') else IntSort() cur = Const("y" + str(i), sort) res.append(cur) self._qf = res return res
def knaves_tell_lies(): """ Encodes 'Knaves always tell lies'. In other terms: for all persons, being a knave implies lying. Returns ------- Formula """ # TASK 1 # Your code here # Don't forget the return statement! x = Const('x', Person) return ForAll([x], Implies(R(x) == Knave, Not(S(x))))
def declareAttrVars(): resetVariables() for attr in conf.subjAttrs: attrName = attr.split(':')[0].strip() attrType = attr.split(':')[1].strip() if attrType == 'bool': BOOL_VARS[attrName] = Bool(attrName) elif attrType == 'enum': values = attr.split(':')[2].strip().split(',') newEnumSort = EnumSort(attrName, values) ENUM_VARS[attrName] = Const(attrName, newEnumSort[0]) ENUM_VALUES[attrName] = {} for enumVal in newEnumSort[1]: ENUM_VALUES[attrName][str(enumVal)] = enumVal elif attrType == 'numeric': NUMERIC_VARS[attrName] = Int(attrName) else: raise NameError('unknown attribute type: ' + attrType)
def __create_grids(self): """Create the grids used to model shape region constraints.""" self.__shape_type_grid: Dict[Point, ArithRef] = {} for p in self.__lattice.points: v = Int(f"scst-{ShapeConstrainer._instance_index}-{p.y}-{p.x}") if self.__complete: self.__solver.add(v >= 0) else: self.__solver.add(v >= -1) self.__solver.add(v < len(self.__shapes)) self.__shape_type_grid[p] = v self.__shape_instance_grid: Dict[Point, ArithRef] = {} for p in self.__lattice.points: v = Int(f"scsi-{ShapeConstrainer._instance_index}-{p.y}-{p.x}") if self.__complete: self.__solver.add(v >= 0) else: self.__solver.add(v >= -1) self.__solver.add(v < len(self.__lattice.points)) self.__shape_instance_grid[p] = v sample_payload = self.__shapes[0].offsets_with_payloads[0][1] if sample_payload is None: self.__shape_payload_grid: Optional[Dict[Point, Payload]] = None else: self.__shape_payload_grid: Optional[Dict[Point, Payload]] = {} if isinstance(sample_payload, ExprRef): sort = sample_payload.sort() elif isinstance(sample_payload, int): sort = IntSort() else: raise Exception( f"Could not determine z3 sort for {sample_payload}") for p in self.__lattice.points: v = Const( f"scsp-{ShapeConstrainer._instance_index}-{p.y}-{p.x}", sort) self.__shape_payload_grid[p] = v
def not_contains(self, p: Point2D): i = Const("i", IntSort()) return (ForAll([i], Implies(And(0 <= i, i < self.num_segs), Not(self.segment(i).contains(p)))))
import sys from z3 import Const, DeclareSort, Function, Solver print(""" S = DeclareSort('S') # Declare an uninterpreted sort S f = Function('f', S, S) # Declare function f : S -> S x = Const('x', S) # Declare constant x : S """) sys.stdin.readline() S = DeclareSort('S') f = Function('f', S, S) x = Const('x', S) print(""" s = Solver() # Create a solver context s.add(x == f(f(x))) # Assert fact 1 s.add(x == f(f(f(x)))) # Assert fact 2 """) sys.stdin.readline() s = Solver() s.add(x == f(f(x))) s.add(x == f(f(f(x)))) print(""" print s # Print solver's state """) sys.stdin.readline() print(">>", s)
def __init__(self, label=''): self.v = Const(f'dirval_{label}{self._IDX}', Dir) self.__class__._IDX += 1
def new_thing(nickname=default_name): return Const(_collision_free_string(nickname), datatype)
def __init__(self, x=None, y=None): x = Const(f"p{self._IDX}_x", IntSort()) if x is None else x y = Const(f"p{self._IDX}_y", IntSort()) if y is None else y self.__class__._IDX += 1 super().__init__(x, y)
def declare_variable(self, elem_variable: Variable): s = elem_variable.get_type().get_engine_obj(self._name) v = Const(elem_variable.name, s) self._solver.declare_var(v) elem_variable.add_engine_object(v)
from z3 import EnumSort, Solver, Function, Const, sat import itertools R, values = EnumSort('R', ('alpha', 'beta', 'gamma')) plus = Function('plus', R, R, R) multiply = Function('multiply', R, R, R) neutral_plus = Const('neutral_plus', R) neutral_multiply = Const('neutral_multiply', R) solver = Solver() for a, b, c in itertools.product(values, repeat=3): # (R, +) is a commutative monoid with identity element 0: # (a + b) + c = a + (b + c) # 0 + a = a + 0 = a # a + b = b + a solver.add(plus(plus(a, b), c) == plus(a, plus(b, c))) solver.add(plus(neutral_plus, a) == a) solver.add(plus(a, neutral_plus) == a) solver.add(plus(a, b) == plus(b, a)) # (R, ⋅) is a monoid with identity element 1: # (a⋅b)⋅c = a⋅(b⋅c) # 1⋅a = a⋅1 = a solver.add(multiply(multiply(a, b), c) == multiply(a, multiply(b, c))) solver.add(multiply(neutral_multiply, a) == a) solver.add(multiply(a, neutral_multiply) == a) # Multiplication left and right distributes over addition:
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]
MansionDT.declare("Butler") MansionDT.declare("Charles") # create finite sort Mansion Mansion = MansionDT.create() # constants for ease of reference a, b, c = Mansion.Agatha, Mansion.Butler, Mansion.Charles # declare predicates killed = Function("killed", Mansion, Mansion, BoolSort()) hates = Function("hates", Mansion, Mansion, BoolSort()) richer = Function("richer", Mansion, Mansion, BoolSort()) # quantified variables x = Const("x", Mansion) y = Const("y", Mansion) e1 = Exists([x], killed(x, a)) e2a = ForAll([x, y], Implies(killed(x, y), hates(x, y))) e2b = ForAll([x, y], Implies(killed(x, y), Not(richer(x, y)))) e3 = ForAll([x], Implies(hates(a, x), Not(hates(c, x)))) e4a = hates(a, a) e4b = hates(a, c) e5 = ForAll([x], Implies(Not(richer(x, a)), hates(b, x))) e6 = ForAll([x], Implies(hates(a, x), hates(b, x))) e7 = ForAll([x], Exists([y], Not(hates(x, y)))) s = Solver() s.add(e1) s.add(e2a)
def const(name, sort): return Const(id_name(name), sort)