Exemple #1
0
    def relativize_quantifiers(self, phi):
        """
        forall x (P(x))  --->  forall x (exists cx (R[f](x,cx)) -> P(x))
        exists x (P(x))  --->  exists x (exists cx (R[f](x,cx)) & P(x))
        """
        def gen_tot(t, r, s, connective):
            for x in s[:-1]:
                if x.subtrees:
                    raise ValueError, "nonterminal quantified variable '%s'" % (
                        x, )
            imp = self.construct_totality([x.root for x in s[:-1]])
            T = type(t)
            return T(r, s[:-1] + [T(connective, [imp, s[-1]])])

        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, )

        self._mark_context_sign(phi)
        return TreeTransform([xform], dir=TreeTransform.BOTTOM_UP).inplace(phi)
Exemple #2
0
 def __call__(self, text):
     t, = self.forestify(self.b(self.l(text)))
     t = TreeTransform(
         [functools.partial(AuxTransformers.unfold, symbols={';': 2})],
         dir=TreeTransform.BOTTOM_UP,
         recurse=True)(t)
     return t
 def normalize(self):
     def transformer(self):
         if isinstance(self.root, Identifier) and \
            isinstance(self.root.literal, type(self)) and \
            not self.subtrees:
             return self.root.literal
     return TreeTransform([transformer])(self)
Exemple #4
0
    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 __init__(self, naming_convention=NamingConvention()):
        _ = AuxTransformers
        fold_f = TreeTransform([_.fold], dir=TreeTransform.BOTTOM_UP)
        #fold_f.IS_DESCENDING = True
        self.naming = naming_convention

        regroup_f = TreeTransform([partial(_.regroup, head='forall', tag='')],
                                  dir=TreeTransform.BOTTOM_UP)

        synonyms = {
            FolFormula.FORALL: Identifier('forall', 'quantifier'),
            FolFormula.EXISTS: Identifier('exists', 'quantifier'),
            FolFormula.AND: Identifier('and', 'connective'),
            FolFormula.OR: Identifier('or', 'connective'),
            FolFormula.IFF: Identifier('iff', 'connective'),
            FolFormula.IMPLIES: Identifier('=>', 'connective'),
            FolFormula.NOT: Identifier('not', 'connective'),
            True: 'true',
            False: 'false'
        }
        synonyms_f = TreeSubstitution(synonyms)

        #e = Expansion()   # must get rid of it; only needed for the parser
        L = DeltaReduction.Transformer._mkparser(
        )  # suggested optimization: use singleton for parser. Also, only parse macros once
        macros = [
            "x != y := ~(x=y)", "forall x (psi) := [forall]([]([](x,V)), psi)",
            "exists x (psi) := [exists]([]([](x,V)), psi)"
        ]
        macros_f = DeltaReduction(dir=TreeTransform.BOTTOM_UP)
        macros_f.IS_DESCENDING = False
        macros_f.transformers += \
            [DeltaReduction.Transformer(macros_f, L(m)) for m in macros]

        from adt.tree.transform.apply import ApplyTo  # @Reimport
        escape_f = ApplyTo(nodes=naming_convention.escape_safe).inplace

        self.phases = ProcessingPhases([(macros_f, "Operators/quantifiers"),
                                        (SExpression.reconstruct,
                                         "S-expression"), (fold_f, "Fold"),
                                        (synonyms_f, "Rename keywords"),
                                        (regroup_f, "Regroup"),
                                        (escape_f, "Escape identifiers")])
        self.preface = ''
 def __call__(self, t):
     if t.root == self.head:
         if not self.params and not self.body.subtrees:  # e.g. "r := q"
             return TreeTransform.Scalar(self.body.root)
         elif len(t.subtrees) == len(
                 self.params):  # e.g. "r := p(a,b)" or "r(a) := p(a,b)"
             tun = self.o.tuning
             subst = dict(
                 map(self._single_out, zip(self.params, t.subtrees)))
             body = tun.local_.before(self.body)
             return tun.local_.after(TreeSubstitution(subst)(body))
Exemple #7
0
    def e_absapp(self, expr):
        is_value = self.is_value
        beta_reduce = self.beta_reduce

        class Transformer(object):
            def __init__(self):
                self.stop = False

            def __call__(self, t):
                if not self.stop and t.root == 'App' and \
                   all(is_value(x) for x in t.subtrees):
                    assert len(t.subtrees) == 2
                    self.stop = True
                    func, arg = t.subtrees
                    return beta_reduce(func, arg)

        return TreeTransform([Transformer()])(expr)
