def to_command(model: ModelRef, before: EncodedState, after: EncodedState) -> Command: for p in before.keys(): installed_before = bool(model.eval(before[p])) installed_after = bool(model.eval(after[p])) if (not installed_before) and installed_after: return Command(CommandSort.INSTALL, p) elif installed_before and (not installed_after): return Command(CommandSort.UNINSTALL, p) return None
def extract_model(m: z3.ModelRef, sig: Signature, label: str = "") -> Model: M = Model(sig) M.label = label z3_to_model_elems = {} # add elements for sort in sorted(sig.sorts): univ = m.get_universe(sorts_to_z3[sort]) assert len(univ) > 0 for e in sorted(univ, key=str): z3_to_model_elems[str(e)] = M.add_elem(str(e), sort) # assign constants for const, sort in sorted(sig.constants.items()): M.add_constant( const, str( m.eval(z3.Const(const, sorts_to_z3[sort]), model_completion=True))) # assign relations for rel, sorts in sorted(sig.relations.items()): univs = [m.get_universe(sorts_to_z3[s]) for s in sorts] for t in itertools.product(*univs): ev = m.eval(z3_rel_func[rel](*t), model_completion=True) if ev: M.add_relation(rel, [str(x) for x in t]) for func, (sorts, _) in sorted(sig.functions.items()): univs = [m.get_universe(sorts_to_z3[s]) for s in sorts] for t in itertools.product(*univs): ev = m.eval(z3_rel_func[func](*t), model_completion=True) M.add_function(func, [str(x) for x in t], str(ev)) return M
def _solution_from_model(self, model: z3.ModelRef) -> SchedulingSolution: plan: List[Set[BehaviorInstance]] = [ set() for _ in range(self._n_steps) ] for s in self._sequences.values(): for i, b in enumerate(s): bhv_fun = self._bhv_dt.get_constructor( b.component_instance().id() + "_" + b.behavior().name() + "_" + str(i)) step = model.eval(self._toint_fun.z3_func()( self._schedule_fun.z3_func()( bhv_fun.z3_func()))).as_long() plan[step].add(b) return SchedulingSolution(plan)
def model_to_first_order_structure( z3model: z3.ModelRef) -> FirstOrderStructure: ''' Convert z3 model to a BareFirstOrderStructure. Note that all declarations of the bare structure are not related to the program's declarations. ''' assert isinstance(z3model, z3.ModelRef), f'{type(z3model)}\n{z3model}' struct = BareFirstOrderStructure({}, {}, {}, {}) # create universe sorts: Dict[str, Sort] = { 'Bool': BoolSort, 'Int': IntSort, } sort_decls: Dict[Sort, SortDecl] = { } # TODO: remove once Universe maps sorts and not SortDecls elements: Dict[Tuple[Sort, z3.ExprRef], Element] = {} z3elements: Dict[Tuple[Sort, Element], z3.ExprRef] = {} for z3sort in sorted(z3model.sorts(), key=str): z3elems = sorted(z3model.get_universe(z3sort), key=str) name = z3sort.name() sort = UninterpretedSort(name) sort.decl = SortDecl(name) sorts[sort.name] = sort sort_decls[sort] = sort.decl struct.univs[sort.decl] = () for i, x in enumerate(z3elems): e = f'{sort.name}{i}' # TODO: someday this will just be i assert (sort, x) not in elements, (sort, i, x, e) elements[sort, x] = e assert (sort, e) not in z3elements, (sort, i, x, e) z3elements[sort, e] = x struct.univs[sort.decl] += (e, ) # interpret relations, constants, functions def _eval_bool(expr: z3.ExprRef) -> bool: assert z3.is_bool(expr), expr ans = z3model.eval(expr, model_completion=True) assert z3.is_bool(ans), (expr, ans) return bool(ans) def _eval_int(expr: z3.ExprRef) -> str: # TODO: this should return int assert z3.is_int(expr), expr ans = z3model.eval(expr, model_completion=True) assert z3.is_int_value(ans), (expr, ans) return str(ans.as_long()) def _eval_elem(sort: Sort) -> Callable[[z3.ExprRef], Element]: def _eval(expr: z3.ExprRef) -> Element: assert sorts[expr.sort().name()] is sort, expr ans = z3model.eval(expr, model_completion=True) assert (sort, ans) in elements, (sort, expr, ans) return elements[sort, ans] return _eval for z3decl in sorted(z3model.decls(), key=str): name = z3decl.name() dom = tuple(sorts[z3decl.domain(i).name()] for i in range(z3decl.arity())) rng = sorts[z3decl.range().name()] decl: Union[RelationDecl, ConstantDecl, FunctionDecl] if rng is BoolSort: decl = RelationDecl(name, tuple(dom), mutable=False) elif len(dom) == 0: decl = ConstantDecl(name, rng, mutable=False) else: decl = FunctionDecl(name, tuple(dom), rng, mutable=False) _eval: Callable[[z3.ExprRef], Union[bool, int, Element]] if rng is BoolSort: _eval = _eval_bool elif rng is IntSort: _eval = _eval_int elif isinstance(rng, UninterpretedSort): _eval = _eval_elem(rng) else: assert False, (decl, rng) domains = [struct.univs[sort_decls[sort]] for sort in dom] fi = { row: _eval( z3decl(*(z3elements[sort, e] for sort, e in zip(dom, row)))) for row in product(*domains) } if isinstance(decl, RelationDecl): assert decl not in struct.rel_interps assert all(isinstance(v, bool) for v in fi.values()) assert all( len(k) == len(dom) and all( e in struct.univs[sort_decls[sort]] for e, sort in zip(k, dom)) for k in fi.keys()) struct.rel_interps[decl] = cast(RelationInterp, fi) elif isinstance(decl, FunctionDecl): assert decl not in struct.func_interps assert all(isinstance(v, Element) for v in fi.values()) if isinstance(rng, UninterpretedSort): assert all(v in struct.univs[sort_decls[rng]] for v in fi.values()) elif rng is IntSort: assert all(isinstance(int(v), int) for v in fi.values()) else: assert False, (decl, rng) assert all( len(k) == len(dom) and all( e in struct.univs[sort_decls[sort]] for e, sort in zip(k, dom)) for k in fi.keys()) struct.func_interps[decl] = cast(FunctionInterp, fi) elif isinstance(decl, ConstantDecl): assert decl not in struct.const_interps assert list(fi.keys()) == [()] v = fi[()] assert isinstance(v, Element) if isinstance(rng, UninterpretedSort): assert v in struct.univs[sort_decls[rng]] elif rng is IntSort: assert isinstance(int(v), int) else: assert False, (decl, rng) struct.const_interps[decl] = cast(Element, fi[()]) return struct
def _old_model_to_trace(z3model: z3.ModelRef, num_states: int, allow_undefined: bool = False) -> Trace: ''' Convert z3 model to Trace with given number of states. If allow_undefined is True, the resulting trace may leave some symbols undefined. ''' trace = Trace(num_states) keys = Z3Translator._get_keys(num_states) def rename(s: str) -> str: return s.replace('!val!', '').replace('@uc_', '') def _eval(expr: z3.ExprRef) -> z3.ExprRef: ans = z3model.eval(expr, model_completion=True) assert bool(ans) is True or bool(ans) is False, (expr, ans) return ans prog = syntax.the_program for z3sort in sorted(z3model.sorts(), key=str): sort = prog.scope.get_sort(str(z3sort)) assert sort is not None univ = z3model.get_universe(z3sort) trace.univs[sort] = tuple(sorted(rename(str(x)) for x in univ)) model_decls = z3model.decls() all_decls = model_decls for z3decl in sorted(all_decls, key=str): z3name = str(z3decl) for i, k in enumerate(keys): if z3name.startswith(k): name = z3name[len(k + '_'):] R = trace.rel_interps[i] C = trace.const_interps[i] F = trace.func_interps[i] break else: name = z3name R = trace.immut_rel_interps C = trace.immut_const_interps F = trace.immut_func_interps decl = prog.scope.get(name) assert not isinstance(decl, syntax.Sort) and \ not isinstance(decl, syntax.SortInferencePlaceholder) if decl is not None: if isinstance(decl, RelationDecl): if decl.arity: rl: RelationInterp = {} domains = [ z3model.get_universe(z3decl.domain(i)) for i in range(z3decl.arity()) ] if not any(x is None for x in domains): # Note: if any domain is None, we silently drop this symbol. # It's not entirely clear that this is an ok thing to do. g = product(*domains) for row in g: relation_expr = z3decl(*row) ans = _eval(relation_expr) rl[tuple(rename(str(col)) for col in row)] = bool(ans) assert decl not in R R[decl] = rl else: ans = z3model.eval(z3decl()) assert decl not in R R[decl] = {(): bool(ans)} elif isinstance(decl, FunctionDecl): fl: FunctionInterp = {} domains = [ z3model.get_universe(z3decl.domain(i)) for i in range(z3decl.arity()) ] if not any(x is None for x in domains): # Note: if any domain is None, we silently drop this symbol. # It's not entirely clear that this is an ok thing to do. g = product(*domains) for row in g: ans = z3model.eval(z3decl(*row)) if z3.is_int_value(ans): ans_str = str(ans.as_long()) else: ans_str = rename(ans.decl().name()) fl[tuple(rename(str(col)) for col in row)] = ans_str assert decl not in F F[decl] = fl else: assert isinstance(decl, ConstantDecl) v = z3model.eval(z3decl()) if z3.is_int_value(v) or isinstance(v, CVC4Int): v_str = str(v.as_long()) else: v_str = rename(v.decl().name()) assert decl not in C C[decl] = v_str else: if name.startswith(TRANSITION_INDICATOR + '_') and z3model.eval(z3decl()): name = name[len(TRANSITION_INDICATOR + '_'):] istr, name = name.split('_', maxsplit=1) i = int(istr) if i < len(trace.transitions): trace.transitions[i] = name else: # TODO: not sure what's going on here with check_bmc and pd.check_k_state_implication # assert False pass if allow_undefined: return trace def get_univ(d: SortDecl) -> Tuple[Element, ...]: if d not in trace.univs: trace.univs[d] = (d.name + '0', ) return trace.univs[d] def arbitrary_interp_r(r: RelationDecl) -> RelationInterp: doms = [get_univ(syntax.get_decl_from_sort(s)) for s in r.arity] return dict.fromkeys(product(*doms), False) def ensure_defined_r(r: RelationDecl) -> None: arb_interp: Optional[RelationInterp] = None for m in (trace.rel_interps if r.mutable else [trace.immut_rel_interps]): if r not in m: if arb_interp is None: arb_interp = arbitrary_interp_r(r) m[r] = arb_interp def arbitrary_interp_c(c: ConstantDecl) -> Element: if isinstance(c.sort, syntax._BoolSort): return 'false' elif isinstance(c.sort, syntax._IntSort): return '0' assert isinstance(c.sort, syntax.UninterpretedSort) sort = c.sort return get_univ(syntax.get_decl_from_sort(sort))[0] def ensure_defined_c(c: ConstantDecl) -> None: arb_interp = arbitrary_interp_c(c) for m in (trace.const_interps if c.mutable else [trace.immut_const_interps]): if c not in m: m[c] = arb_interp def arbitrary_interp_f(f: FunctionDecl) -> FunctionInterp: doms = [get_univ(syntax.get_decl_from_sort(s)) for s in f.arity] image = get_univ(syntax.get_decl_from_sort(f.sort))[0] return dict.fromkeys(product(*doms), image) def ensure_defined_f(f: FunctionDecl) -> None: arb_interp: Optional[FunctionInterp] = None for m in (trace.func_interps if f.mutable else [trace.immut_func_interps]): if f not in m: if arb_interp is None: arb_interp = arbitrary_interp_f(f) m[f] = arb_interp for decl in prog.relations_constants_and_functions(): if isinstance(decl, RelationDecl): ensure_defined_r(decl) elif isinstance(decl, ConstantDecl): ensure_defined_c(decl) elif isinstance(decl, FunctionDecl): ensure_defined_f(decl) else: assert False, decl return trace
def answer_key(m: ModelRef, L) -> int: res = 0 for l in L: res *= 10 res += m.evaluate(l).as_long() return res
def evaluate(self, m: z3.ModelRef): timeslot = m.eval(self.time()).as_long() room = m.eval(self.room()).as_long() lab = None if not self.labs else m.eval(self.lab()).as_long() return {'name': str(self), 'time': timeslot, 'room': room, 'lab': lab, 'faculty': self.faculty}