def check_bmc(s: Solver, safety: Expr, depth: int, preconds: Optional[Iterable[Expr]] = None, minimize: Optional[bool] = None) -> Optional[Trace]: prog = syntax.the_program if preconds is None: preconds = (init.expr for init in prog.inits()) t = s.get_translator(depth + 1) with s.new_frame(): for precond in preconds: s.add(t.translate_expr(precond)) s.add(t.translate_expr(syntax.New(syntax.Not(safety), depth))) for i in range(depth): s.add(t.translate_expr(New(safety, i))) assert_any_transition(s, t, i, allow_stutter=False) res = s.check() if res == solver.sat: z3m = s.model(minimize=minimize) m = Z3Translator.model_to_trace(z3m, depth + 1) return m elif res == solver.unknown: print('unknown!') return None
def translate_transition(self, t: syntax.DefinitionDecl, index: int = 0) -> z3.ExprRef: new_decl = relativize_decl(t, self._active_rels_mapping, self._active_scope, inline_relax_actives=True) # TODO: hack! relativize_decl doesn't do this, so the expression can be non-closed. # TODO: Should it generate & use an extended scope? typechecker.typecheck_declcontainingexpr(self._active_scope, new_decl) res = self._t.translate_expr( syntax.New(new_decl.as_twostate_formula(self._active_scope), index)) return res
def relax_actives_action_chunk(scope: syntax.Scope, actives: Dict[syntax.SortDecl, syntax.RelationDecl]) \ -> Tuple[Tuple[syntax.ModifiesClause, ...], List[Expr]]: new_mods = [] new_conjs = [] for sort, active_rel in actives.items(): name = scope.fresh(sort.name[0].upper()) ap = syntax.Apply(active_rel.name, (syntax.Id(name), )) expr = syntax.Forall((syntax.SortedVar(name, None), ), syntax.Implies(syntax.New(ap), ap)) new_conjs.append(expr) new_mods.append(syntax.ModifiesClause(actives[sort].name)) return tuple(new_mods), new_conjs
def is_rel_blocking_relax_step( trns: Trace, idx: int, derived_rel: Tuple[List[Tuple[syntax.SortedVar, str]], Expr] ) -> bool: # TODO: probably can obtain the sort from the sortedvar when not using pickle free_vars, derived_relation_formula = derived_rel free_vars_active_clause = syntax.And(*(active_var(v.name, sort_name) for (v, sort_name) in free_vars)) diffing_formula = syntax.Exists([v for (v, _) in free_vars], syntax.And(syntax.And(free_vars_active_clause, derived_relation_formula), syntax.New(syntax.And(free_vars_active_clause, syntax.Not(derived_relation_formula))))) with syntax.the_program.scope.fresh_stack(): with syntax.the_program.scope.n_states(2): diffing_formula.resolve(syntax.the_program.scope, syntax.BoolSort) res = trns.eval(diffing_formula, idx) assert isinstance(res, bool) return cast(bool, res)
def relaxation_action_def(prog: syntax.Program, actives: Optional[Dict[syntax.SortDecl, syntax.RelationDecl]] = None, fresh: bool = True) -> syntax.DefinitionDecl: decrease_name = (prog.scope.fresh('decrease_domain') if fresh else 'decrease_domain') mods: Tuple[syntax.ModifiesClause, ...] = () conjs: List[Expr] = [] if actives is None: actives = active_rel_by_sort(prog) # a conjunct allowing each domain to decrease new_mods, new_conjs = relax_actives_action_chunk(prog.scope, actives) mods += new_mods conjs += new_conjs # constants are active for const in prog.constants(): conjs.append( syntax.New( syntax.Apply( actives[syntax.get_decl_from_sort(const.sort)].name, (syntax.Id(const.name), )))) # functions map active to active for func in prog.functions(): names: List[str] = [] func_conjs = [] for arg_sort in func.arity: arg_sort_decl = syntax.get_decl_from_sort(arg_sort) name = prog.scope.fresh(arg_sort_decl.name[0].upper(), also_avoid=names) names.append(name) func_conjs.append( syntax.New( syntax.Apply(actives[arg_sort_decl].name, (syntax.Id(name), )))) ap_func = syntax.Apply(func.name, tuple(syntax.Id(name) for name in names)) name = prog.scope.fresh('y', also_avoid=names) active_func = syntax.Let( syntax.SortedVar(name, func.sort), ap_func, syntax.New( syntax.Apply( actives[syntax.get_decl_from_sort(func.sort)].name, (syntax.Id(name), )))) conjs.append( syntax.Forall( tuple(syntax.SortedVar(name, None) for name in names), syntax.Implies(syntax.And(*func_conjs), active_func))) # (relativized) axioms hold after relaxation for axiom in prog.axioms(): if not syntax.is_universal(axiom.expr): conjs.append(syntax.relativize_quantifiers(actives, axiom.expr)) # derived relations have the same interpretation on the active domain for rel in prog.derived_relations(): names = [] rel_conjs = [] for arg_sort in rel.arity: arg_sort_decl = syntax.get_decl_from_sort(arg_sort) name = prog.scope.fresh(arg_sort_decl.name[0].upper(), also_avoid=names) names.append(name) rel_conjs.append( syntax.Apply(actives[arg_sort_decl].name, (syntax.Id(name), ))) ap_rel = syntax.Apply(rel.name, tuple(syntax.Id(name) for name in names)) conjs.append( syntax.Forall( tuple(syntax.SortedVar(name, None) for name in names), syntax.Implies(syntax.And(*rel_conjs), syntax.Iff(syntax.New(ap_rel), ap_rel)))) return syntax.DefinitionDecl(is_public_transition=True, num_states=2, name=decrease_name, params=(), mods=mods, expr=syntax.And(*conjs))