Beispiel #1
0
 def __init__(self, signature=FolManySortSignature(), logic="QF_UF"):
     self.signature = signature
     if not isinstance(signature, FolManySortSignature):
         self.signature = FolManySortSignature(signature.funcs,
                                               signature.preds)
     self.logic = logic
     self.builtin_mappings = {
         'R': "Real",
         'Z': "Int",
         FolWithEquality.Signature.eq: "="
     }
    def demo2():
        V = DeclareSort("V")
        R = Function("R", V, V, BoolSort())
        u, v, w = Consts("u v w", V)
        po = And(
            ForAll([u, v, w], Implies(And(R(u, v), R(v, w)),
                                      R(u, w))),  # transitive
            ForAll([u, v], Not(And(R(u, v), R(v, u))))  # antisymmetric
        )
        s = Solver()
        s.add(po)
        s.add(u != v)
        s.add(u != w)
        s.add(And(Or(R(u, v), R(v, u)), Or(R(u, w), R(w, u))))
        print s.check()
        m = s.model()

        class _:
            u = Identifier('u', 'function')
            v = Identifier('v', 'function')
            w = Identifier('w', 'function')
            R = Identifier('R', 'predicate')
            sorts = FolSorts({u: u'→V', v: u'→V', w: u'→V', R: u'V×V→'})

        sig = FolManySortSignature.from_sorts(_.sorts)
        z3m = Z3ModelToFolStructure(sig, {_.u: u, _.v: v, _.w: w, _.R: R})
        mm = z3m(m)
        print mm
        from adt.graph.format import DEFAULT as FORMATTER
        mm.domain = mm.domain['V']
        print FORMATTER(AlgebraicStructureGraphTool(mm, [_.R])())
Beispiel #3
0
 def __call__(self, phi):
     """
     Makes sure any two identifiers that are not equal (not __eq__(x,y))
     have distinct literals. Note: performs modification of formulas in-place.
     @param phi a FolFormula instance
       it may also be:
       * an Identifier, in which case the corresponding unique identifier is returned
       * a FolManySortSignature, in which case returns a *new* signature where all
         symbols are translated to unique ones
     """
     if isinstance(phi, FolFormula):
         symset = OrderedSet(node.root for node in phi.nodes
                             if node.root.ns is not None)
         symdict = {sym: self.gen_uniq(sym) for sym in symset}
         return TreeNodeRename(symdict).inplace(phi)
     elif isinstance(phi, Identifier):
         sym = phi
         return self.gen_uniq(sym) if sym.ns is not None else sym
     elif isinstance(phi, FolManySortSignature):
         renamed_sorts = FolSorts(
             {self(k): v
              for k, v in phi.sorts.sorts.iteritems()})
         return FolManySortSignature.from_sorts(renamed_sorts)
     else:
         raise TypeError, "expected identifier, formula, or signature; found '%s'" % (
             type(phi).__name__)
Beispiel #4
0
 def declare_relations(self, signature):
     for f in self.funcs:
         Rf = self._rel(f)
         if Rf not in signature.preds:
             for from_, to_ in signature.sort_of(f):
                 signature |= FolManySortSignature.from_sorts(
                     FolSorts({Rf: [(tuple(from_) + (to_, ), 'bool')]}))
Beispiel #5
0
 def __init__(self):
     self.z3_sort_map = OneToOne({
         'bool': BoolSort(),
         '': BoolSort()
     }).of(self._mksort)
     self.z3_decls = {}
     self.signature = FolManySortSignature()
     self.expansion = None
Beispiel #6
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)
 def domain_of(self, symbol, signature):
     d = MultiDomain.promote(self.domain)
     s = FolManySortSignature.promote(signature)
     for (from_, _) in s.sort_of(symbol):
         if len(from_) == 1:
             l = d[from_[0]]
         else:
             l = d[from_]
         for el in l:
             yield el