Exemple #8
0
    def replace_equalities_with_atomic(self, phi, quantifier_type):
        '''f(x) = y    --->   R[f](x, y)
           y = f(x)    --->   R[f](x, y)
           f(x) = g(y) --->   forall z (R[f](x,z) -> R[g](y,z))   /
                              exists z (R[f](x,z) & R[g](y,z))
                              
           The quantifier is determined according to quantifier_type (either FolFormula.FORALL or FolFormula.EXISTS)
           when the atomic formula occurs in a positive context. In a negative 
           context, the other quantifier is used.
           '''
        EQ = FolWithEquality.eq

        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:])

        self._mark_context_sign(phi)
        return TreeTransform([xform]).inplace(phi)
Exemple #9
0
 def __call__(self, tree):
     w = self.replace_what
     if isinstance(w, type(tree)):
         compare_with = w
     else:
         compare_with = type(tree)(w)
     if tree.root == w and isinstance(self.replace_with, list):
         return type(tree)([], self.replace_with)
     if tree.root == w and not isinstance(self.replace_with,
                                          type(tree)):
         return TreeTransform.Scalar(self.replace_with)
     elif tree == compare_with:
         if isinstance(self.replace_with, list):
             return type(tree)([], self.replace_with)
         elif isinstance(self.replace_with, type(tree)):
             return self.replace_with
         else:
             return type(tree)(self.replace_with)
Exemple #10
0
    def to_quantified(cls, phi, quantifier_context):
        '''
        @param quantifier_context: either FolFormula.FORALL or FolFormula.EXISTS
        '''
        def xform(t):
            r, s = t.root, t.subtrees
            if r == cls.LET:
                _ = FolFormula
                if t.quantifier_context == _.FORALL:
                    return _(_.FORALL, [s[0].subtrees[0], _(_.IMPLIES, s)])
                elif t.quantifier_context == _.EXISTS:
                    return _(_.EXISTS, [s[0].subtrees[0], _(_.AND, s)])
                else:
                    raise ValueError, "invalid quantifier context '%s' for '%s'" % (
                        t.quantifier_context, t)

        cls._mark_quantifier_context(phi, quantifier_context)
        return TreeTransform([xform])(phi)
Exemple #11
0
 def __call__(self, formula):
     q = []
     def pull_out(t, op_prefix=(), q=q):
         """ Extracts quantifiers nested in (sub-)formula t. """
         r, s = t.root, t.subtrees
         if r in self.quantifiers:
             q += [self._apply_ops(op_prefix, type(t)(r, s[:-1]))]
         if r in self.instructions:
             ops = self.instructions[r]
             for x, op in zip(s, ops):
                 pull_out(x, op_prefix + (op,))
     def xform(t):
         r, s = t.root, t.subtrees
         if r in self.quantifiers:
             return s[-1]
     pull_out(formula)
     phi = TreeTransform([xform], recurse=True)(formula)
     for prefix in reversed(q):
         prefix.subtrees += [phi]
         phi = prefix
     return phi
Exemple #12
0
    def simplify(self, t):
        def transform(t):
            r, arity, s = t.root, len(t.subtrees), t.subtrees
            h = None
            if r == 'S' and arity == 1:
                h = s[0]
            #elif r == 'id' and arity == 1:
            #    h = s[0]
            elif r == 'Abs' and arity == 3:
                h = type(t)(r, s[1:])
            elif r == 'S' and arity == 3 and s[0].root == '(' and s[
                    2].root == ')':
                h = s[1]
            elif isinstance(r, Tagged) and hasattr(r, 'token'):
                h = type(t)(r.token)

            if h is not None:
                return recurse(h)

        recurse = TreeTransform([transform])
        return recurse(t)
Exemple #13
0
    def inspect_formula(self, phi, ctx):
        '''Collects constants occurring in assertions.'''
        # TODO: remove 'used_fragment', take all the functions ever
        s = ctx.signature  #.used_fragment([phi])
        self.constants = [
            c for c, _ in s.funcs if s.sorts.is_const(c, of_sort="V")
        ]
        self.funcs = [
            c for c, a in s.funcs if a == 1 and s.sorts.returns(c, "V")
        ]
        #self.rel_funcs = self.funcs
        #self.rel_funcs = [c for c in self.funcs if (c,1) in s.used_fragment([phi]).funcs or c in ["k0", "km0"]]

        _ = Tree
        #rel_funcs = _('', [_('k10', [_('k20'), _('km20')]),
        #                   _('km10', [_('k20'), _('km20')])
        #                   ] + [_(x) for x in ["f", "g", "l0", "k0", "km0", "k20", "km20"]])
        rel_funcs = _('', [
            _(x) for x in
            ["f", "g", "l0", "k0", "km0", "k10", "km10", "k20", "km20", "en0"]
        ])

        def xform(t):
            r, s = t.root, t.subtrees
            if r != '':
                f = [c for c in self.funcs if c.literal == r]
                if f:
                    new_r = f[0]
                else:
                    return Tree('')
            else:
                new_r = r
            return Tree(new_r, [x for x in s if x.root != ''])

        self.rel_funcs = TreeTransform([xform],
                                       dir=TreeTransform.BOTTOM_UP)(rel_funcs)
        #[c for c in self.funcs if c in ["f", "g", "l0", "k0", "km0", "k10", "km10", "k20", "km20", "k2k10", "km2k10", "k2km10", "km2km10"]]
        self.declare_relations(ctx.signature)

        self.inplace(phi)
