def convert_from_sortvars(s): """ Convert sort vars to TopSort """ s = find(s) if type(s) is SortVar: return TopSort() elif type(s) is FunctionSort: return FunctionSort(*(convert_from_sortvars(x) for x in s)) else: return s
def insert_sortvars(s, env): """ Convert each named TopSort to a new SortVar """ if type(s) is TopSort and s.is_sort_variable(): if s not in env: env[s] = SortVar() return env[s] elif type(s) is FunctionSort: return FunctionSort(*(insert_sortvars(x, env) for x in s)) else: return s
result.append(False) elif res == z3.unsat: _implies_cache[key] = True result.append(True) else: # no caching of unknown results print "z3 returned: {}".format(res) assert False result.append(None) return result if __name__ == '__main__': S = UninterpretedSort('S') X, Y, Z = (Var(n, S) for n in ['X', 'Y', 'Z']) BinRel = FunctionSort(S, S, Boolean) leq = Const('leq', BinRel) transitive1 = ForAll((X, Y, Z), Implies(And(leq(X, Y), leq(Y, Z)), leq(X, Z))) transitive2 = ForAll((X, Y, Z), Or(Not(leq(X, Y)), Not(leq(Y, Z)), leq(X, Z))) transitive3 = Not( Exists((X, Y, Z), And(leq(X, Y), leq(Y, Z), Not(leq(X, Z))))) antisymmetric = ForAll((X, Y), Implies(And(leq(X, Y), leq(Y, X), true), Eq(Y, X))) print z3_implies(transitive1, transitive2) print z3_implies(transitive2, transitive3) print z3_implies(transitive3, transitive1) print z3_implies(transitive3, antisymmetric) print
def get_standard_combiners(): T = TopSort() UnaryRelation = FunctionSort(T, Boolean) BinaryRelation = FunctionSort(T, T, Boolean) X, Y, Z = (Var(n, T) for n in ['X', 'Y', 'Z']) U = Var('U', UnaryRelation) U1 = Var('U1', UnaryRelation) U2 = Var('U2', UnaryRelation) B = Var('B', BinaryRelation) B1 = Var('B1', BinaryRelation) B2 = Var('B2', BinaryRelation) result = OrderedDict() result['none'] = ConceptCombiner([U], Not(Exists([X], U(X)))) result['at_least_one'] = ConceptCombiner([U], Exists([X], U(X))) result['at_most_one'] = ConceptCombiner([U], ForAll([X,Y], Implies(And(U(X), U(Y)), Eq(X,Y)))) result['node_necessarily'] = ConceptCombiner( [U1, U2], ForAll([X], Implies(U1(X), U2(X))), ) result['node_necessarily_not'] = ConceptCombiner( [U1, U2], ForAll([X], Implies(U1(X), Not(U2(X)))), ) result['mutually_exclusive'] = ConceptCombiner( [U1, U2], ForAll([X, Y], Not(And(U1(X), U2(Y)))) ) result['all_to_all'] = ConceptCombiner( [B, U1, U2], ForAll([X,Y], Implies(And(U1(X), U2(Y)), B(X,Y))) ) result['none_to_none'] = ConceptCombiner( [B, U1, U2], ForAll([X,Y], Implies(And(U1(X), U2(Y)), Not(B(X,Y)))) ) result['total'] = ConceptCombiner( [B, U1, U2], ForAll([X], Implies(U1(X), Exists([Y], And(U2(Y), B(X,Y))))) ) result['functional'] = ConceptCombiner( [B, U1, U2], ForAll([X, Y, Z], Implies(And(U1(X), U2(Y), U2(Z), B(X,Y), B(X,Z)), Eq(Y,Z))) ) result['surjective'] = ConceptCombiner( [B, U1, U2], ForAll([Y], Implies(U2(Y), Exists([X], And(U1(X), B(X,Y))))) ) result['injective'] = ConceptCombiner( [B, U1, U2], ForAll([X, Y, Z], Implies(And(U1(X), U1(Y), U2(Z), B(X,Z), B(Y,Z)), Eq(X,Y))) ) result['node_info'] = ['none', 'at_least_one', 'at_most_one'] if False: # this just slows us down, and it's not clear it's needed # later this should be made customizable by the user result['edge_info'] = ['all_to_all', 'none_to_none', 'total', 'functional', 'surjective', 'injective'] else: result['edge_info'] = ['all_to_all', 'none_to_none'] result['node_label'] = ['node_necessarily', 'node_necessarily_not'] return result
count = defaultdict(int) for c in elements: prefix = str(c.sort).lower() result[c.name] = prefix + str(count[prefix]) count[prefix] += 1 return result if __name__ == '__main__': def test(st): print st, "=", eval(st) S = UninterpretedSort('S') T = TopSort() UnaryRelationS = FunctionSort(S, Boolean) BinaryRelationS = FunctionSort(S, S, Boolean) UnaryRelationT = FunctionSort(T, Boolean) BinaryRelationT = FunctionSort(T, T, Boolean) X, Y, Z = (Var(n, S) for n in ['X', 'Y', 'Z']) r = Const('r', BinaryRelationS) n = Const('n', BinaryRelationS) p = Const('p', UnaryRelationS) q = Const('q', UnaryRelationS) u = Const('u', UnaryRelationS) c11 = Concept([X], And(p(X), q(X))) c10 = Concept([X], And(p(X), Not(q(X))))
def infer_sorts(t, env=None): """ Infer the sort of term t in environment env. env maps symbol names to sort variables. The result is a pair: (s, tt) where s is a sort or sort variable with the sort of t in env, and tt is a closure that, when called, will concretize t according to inferred sort information at its call time. If env is not None, it must contain all the free variables and constants used in t. """ if env is None: names = free_variables(t, by_name=True).union(x.name for x in used_constants(t)) env = dict((name, SortVar()) for name in names) if type(t) in (Var, Const): if is_polymorphic(t): # each instance can have different sort s = insert_sortvars(t.sort, {}) else: s = env[t.name] unify(s, t.sort) return s, lambda: type(t)(t.name, convert_from_sortvars(s)) elif type(t) is Apply: func_s, func_t = infer_sorts(t.func, env) xys = [infer_sorts(tt, env) for tt in t.terms] terms_s = [x for x, y in xys] terms_t = [y for x, y in xys] sorts = terms_s + [SortVar()] unify(func_s, FunctionSort(*sorts)) return sorts[-1], lambda: Apply(func_t(), *(x() for x in terms_t)) elif type(t) is Eq: s1, t1 = infer_sorts(t.t1, env) s2, t2 = infer_sorts(t.t2, env) unify(s1, s2) return Boolean, lambda: Eq(t1(), t2()) elif type(t) is Ite: s_cond, t_cond = infer_sorts(t.cond, env) s_then, t_then = infer_sorts(t.t_then, env) s_else, t_else = infer_sorts(t.t_else, env) unify(s_cond, Boolean) unify(s_then, s_else) return s_then, lambda: Ite(t_cond(), t_then(), t_else()) elif type(t) in (Not, And, Or, Implies, Iff): xys = [infer_sorts(tt, env) for tt in t] terms_s = [x for x, y in xys] terms_t = [y for x, y in xys] for s in terms_s: unify(s, Boolean) return Boolean, lambda: type(t)(*[x() for x in terms_t]) elif type(t) in (ForAll, Exists): # create a copy of the environment and shadow that quantified # variables env = env.copy() env.update((v.name, SortVar()) for v in t.variables) vars_t = [infer_sorts(v, env)[1] for v in t.variables] body_s, body_t = infer_sorts(t.body, env) unify(body_s, Boolean) return Boolean, lambda: type(t)( [x() for x in vars_t], body_t(), ) elif hasattr(t, 'clone'): xys = [infer_sorts(tt, env) for tt in t.args] terms_t = [y for x, y in xys] return TopSort(), lambda: t.clone([x() for x in terms_t]) else: assert False, type(t)
return result if __name__ == '__main__': from collections import ConceptDict from logic import (Var, Const, Apply, Eq, Not, And, Or, Implies, ForAll, Exists) from logic import UninterpretedSort, FunctionSort, first_order_sort, Boolean from logic_util import free_variables, substitute, substitute_apply from concept import Concept, ConceptCombiner, ConceptDomain def test(st): print st, "=", eval(st) S = UninterpretedSort('S') UnaryRelation = FunctionSort(S, Boolean) BinaryRelation = FunctionSort(S, S, Boolean) X, Y, Z = (Var(n, S) for n in ['X', 'Y', 'Z']) U = Var('U', UnaryRelation) U1 = Var('U1', UnaryRelation) U2 = Var('U2', UnaryRelation) B = Var('B', BinaryRelation) B1 = Var('B1', BinaryRelation) B2 = Var('B2', BinaryRelation) nstar = Const('nstar', BinaryRelation) x = Const('x', S) y = Const('y', S) c11 = Concept('xy', [X], And(Eq(x, X), Eq(y, X)))