def as_onestate_formula(self, index: Optional[int] = None) -> Expr: # TODO: move to class State, this shouldn't be here assert self.num_states == 1 or index is not None, \ 'to generate a onestate formula from a multi-state model, ' + \ 'you must specify which state you want' assert index is None or (0 <= index and index < self.num_states) if index is None: index = 0 if index not in self.onestate_formula_cache: prog = syntax.the_program mut_rel_interps = self.rel_interps[index] mut_const_interps = self.const_interps[index] mut_func_interps = self.func_interps[index] vs: List[syntax.SortedVar] = [] ineqs: Dict[SortDecl, List[Expr]] = {} rels: Dict[RelationDecl, List[Expr]] = {} consts: Dict[ConstantDecl, Expr] = {} funcs: Dict[FunctionDecl, List[Expr]] = {} for sort in self.univs: vs.extend(syntax.SortedVar(v, syntax.UninterpretedSort(sort.name)) for v in self.univs[sort]) u = [syntax.Id(v) for v in self.univs[sort]] ineqs[sort] = [syntax.Neq(a, b) for a, b in combinations(u, 2)] for R, l in chain(mut_rel_interps.items(), self.immut_rel_interps.items()): rels[R] = [] for tup, ans in l.items(): e: Expr = ( syntax.AppExpr(R.name, tuple(syntax.Id(col) for col in tup)) if tup else syntax.Id(R.name) ) rels[R].append(e if ans else syntax.Not(e)) for C, c in chain(mut_const_interps.items(), self.immut_const_interps.items()): consts[C] = syntax.Eq(syntax.Id(C.name), syntax.Id(c)) for F, fl in chain(mut_func_interps.items(), self.immut_func_interps.items()): funcs[F] = [ syntax.Eq(syntax.AppExpr(F.name, tuple(syntax.Id(col) for col in tup)), syntax.Id(res)) for tup, res in fl.items() ] # get a fresh variable, avoiding names of universe elements in vs fresh = prog.scope.fresh('x', [v.name for v in vs]) e = syntax.Exists(tuple(vs), syntax.And( *chain(*ineqs.values(), *rels.values(), consts.values(), *funcs.values(), ( syntax.Forall((syntax.SortedVar(fresh, syntax.UninterpretedSort(sort.name)),), syntax.Or(*(syntax.Eq(syntax.Id(fresh), syntax.Id(v)) for v in self.univs[sort]))) for sort in self.univs )))) assert prog.scope is not None with prog.scope.n_states(1): typechecker.typecheck_expr(prog.scope, e, None) self.onestate_formula_cache[index] = e return self.onestate_formula_cache[index]
def relaxed_program(prog: syntax.Program) -> syntax.Program: new_decls: List[syntax.Decl] = [d for d in prog.sorts()] actives: Dict[syntax.SortDecl, syntax.RelationDecl] = {} for sort in prog.sorts(): name = prog.scope.fresh('active_' + sort.name) r = syntax.RelationDecl(name, arity=[syntax.UninterpretedSort(sort.name)], mutable=True, derived=None, annotations=[]) actives[sort] = r new_decls.append(r) # active relations initial conditions: always true for sort in prog.sorts(): name = prog.scope.fresh(sort.name[0].upper()) expr = syntax.Forall([syntax.SortedVar(name, None)], syntax.Apply(actives[sort].name, [syntax.Id(name)])) new_decls.append(syntax.InitDecl(name=None, expr=expr)) for d in prog.decls: if isinstance(d, syntax.SortDecl): pass # already included above elif isinstance(d, syntax.RelationDecl): if d.derived_axiom is not None: expr = syntax.relativize_quantifiers(actives, d.derived_axiom) new_decls.append(syntax.RelationDecl(d.name, d.arity, d.mutable, expr, d.annotations)) else: new_decls.append(d) elif isinstance(d, syntax.ConstantDecl): new_decls.append(d) elif isinstance(d, syntax.FunctionDecl): new_decls.append(d) elif isinstance(d, syntax.AxiomDecl): new_decls.append(d) elif isinstance(d, syntax.InitDecl): new_decls.append(d) elif isinstance(d, syntax.DefinitionDecl): assert not isinstance(d.body, syntax.BlockStatement), \ "relax does not support transitions written in imperative syntax" mods, expr = d.body expr = syntax.relativize_quantifiers(actives, expr) if d.is_public_transition: guard = syntax.relativization_guard_for_binder(actives, d.binder) expr = syntax.And(guard, expr) new_decls.append(syntax.DefinitionDecl(d.is_public_transition, d.num_states, d.name, params=d.binder.vs, body=(mods, expr))) elif isinstance(d, syntax.InvariantDecl): expr = syntax.relativize_quantifiers(actives, d.expr) new_decls.append(syntax.InvariantDecl(d.name, expr=expr, is_safety=d.is_safety, is_sketch=d.is_sketch)) else: assert False, d new_decls.append(relaxation_action_def(prog, actives=actives, fresh=True)) res = syntax.Program(new_decls) res.resolve() # #sorrynotsorry return res
def _generate_active_rels(self, scope: syntax.Scope) -> None: for sort in scope.known_sorts(): active_name = scope.fresh('active_%s' % sort.name) # TODO: is there a better way to get Sort out of SortDecl? sort_not_decl = syntax.UninterpretedSort(sort.name) typechecker.typecheck_sort(scope, sort_not_decl) active_rel = syntax.RelationDecl(active_name, arity=(sort_not_decl, ), mutable=True) self._active_rels_mapping[sort] = active_rel
def _read_first_order_structure( struct: FirstOrderStructure ) -> Tuple[List[syntax.SortedVar], # vs Dict[SortDecl, List[Expr]], # ineqs Dict[RelationDecl, List[Expr]], # rels Dict[ConstantDecl, Expr], # consts Dict[FunctionDecl, List[Expr]], # funcs ]: vars_by_sort: Dict[SortDecl, List[syntax.SortedVar]] = {} ineqs: Dict[SortDecl, List[Expr]] = {} rels: Dict[RelationDecl, List[Expr]] = {} consts: Dict[ConstantDecl, Expr] = {} funcs: Dict[FunctionDecl, List[Expr]] = {} for sort in struct.univs: vars_by_sort[sort] = [ syntax.SortedVar(v, syntax.UninterpretedSort(sort.name)) for v in struct.univs[sort] ] u = [syntax.Id(s) for s in struct.univs[sort]] ineqs[sort] = [ syntax.Neq(a, b) for a, b in itertools.combinations(u, 2) ] for R, l in struct.rel_interps.items(): rels[R] = [] for tup, ans in l.items(): e: Expr if tup: args: List[Expr] = [] for (col, col_sort) in zip(tup, R.arity): assert isinstance(col_sort, syntax.UninterpretedSort) assert col_sort.decl is not None args.append(syntax.Id(col)) e = syntax.AppExpr(R.name, tuple(args)) else: e = syntax.Id(R.name) e = e if ans else syntax.Not(e) rels[R].append(e) for C, c in struct.const_interps.items(): e = syntax.Eq(syntax.Id(C.name), syntax.Id(c)) consts[C] = e for F, fl in struct.func_interps.items(): funcs[F] = [] for tup, res in fl.items(): e = syntax.AppExpr(F.name, tuple(syntax.Id(col) for col in tup)) e = syntax.Eq(e, syntax.Id(res)) funcs[F].append(e) vs = list(itertools.chain(*(vs for vs in vars_by_sort.values()))) return vs, ineqs, rels, consts, funcs
def active_rels_mapping() -> Mapping[syntax.SortDecl, syntax.RelationDecl]: # TODO: should be read from the relaxation / the program, not fixed. # TODO: duplicated from relaxed_program() actives: Dict[syntax.SortDecl, syntax.RelationDecl] = {} prog = syntax.the_program for sort in prog.sorts(): name = 'active_' + sort.name # prog.scope.fresh('active_' + sort.name) r = syntax.RelationDecl(name, arity=[syntax.UninterpretedSort(sort.name)], mutable=True, derived=None, annotations=[]) actives[sort] = r return actives
def p_sort(p: Any) -> None: 'sort : id' p[0] = syntax.UninterpretedSort(p[1], p[1].value)
def p_sort(p: Any) -> None: 'sort : id' tok: Token = p[1] p[0] = syntax.UninterpretedSort(tok.value, span=span_from_tok(tok))
def relaxed_program(prog: syntax.Program) -> syntax.Program: new_decls: List[syntax.Decl] = [d for d in prog.sorts()] actives: Dict[syntax.SortDecl, syntax.RelationDecl] = {} for sort in prog.sorts(): name = prog.scope.fresh('active_' + sort.name) r = syntax.RelationDecl(name, arity=(syntax.UninterpretedSort(sort.name), ), mutable=True) actives[sort] = r new_decls.append(r) # active relations initial conditions: always true for sort in prog.sorts(): name = prog.scope.fresh(sort.name[0].upper()) expr = syntax.Forall((syntax.SortedVar(name, None), ), syntax.Apply(actives[sort].name, (syntax.Id(name), ))) new_decls.append(syntax.InitDecl(name=None, expr=expr)) for d in prog.decls: if isinstance(d, syntax.SortDecl): pass # already included above elif isinstance(d, syntax.RelationDecl): if d.derived_axiom is not None: expr = syntax.relativize_quantifiers(actives, d.derived_axiom) new_decls.append( syntax.RelationDecl(d.name, d.arity, d.mutable, expr, annotations=d.annotations)) else: new_decls.append(d) elif isinstance(d, syntax.ConstantDecl): new_decls.append(d) elif isinstance(d, syntax.FunctionDecl): new_decls.append(d) elif isinstance(d, syntax.AxiomDecl): new_decls.append(d) elif isinstance(d, syntax.InitDecl): new_decls.append(d) elif isinstance(d, syntax.DefinitionDecl): relativized_def = relativize_decl(d, actives, prog.scope, inline_relax_actives=False) new_decls.append(relativized_def) elif isinstance(d, syntax.InvariantDecl): expr = syntax.relativize_quantifiers(actives, d.expr) new_decls.append( syntax.InvariantDecl(d.name, expr=expr, is_safety=d.is_safety, is_sketch=d.is_sketch)) else: assert False, d new_decls.append(relaxation_action_def(prog, actives=actives, fresh=True)) res = syntax.Program(new_decls) typechecker.typecheck_program(res) # #sorrynotsorry return res