예제 #1
0
    class Signature(FolWithEquality.Signature):
        add = Identifier("+", 'function')
        cos = Identifier("cos", 'function')
        sin = Identifier("sin", 'function')
        x = Identifier("x", 'function')

        sorts = FolSorts({add: "R×R→R", sin: "R→R", cos: "R→R", x: "→R"})
        formal = FolManySortSignature.from_sorts(sorts)
예제 #2
0
class FolNaturalPartialOrder:

    lt = Identifier('<', 'predicate', 'lt')
    gt = Identifier('>', 'predicate', 'gt')

    le = Identifier(u'≤', 'predicate', 'le')
    ge = Identifier(u'≥', 'predicate', 'ge')

    STANDARD_INTERPRETATION = \
    {lt: lambda x,y: x < y,
     gt: lambda x,y: x > y,
     le: lambda x,y: x <= y,
     ge: lambda x,y: x >= y,
     }
예제 #3
0
     class Signature(FolWithEquality.Signature):
         add = Identifier("+", 'function')
         cos = Identifier("cos", 'function')
         sin = Identifier("sin", 'function')
         x = Identifier("[x]", 'function', mnemonic="x")
         
         sorts = FolSorts({add: "R×R→R",
                           sin: "R→R",
                           cos: "R→R",
                           x: "→R"})
         formal = FolManySortSignature.from_sorts(sorts)
 
         standard_interpretation = \
             {sin: lambda x: math.sin(x*math.pi/180),
              cos: lambda x: math.cos(x*math.pi/180)}
예제 #4
0
 def __init__(self):
     import re
     m = self.ESCAPE_SEQ
     self._ck = re.compile(self.VALID_IDENTIFIER_RE)
     self._multisubst = MultiSubstitution(m)
     self._sscript_re = re.compile(ur'[₀₁₂₃₄₅₆₇₈₉]+')
     self._sscript_tab = {
         ord(k): ord(v)
         for k, v in zip(u"₀₁₂₃₄₅₆₇₈₉", "0123456789")
     }
     self.escape = self.When(self._should_escape,
                             Identifier.lift(self._s_escape))
     self.unescape = Identifier.lift(
         MultiSubstitution({v: k
                            for k, v in m.iteritems()}))
     self._is_valid_identifier = Identifier.lift(self._s_is_valid)
예제 #5
0
 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:])
예제 #6
0
class FolIntegerArithmetic(FolNaturalPartialOrder):
    """
    Signature for basic arithmetic.
    """

    add = Identifier('+', 'function')
    sub = Identifier(u'−', 'function')
    mul = Identifier(u'⋅', 'function')
    div = Identifier('/', 'function')
    neg = Identifier('-', 'function')
    
    sorts = FolSorts({add: u"Z×Z→Z", mul: u"Z×Z→Z", sub: u"Z×Z→Z", div: u"Z×Z→Z",
                      neg: u"Z→Z", 
                      FolNaturalPartialOrder.gt: u"Z×Z→",
                      FolNaturalPartialOrder.lt: u"Z×Z→",
                      FolNaturalPartialOrder.ge: u"Z×Z→",
                      FolNaturalPartialOrder.le: u"Z×Z→"})
    
    formal = FolManySortSignature.from_sorts(sorts)

    STANDARD_INTERPRETATION = \
    {add : operator.add, sub: lambda a,b=None: -a if b is None else a-b, 
     u'−': operator.sub,
     mul: operator.mul, u'*': operator.mul,
     div: operator.div # integer division
     }

    FolFormula.INFIXES += [mul, sub]

    class Sugar:
        """FolSymbolic mix-in"""
        def _b(self, root, subs):
            return type(self)(root, [self.promote(x) for x in subs])
        def __add__(self, other):   return self.build(self._.add, [self, other])
        def __radd__(self, other):  return self.build(self._.add, [other, self])
        def __sub__(self, other):   return self.build(self._.sub, [self, other])
        def __rsub__(self, other):  return self.build(self._.sub, [other, self])
        def __mul__(self, other):   return self.build(self._.mul, [self, other])
        def __rmul__(self, other):  return self.build(self._.mul, [other, self])
        def __neg__(self):          return self.build(self._.neg, [self])
        # Naturally should be part of FolWithEquality
        def __eq__(self, other):    return self.build(self._.eq, [self, other])
        # Naturally should be part of FolNaturalPartialOrder
        def __gt__(self, other):    return self.build(self._.gt, [self, other])
        def __lt__(self, other):    return self.build(self._.lt, [self, other])
        def __ge__(self, other):    return self.build(self._.ge, [self, other])
        def __le__(self, other):    return self.build(self._.le, [self, other])