Beispiel #8
0
    def blur(self, phi):
        reg = self
        s = self.symbols

        class FormulaWalk(RichTreeWalk.Visitor):
            def enter(self, subtree, prune=lambda: None):
                r = subtree.root
                if isinstance(r, Identifier) and \
                     r.kind in ['function', 'predicate'] and r not in reg.symbols:
                    prune()
                    return reg.UNDEF
                else:
                    return r

            def join(self, node, prefix, infix, postfix):
                known = [a for a in infix if a.root != reg.UNDEF]
                if len(known) == len(infix):
                    return type(node)(prefix, known)
                elif prefix == FolFormula.AND and len(known) == 1:
                    return known[0]
                else:
                    return type(node)(reg.UNDEF)

            def done(self, root, final):
                return final

        if isinstance(phi, FolFormula):
            return RichTreeWalk(FormulaWalk())(phi)
        elif isinstance(phi, FolTheory):
            sig = self.blur(phi.signature)
            t = (y for y in (self.blur(x) for x in phi)
                 if y.root != self.UNDEF)
            return FolTheory(t).with_signature(sig)
        elif isinstance(phi, FolManySortSignature):
            return FolManySortSignature([(f, a)
                                         for f, a in phi.funcs if f in s],
                                        [(p, a)
                                         for p, a in phi.preds if p in s],
                                        self.blur(phi.sorts))
        elif isinstance(phi, FolSignature):
            return FolSignature([(f, a) for f, a in phi.funcs if f in s],
                                [(p, a) for p, a in phi.preds if p in s])
        elif isinstance(phi, FolSorts):
            return FolSorts(self.blur(phi.sorts))
        elif isinstance(phi, FolStructure):
            return FolStructure(domain=phi.domain,
                                interpretation=self.blur(phi.interpretation))
        elif isinstance(phi, dict):
            return dict(
                (sym, v) for sym, v in phi.iteritems() if sym in self.symbols)
        else:
            raise TypeError, phi
 def structure(self, structure, signature, domain=None):
     if domain is None: domain = structure.domain
     domain = MultiDomain.promote(domain)
     s = FolManySortSignature.promote(signature)
     i = structure.interpretation
     explicit_i = {}
     for f, _ in signature.funcs:
         explicit_i[f] = self.join(
             self.function(i[f], from_, domain)
             for from_, _ in s.sort_of(f))
     for p, _ in signature.preds:
         explicit_i[p] = self.join(
             self.predicate(i[p], from_, domain)
             for from_, _ in s.sort_of(p))
     return FolStructure(domain, explicit_i)
     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)}
Beispiel #11
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])
    def __call__(self, z3_elements):
        sorts = FolSorts()
        decls = {}
        for z3_symbol in z3_elements:
            idf = Identifier(z3_symbol.name(), self._get_kind(z3_symbol))
            decls[idf] = z3_symbol
            if is_const(z3_symbol):
                sorts[idf] = FolSorts.FunctionType((), z3_symbol.sort())
            elif is_func_decl(z3_symbol):
                z3_domains = [
                    z3_symbol.domain(i) for i in xrange(z3_symbol.arity())
                ]
                z3_range = z3_symbol.range()
                sorts[idf] = FolSorts.FunctionType(tuple(z3_domains), z3_range)

        sigma = FolManySortSignature.from_sorts(sorts)
        sigma.z3_decls = decls
        return sigma
Beispiel #13
0
 def signature(self):
     """
     Extracts a first-order sorted signature describing the type of
     the structure.
     """
     sorts = FolSorts()
     for name, (args, ret, _) in self.funcs.iteritems():
         # ~ symbols with '!' are reserved for compiler-generated aux
         if not "!" in name:
             nameid = Identifier(
                 name, '?')  # 'kind' will be filled by FolManySortSignature
             argtypes = [
                 Identifier(a.subtrees[0].root, 'sort') for a in args
             ]
             rettype = Identifier(ret.root, 'sort')
             if rettype == 'bool': rettype = ''
             sorts[nameid] = [FolSorts.FunctionType(argtypes, rettype)]
     return FolManySortSignature.from_sorts(sorts)
        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)
 def range_of(self, symbol, signature):
     d = MultiDomain.promote(self.domain)
     s = FolManySortSignature.promote(signature)
     for r in set(to_ for _, to_ in s.sort_of(symbol)):
         for el in d[r]:
             yield el
 def __init__(self):
     self.declarations = FolSorts()
     self.signature = FolManySortSignature(set(), set())
     self.special_symbols = {sym.literal: sym for sym in self.SPECIALTIES}
