def _rename_terms_over(self, phi, variable): ns = AlphaRenaming.NS() new_names = BidirectionalDict( {FolFormula(variable): FolFormula(variable)}) def _scan(t): if t.root != '=': return type(t)(t.root, [_collect(x) or x for x in t.subtrees]) def _collect(t): if t.root.kind == 'function': try: t_prime = new_names.get_backwards(t) return t_prime except KeyError: if t.subtrees and all( new_names.has_key(x) for x in t.subtrees): c = FolFormula( Identifier(u"β%d" % len(new_names), 'variable', ns=ns)) new_names[c] = t return c return TreeTransform([_scan], dir=TreeTransform.BOTTOM_UP)(phi), new_names
def _xform_toplevel(self, phi, constants, quantifier_context): for c in constants: phi, new_names = self._rename_terms_over(phi, c) del new_names[FolFormula(c)] phi = self._add_quantifier_prefix(phi, quantifier_context, new_names) return phi
def xform(t): if not self.unnest.is_fine(t): raise ValueError, "nested term not allowed; in '%s'" % t r, s = t.root, t.subtrees s = sorted(s, key=lambda x: len(x.subtrees), reverse=True) if r == EQ and len(s) == 2 and s[0].root in self.funcs: if s[1].root in self.funcs: _ = FolFormula gamma = Identifier(u'γ', 'variable', ns=AlphaRenaming.NS()) if (quantifier_type, t.context_sign) in [(_.FORALL, "+"), (_.EXISTS, "-")]: quantifier, connective = _.FORALL, _.IMPLIES elif (quantifier_type, t.context_sign) in [(_.FORALL, "-"), (_.EXISTS, "+") ]: quantifier, connective = _.EXISTS, _.AND else: raise ValueError, "invalid quantifier context %s" % ( (quantifier_type, t.context_sign), ) return _(quantifier, [ _(gamma), _(connective, [ _(self._rel(s[0].root), s[0].subtrees + [_(gamma)]), _(self._rel(s[1].root), s[1].subtrees + [_(gamma)]) ]) ]) else: return FolFormula(self._rel(s[0].root), s[0].subtrees + s[1:])
def __call__(self, t, e=None): """ Modifies lemmas such that they have totality antecedents at the beginning for global constants and then again for every universally quantified variable. """ simpl = self._simplify ar = AlphaRenaming() if t.root == 'lemma' and len(t.subtrees) == 1: phi = simpl(t.subtrees[0]) phi = self.unnest(phi, self.constants, FolFormula.FORALL) totc = self.construct_totality() relt = self.replace_equalities_with_atomic( self.relativize_quantifiers(phi), quantifier_type=FolFormula.EXISTS) phi = FolFormula(FolFormula.IMPLIES, [totc, relt]) phi = FolFormula.conjunction(ar(conj) for conj in phi.split()) return simpl(FolFormula(t.root, [phi])) else: phi = simpl(t) # @todo resolve cyclic dependency from eprv.synopsis.proof import CheckQuantifierAlternation if not CheckQuantifierAlternation().is_universal(phi): raise ValueError, "axioms must be universal; this one isn't: '%s'" % phi phi = self.unnest(phi, self.constants, FolFormula.FORALL) phi = simpl( self.replace_equalities_with_atomic( phi, quantifier_type=FolFormula.FORALL)) phi = FolFormula.conjunction(ar(conj) for conj in phi.split()) return phi
def __call__(self, program_text, compose_prefix=''): ast = self.parser(program_text) astf = ApplyTo(nodes=Identifier.promote).inplace( FolFormula.reconstruct(ast)) if compose_prefix: for n in astf.nodes: if n.subtrees: n.root = Identifier(compose_prefix + n.root.literal, 'macro') return astf
def _collect(t): if t.root.kind == 'function': try: t_prime = new_names.get_backwards(t) return t_prime except KeyError: if t.subtrees and all( new_names.has_key(x) for x in t.subtrees): c = FolFormula( Identifier(u"β%d" % len(new_names), 'variable', ns=ns)) new_names[c] = t return c
class TypeDeclarations(FolManySortSignature): COLON_SEP = [':'] FUNC_SEP = [u"→", '->', FolFormula.IMPLIES] PARAM_SEP = [u"×", FolIntegerArithmetic.mul, "*"] EMPTY_MARKER = [FolFormula(Identifier("", '?'))] def to_sorts(self, phi): if not isinstance(phi, FolFormula) or phi.root not in self.COLON_SEP or len( phi.subtrees) != 2: raise ValueError, "expected a declaration, found '%s'" % phi name, typename = phi.subtrees if not name.subtrees: name = name.root else: raise ValueError, "expected atomic identifier, found '%s' (in declaration '%s')" % ( name, phi) if typename.root in self.FUNC_SEP: if len(typename.subtrees) == 2: left, right = typename.subtrees else: raise ValueError, "invalid usage of '%s' (in declaration '%s')" % ( self.FUNC_SEP[0], phi) else: left, right = self.EMPTY_MARKER, typename from_ = () if left == self.EMPTY_MARKER else map( self._typename, left.split(self.PARAM_SEP)) to_ = '' if right == self.EMPTY_MARKER or right.root == "bool" else self._typename( right) return FolSorts({name: FolSorts.FunctionType(from_, to_)}) def _typename(self, term): if term.subtrees: raise NotImplementedError, "Non-atomic type '%s'" % term return term.root def is_declaration(self, phi): return isinstance(phi, FolFormula) and phi.root in self.COLON_SEP def read_from(self, formulas): if not isinstance(formulas, (list, set, tuple)): formulas = (formulas, ) for phi in formulas: self |= self.from_sorts(self.to_sorts(phi)) return self
def xform(t): r, s = t.root, t.subtrees if r == 'disable-relativization': return FolFormula.conjunction(s) elif r.kind == 'quantifier' and t.context_sign == '--': return None # skip relativization for this quantifier (disable-relativization) elif r.kind == 'quantifier' and (u'β' in s[0].root.literal or u'γ' in s[0].root.literal): return None elif r == FolFormula.FORALL and t.context_sign == '+': return gen_tot(t, r, s, FolFormula.IMPLIES) elif r == FolFormula.EXISTS and t.context_sign == '-': return gen_tot(t, r, s, FolFormula.AND) elif r in [FolFormula.FORALL, FolFormula.EXISTS ] and t.context_sign == '+-': raise NotImplementedError, "ambiguous context for quantifier: '%s'" % ( t, )
def __mul__(self, line_of_text): """ Quickly parse, expand, and return result as FolFormula. """ return FolFormula.conjunction(self.expansion(line_of_text))
def assumptions(self, t, collect=[]): if t.root == 'provided': collect += t.subtrees return FolFormula(FolFormula.TRUE)
def obligations(self, t, collect=[]): if t.root == 'valid': collect += [ type(t)(Identifier('lemma', '?'), [x]) for x in t.subtrees ] return FolFormula(FolFormula.TRUE)
def _img(self, f, x, ns=None): f = self.BracketedModifier(f, 'modifier') return Identifier(FolFormula(f, [FolFormula(x)]), 'function', ns=ns)
# Demo AST deserialization w = WhileFrontend.WhileASTDeserialize() print w(unicode(astf)) print w(";{x:=y{i,j},y:=x.n{k,i},x.n:=y{i,i}}") print w( ";{;{x:=y{i,h},x:=null{j},x:=null{t},while {((i != null) & (t = null)), I, skip}}}" ) raise SystemExit astf = fe("k:=i.n ; i.n:=j; j:=i; i:=k", 'wp ') astf = fe( "( if $C( i )$ then ( t := i.n ; j.n := null ; j.n := t ) else j := i ) ; i := i.n", 'wp ') astf.subtrees += [FolFormula.promote("Q")] def compose_xform(t): import copy r, s = t.root, t.subtrees a = len(s) if r == 'wp ;' and a == 3: c1 = copy.deepcopy(s[0]) c2 = copy.deepcopy(s[1]) c2.subtrees += [s[2]] c1.subtrees += [c2] return c1 if r == 'wp if' and a == 4: ct, ce = copy.deepcopy(s[1]), copy.deepcopy(s[2]) ct.subtrees += [s[3]] ce.subtrees += [s[3]]