예제 #7
0
 def instantiate(node, varsym):
     l = []
     for s in node.subtrees:
         f = s.root
         new_var = Identifier(u"%s_%s" % (f, varsym), 'variable', ns=ns)
         img = _(self._rel(f), [q(varsym), q(new_var)])
         imgs = _.conjunction([img] + instantiate(s, new_var))
         l += [_(_.EXISTS, [q(new_var), imgs])]
     return l
예제 #8
0
class GraphStructure(object):

    E = Identifier('E', 'predicate')
    w = Identifier('w', 'function')

    def __init__(self, g, weighted=False):
        self.g = g
        self.weighted = weighted

    def structure(self):
        has_edge = Labeled("has_edge", lambda u, v: v in u.get_adjacent_out())
        interpretation = {self.E: has_edge}
        if self.weighted:
            get_weight = Labeled(
                "weight", lambda u, v: has_edge(u, v) and min(
                    e.label for e in u.get_edges_to(v)) or INF)
            interpretation[self.w] = get_weight
        m = FolStructure(self.g.nodes, interpretation)
        return m
예제 #9
0
    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
예제 #10
0
 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
예제 #11
0
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
예제 #12
0
    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 = ''
예제 #13
0
class TypeInference(object):

    SPECIALTIES = [Identifier("ite", 'connective'), Identifier("?:", 'macro')]

    def __init__(self):
        self.declarations = FolSorts()
        self.signature = FolManySortSignature(set(), set())
        self.special_symbols = {sym.literal: sym for sym in self.SPECIALTIES}

    def __call__(self, formula_or_formulas):
        if isinstance(formula_or_formulas, (tuple, list)):
            for phi in formula_or_formulas:
                self._formula(phi)
            if isinstance(formula_or_formulas, FolTheory):
                formula_or_formulas.signature |= self.signature
                formula_or_formulas.signature = formula_or_formulas.vocabulary
        else:
            self._formula(formula_or_formulas)
        return formula_or_formulas

    def _formula(self, phi, result_type='', bound_vars=set()):
        """
        (changes formula in-place, and also affects self.signature)
        """
        r, s, arity = phi.root, phi.subtrees, len(phi.subtrees)
        if isinstance(r, Identifier):
            if r.kind == '?' and r.literal in self.special_symbols:
                phi.root = r = self.special_symbols[r.literal]
            if r.kind == 'quantifier':
                v = self._variable(phi.subtrees[0])
                for expr in phi.subtrees[1:]:
                    self._formula(expr, '', bound_vars | v)
                return ''
            elif r.kind == 'connective':
                for expr in phi.subtrees:
                    self._formula(expr, '', bound_vars)
                return ''
            elif r == "?:":  # @@ hard-coded for now
                self._formula(s[0], '', bound_vars)
                term_types = [self._formula(x, '?', bound_vars) for x in s[1:]]
                if term_types and all(x == term_types[0]
                                      for x in term_types[1:]):
                    return term_types[0]
                else:
                    return '?'
            elif r in bound_vars:
                phi.root = [v for v in bound_vars if v == r][0]
                sort = self.declarations.ary(phi.root, 0)
                self._infer(phi, result_type)
                return sort[0].to_ if sort else ' '
            else:
                sort = self.declarations.ary(r, arity)
                if len(sort) == 1:
                    # matching declaration
                    subtypes = sort[0].from_
                    result_type = sort[0].to_
                else:
                    # undeclared or ambiguous
                    subtypes = (' ', ) * arity
                # Try to assign a kind (predicate or function) to identifier
                if r.kind == '?':
                    if (r, arity) in self.signature.funcs:
                        cr = [
                            s for s, a in self.signature.funcs
                            if (s, a) == (r, arity)
                        ][0]
                    elif (r, arity) in self.signature.preds:
                        cr = [
                            s for s, a in self.signature.preds
                            if (s, a) == (r, arity)
                        ][0]
                    else:
                        cr = copy.copy(r)
                        # TODO somtimes this is 'bool' when it should be ''
                        if result_type == 'bool': result_type = ''
                        cr.kind = 'predicate' if result_type == '' else 'function'
                        if sort: self.signature.sorts[cr] = sort
                    if cr.kind == 'function':
                        self.signature.funcs.add((cr, arity))
                    else:
                        self.signature.preds.add((cr, arity))
                    phi.root = cr

                self._infer(phi, result_type)

                for expr, subtype in zip(phi.subtrees, subtypes):
                    self._formula(expr, subtype, bound_vars)
                return result_type

    def _variable(self, variable_expr):
        if not variable_expr.subtrees:
            v = variable_expr.root
            if isinstance(v, Identifier) and v.kind == '?':
                cv = copy.copy(v)
                cv.kind = 'variable'
            else:
                cv = v
            sort = self.declarations.ary(cv, 0)
            if sort: self.signature.sorts[cv] = sort
            return set([cv])

        return set()

    def _infer(self, expr, expected_type):
        sorts = self.signature.sorts
        r = expr.root
        if expected_type not in [' ', '', '?'
                                 ] and not expr.subtrees and r not in sorts:
            sorts[r] = [((), expected_type)]