Beispiel #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
Beispiel #18
0
class SmtLibInputFormat(object):
    class Attribute(object):
        def __init__(self, name, value):
            self.name = name
            self.value = value

        def __str__(self):
            return ":%s %s" % (self.name, self.value)

    def __init__(self, signature=FolManySortSignature(), logic="QF_UF"):
        self.signature = signature
        if not isinstance(signature, FolManySortSignature):
            self.signature = FolManySortSignature(signature.funcs,
                                                  signature.preds)
        self.logic = logic
        self.builtin_mappings = {
            'R': "Real",
            'Z': "Int",
            FolWithEquality.Signature.eq: "="
        }

    def predicates(self, preds):
        S = SchemeExpression
        return S("", [
            S(p,
              self.sort_of(p, a) or [""])
            for p, a in preds if p not in self.builtin_mappings
        ])

    def functions(self, funcs):
        S = SchemeExpression
        return S("", [
            S(f, self.sort_of(f, a))
            for f, a in funcs if f not in self.builtin_mappings
        ])

    def quantified_expression(self, variable):
        S = SchemeExpression
        return S("?%s" % variable, self.sort_of(variable, 0))

    def mkid(self, identifier, *a):
        x = identifier
        return SchemeExpression(self.builtin_mappings.get(x, x), *a)

    def sort_of(self, symbol, arity):
        S = self.mkid
        sr = self.signature.sort_of(symbol, arity)

        if not sr:
            raise TypeError, "No sort for '%s/%d'" % (symbol, arity)

        from_, to_ = sr[0]  # TODO support more than one
        to_ = [x for x in [to_] if x is not None]
        return [S(f) for l in (from_, to_) for f in l]

    def benchmark(self, title):
        return SchemeExpression("benchmark %s" % title)

    def list(self, l):  #@ReservedAssignment
        S = SchemeExpression
        if l:
            return S("", [S.promote(x) for x in l])
        else:
            return S("", [""])

    def formula(self, formula):
        r = formula.root
        quantifiers_and_connectives = {
            FolFormula.FORALL: "forall",
            FolFormula.EXISTS: "exists",
            FolFormula.IMPLIES: "implies",
            FolFormula.AND: "and",
            FolFormula.OR: "or",
            FolFormula.IFF: "iff",
            FolFormula.NOT: "not"
        }
        it = r
        kind = None
        if isinstance(r, FolFormula.Identifier):
            kind = r.kind
            if r.kind == 'quantifier' or r.kind == 'connective':
                it = quantifiers_and_connectives[r]
            if r.kind == 'variable':
                it = "?%s" % r
        S = self.mkid
        if kind == 'quantifier':
            expr = S(it, [
                self.quantified_expression(s.root)
                for s in formula.subtrees[:-1]
            ] + [self.formula(s) for s in formula.subtrees[-1:]])
        else:
            expr = S(it, [self.formula(s) for s in formula.subtrees])
        return self._tree_fold(expr)

    def theory(self, formulas, title="theory"):
        bm = self.benchmark(title)
        A = self.Attribute
        signature = self.signature
        all_sorts = set(["V"]) | self.signature.sorts.set()
        all_sorts = set(x for x in all_sorts if x not in self.builtin_mappings)
        attrs = [
            A("logic", SchemeExpression(self.logic)),
            A("extrasorts", self.list(all_sorts)),
            A("extrafuns", self.functions(signature.funcs)),
            A("extrapreds", self.predicates(signature.preds))
        ]
        attrs = [a for a in attrs if a.value]
        bm.attributes.extend(attrs)
        if formulas:
            bm.attributes.extend(
                [A("assumption", self.formula(f)) for f in formulas[:-1]])
            bm.attributes.append(A("formula", self.formula(formulas[-1])))
        return bm

    def __call__(self, thing):
        if isinstance(thing, list):
            thing = self.theory(thing, "theory")
        elif isinstance(thing, FolFormula):
            thing = self.theory([thing], "formula")
        return thing

    def _tree_fold(self, tree, foldables=("and", "or")):
        r = tree.root
        if r in foldables:
            subs = []
            for s in tree.subtrees:
                if s.root == r:
                    subs.extend(self._tree_fold(s, foldables).subtrees)
                else:
                    subs.append(s)
        else:
            subs = tree.subtrees
        return type(tree)(r, [self._tree_fold(s, foldables) for s in subs])