Exemple #14
0
    def __call__(self, phi, ctx=None):
        occurrences = ListWithAdd()
        self._collect_ternies(phi, occurrences)

        def xform(phi):
            _ = FolFormula
            for (atom, ter) in occurrences:
                if phi is atom:
                    if len(ter.subtrees) != 3:
                        raise ValueError, "invalid ternary expression: '%s'" % ter
                    cond, then_, else_ = ter.subtrees
                    phi = _(self.Signature.ite, [
                        cond,
                        self._choose(atom, ter, then_),
                        self._choose(atom, ter, else_)
                    ])
                    return self(phi)

        if occurrences:
            return TreeTransform([xform])(phi)
        else:
            return phi
 def _collect(self, t, parts_f):
     parts = []
     xform = TreeTransform([partial(parts_f, collect=parts)],
                           dir=TreeTransform.BOTTOM_UP)
     parts += [xform(t)]
     return parts
Exemple #16
0
 def __call__(self, phi, ctx=None):
     return TreeTransform([self.xform], dir=TreeTransform.BOTTOM_UP)(phi)
Exemple #17
0
    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]]
            return type(t)(r, [s[0], ct, ce])

    print astf

    xf = TreeTransform([compose_xform],
                       dir=TreeTransform.TOP_DOWN,
                       recurse=True)
    xf.IS_DESCENDING = True
    print xf(astf)
Exemple #18
0
 def unprotect(self):
     return TreeTransform([self._xform_unprotect])
Exemple #19
0
    #print unicode(FOL_GRAMMAR)
    
    for rule in FOL_GRAMMAR.rules:
        if rule.head == 'fml': print rule
    
    #raise SystemExit
    
    class TX(ParserXforms):
        PRIM = {'forall': FolFormula.FORALL, '|': FolFormula.OR, '&': FolFormula.AND, '~': FolFormula.NOT, '->': FolFormula.IMPLIES, '<->': FolFormula.IFF}
        for v in PRIM.values(): PRIM[v.literal] = v
        
        def singl(self, t):   return FolFormula(Identifier((t.subtrees[0] if t.subtrees else t).root.token.value, '?'))
        def qua(self, t):     return FolFormula(self.PRIM[t.subtrees[0].root.token.value], [self.singl(t.subtrees[1]), t.subtrees[3]])
        def cal(self, t):     return FolFormula(self.singl(t).root, self.split(t.subtrees[2], ('term*', 'term+', ',')))
        def bin(self, t):     return FolFormula(self.PRIM[t.subtrees[1].root.token.value], [t.subtrees[0], t.subtrees[2]])
        def un(self, t):      return FolFormula(self.PRIM[t.subtrees[0].root.token.value], [t.subtrees[1]])
        def sam(self, t):     return t.subtrees[0]
        def sam1(self, t):    return t.subtrees[1]
        
    
    lG = set((Tagged(tok).with_(annotation='sam'), tok) for tok in tokens)

    ast = Earley(FOL_GRAMMAR.rules, lG, tokens, lexer=lambda x: x)
    PrintTrees(ast)
    assert len(ast) == 1
    ast = FolFormula.reconstruct(ast[0])
    print ast
    phi = TreeTransform([TX()], dir=TreeTransform.BOTTOM_UP)(ast)

    print phi
Exemple #20
0
    def _choose(self, atom, point_of_choice, choice):
        def xform(phi):
            if phi is point_of_choice: return choice

        return TreeTransform([xform])(atom)
Exemple #21
0
 def __call__(self, phi, constants, quantifier_context):
     phi = TreeTransform([self._xform], dir=TreeTransform.BOTTOM_UP)(phi)
     return self._xform_toplevel(phi, constants, quantifier_context)