예제 #14
0
 def _xform_protect(self, t):
     r = t.root
     if r in self.opaque:
         return type(t)(Identifier(self, 'opaque', ns=[t]))
예제 #15
0
    def __init__(self, context, inner):
        self.context = context
        self.inner = inner
        if isinstance(inner, self.__class__):
            self.__class__ = inner.__class__
        else:

            class NestedException(self.__class__, inner.__class__):
                __str__ = __repr__ = self.__class__.__str__

            self.__class__ = NestedException

    def __str__(self):
        return "In: %r\n%r" % (self.context, self.inner)


# Snippet
if __name__ == '__main__':
    from logic.fol import Identifier
    i = Identifier('i', 'function')
    sigma = FolSignature([(i, 1)], [])
    m = FolStructure([1, 2, 3], {i: lambda x: x % 3 + 1})
    p = FolDomainProjection(sigma, lambda t: t * 2)
    n = p(m)
    print n.domain
    print n.interpretation['i']
    print[n.interpretation['i'](x) for x in n.domain]
    print FolResample().structure(n, sigma)

    print m.evaluate(FolFormula(i, [FolFormula(2)]))
예제 #16
0
 def obligations(self, t, collect=[]):
     if t.root == 'valid':
         collect += [
             type(t)(Identifier('lemma', '?'), [x]) for x in t.subtrees
         ]
         return FolFormula(FolFormula.TRUE)
예제 #17
0
            body_prime = self._add_quantifier_prefix(body_prime, r, new_names)
            return _(t.root, [s[0], body_prime])

    def is_fine(self, atom):
        '''Only atoms of the form f(x)=y are allowed to have functions.'''
        r, s = atom.root, atom.subtrees
        if r == FolWithEquality.eq and len(s) == 2:
            return all(not w.subtrees for x in s for w in x.subtrees)
        elif r.kind == 'predicate':
            return all(not x.subtrees for x in s)
        else:
            return True


if __name__ == '__main__':
    from logic.fol.syntax.parser import FolFormulaParser
    from eprv.synopsis.declare import TypeInference

    L = FolFormulaParser()
    f = Identifier('f', 'function')
    g = Identifier('g', 'function')
    sigma = FolManySortSignature.from_sorts(FolSorts({f: u'V→V', g: u'V→V'}))
    ti = TypeInference()
    ti.declarations = sigma.sorts
    phi = ti(L * "forall u (ite(u=u, f(u) = u, f(u) = g(u)))")

    from eprv.synopsis.proof import ProofSynopsis
    ef = EasyFunctionsExtension()

    ef.inspect_formula(phi, ProofSynopsis.Context(None, sigma))
    print phi
예제 #18
0
 class Signature:
     ter_op = Identifier('?:', 'macro')
     ite = Identifier('ite', 'connective')
예제 #19
0
 class Signature:
     REDUCE_GLOB = Identifier(u"Я", "quantifier")
     formal = FolSignature()
예제 #20
0
        class Signature(FolWithEquality.Signature):
            add = Identifier("+", 'function')
            mul = Identifier("*", 'function')
            gt = Identifier(">", 'predicate', mnemonic="gt")
            ge = Identifier("≥", 'predicate', mnemonic="ge")
            lt = Identifier("<", 'predicate', mnemonic="lt")
            le = Identifier("≤", 'predicate', mnemonic="le")

            x = Identifier("[x]", 'function', mnemonic="x")
            y = Identifier("[y]", 'function', mnemonic="y")
            z = Identifier("[z]", 'function', mnemonic="z")

            b = Identifier(":b:", 'function', mnemonic="b")

            i = Identifier("i", 'variable')
            
            sorts = FolSorts({add: "Z×Z→Z", mul: "Z×Z→Z", gt: "Z×Z→",
                              x: "Z→Z", y: "Z→Z", z: "Z→Z", b: "Z×Z→Z", i: "→Z"})
            formal = FolManySortSignature.from_sorts(sorts)
예제 #21
0
 def _rel(self, f):
     return Identifier("R_%s" % f, 'predicate')
예제 #22
0
 def _img(self, f, x, ns=None):
     f = self.BracketedModifier(f, 'modifier')
     return Identifier(FolFormula(f, [FolFormula(x)]), 'function', ns=ns)
예제 #23
0
 def _mkuniq(self, identifier):
     return Identifier(identifier.literal, identifier.kind, ns=self.NS())