def get_initial_concept_domain(sig): """ sig is an ivy_logic.Sig object """ concepts = OrderedDict() concepts['nodes'] = [] concepts['node_labels'] = [] concepts['edges'] = [] # add sort concepts for s in sorted(sig.sorts.values()): X = Var('X', s) concepts[s.name] = Concept([X], Eq(X,X)) concepts['nodes'].append(s.name) # add equality concept X = Var('X', TopSort()) Y = Var('Y', TopSort()) concepts['='] = Concept([X, Y], Eq(X, Y)) # add concepts from relations for c in sorted(sig.symbols.values()): assert type(c) is Const if first_order_sort(c.sort): # first order constant, add unary equality concept X = Var('X', c.sort) name = '={}'.format(c.name) concepts[name] = Concept([X], Eq(X,c)) elif type(c.sort) is FunctionSort and c.sort.arity == 1: # add unary concept and label X = Var('X', c.sort.domain[0]) name = '{}'.format(c.name) concepts[name] = Concept([X], c(X)) elif type(c.sort) is FunctionSort and c.sort.arity == 2: # add binary concept and edge X = Var('X', c.sort.domain[0]) Y = Var('Y', c.sort.domain[1]) name = '{}'.format(c.name) concepts[name] = Concept([X, Y], c(X, Y)) elif type(c.sort) is FunctionSort and c.sort.arity == 3: # add ternary concept X = Var('X', c.sort.domain[0]) Y = Var('Y', c.sort.domain[1]) Z = Var('Z', c.sort.domain[2]) name = '{}'.format(c.name) concepts[name] = Concept([X, Y, Z], c(X, Y, Z)) else: # skip other symbols pass return ConceptDomain(concepts, get_standard_combiners(), get_standard_combinations())
def get_diagram_concept_domain(sig, diagram): """ sig is an ivy_logic.Sig object diagram is a formula """ concepts = OrderedDict() concepts['nodes'] = [] concepts['node_labels'] = [] concepts['edges'] = [] # add equality concept X = Var('X', TopSort()) Y = Var('Y', TopSort()) concepts['='] = Concept([X, Y], Eq(X, Y)) # add concepts from relations and constants in the signature and # in the diagram if sig is not None: sig_symbols = frozenset(sig.symbols.values()) else: sig_symbols = frozenset() for c in sorted(sig_symbols | used_constants(diagram)): assert type(c) is Const if first_order_sort(c.sort): # first order constant, add unary equality concept X = Var('X', c.sort) name = '{}:{}'.format(c.name, c.sort) concepts[name] = Concept([X], Eq(X,c)) concepts['nodes'].append(name) elif type(c.sort) is FunctionSort and c.sort.arity == 1: # add unary concept and label X = Var('X', c.sort.domain[0]) name = '{}'.format(c.name) concepts[name] = Concept([X], c(X)) elif type(c.sort) is FunctionSort and c.sort.arity == 2: # add binary concept and edge X = Var('X', c.sort.domain[0]) Y = Var('Y', c.sort.domain[1]) name = '{}'.format(c.name) concepts[name] = Concept([X, Y], c(X, Y)) elif type(c.sort) is FunctionSort and c.sort.arity == 3: # add ternary concept X = Var('X', c.sort.domain[0]) Y = Var('Y', c.sort.domain[1]) Z = Var('Z', c.sort.domain[2]) name = '{}'.format(c.name) concepts[name] = Concept([X, Y, Z], c(X, Y, Z)) else: # skip other symbols pass return ConceptDomain(concepts, get_standard_combiners(), get_standard_combinations())
def generate(self): """ generate variable with new name Returns ------- generated_var : .logic.Var generated variable """ generated_var = Var(self.base_name + str(self.counter)) self.counter += 1 return generated_var
def _materialize_node(self, concept_name): """ Materialize a node, returns the witness constant """ concept = self.domain.concepts[concept_name] assert concept.arity == 1 sort = concept.variables[0].sort assert sort != TopSort() witnesses = self._get_witnesses(concept_name) if len(witnesses) > 0: c = witnesses[0] else: c = Const(self._fresh_const_name(), sort) # TODO: maybe we shouldn't split here, and create the concepts explicitly X = Var('X', c.sort) name = '={}'.format(c.name) self.domain.concepts[name] = Concept(name, [X], Eq(X, c)) self.domain.split(concept_name, name) self.suppose(concept(c)) return c
_implies_cache[key] = False 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)
def get_clauses(self): clause1 = Clause(Atom(self.preds[0], [Var('X'), Var('Y')]), []) self.clauses = [clause1]
elif ((type(t) is ForAll and type(t.body) is And) or (type(t) is Exists and type(t.body) is Or)): return normalize_quantifiers( type(t.body)(*(type(t)(t.variables, x) for x in t.body))) elif type(t) in (ForAll, Exists): return type(t)(free_variables(t.body) & frozenset(t.variables), normalize_quantifiers(t.body)) else: assert False, type(t) def is_tautology_equality(t): """Returns True if t is Eq(x,x) for some x""" return type(t) is Eq and t.t1 == t.t2 if __name__ == '__main__': from logic import * s1 = UninterpretedSort('s1') s2 = UninterpretedSort('s2') X1 = Var('X', s1) X2 = Var('X', s2) f = ForAll([X1], Eq(X2, X2)) assert free_variables(f) == {X2} assert free_variables(f, by_name=True) == set() assert free_variables(f.body) == {X2} assert free_variables(f.body, by_name=True) == {'X'}
def get_structure_concept_domain(state, sig=None): """ state is an ivy_interp.State with a .universe sig is an ivy_logic.Sig object """ concepts = OrderedDict() concepts['nodes'] = [] concepts['node_labels'] = [] # add equality concept X = Var('X', TopSort()) Y = Var('Y', TopSort()) concepts['='] = Concept([X, Y], Eq(X, Y)) # add nodes for universe elements elements = [uc for s in state.universe for uc in state.universe[s]] for uc in sorted(elements): # add unary equality concept X = Var('X', uc.sort) name = uc.name if str(uc.sort) not in name: name += ':{}'.format(uc.sort) concepts[name] = Concept([X], Eq(X,uc)) concepts['nodes'].append(name) # # find which symbols are equal to which universe constant # equals = dict( # (uc, [c for c in symbols # if c != uc and # c.sort == s and # z3_implies(state_formula, Eq(c, uc))]) # for s in state.universe # for uc in state.universe[s] # ) # add concepts for relations and constants state_formula = state.clauses.to_formula() symbols = used_constants(state_formula) if sig is not None: symbols = symbols | frozenset(sig.symbols.values()) symbols = symbols - frozenset(elements) symbols = sorted(symbols) for c in symbols: assert type(c) is Const if first_order_sort(c.sort): # first order constant, add unary equality concept X = Var('X', c.sort) name = '={}'.format(c.name) concepts[name] = Concept([X], Eq(X,c)) elif type(c.sort) is FunctionSort and c.sort.arity == 1: # add unary concept and label X = Var('X', c.sort.domain[0]) name = '{}'.format(c.name) concepts[name] = Concept([X], c(X)) elif type(c.sort) is FunctionSort and c.sort.arity == 2: # add binary concept and edge X = Var('X', c.sort.domain[0]) Y = Var('Y', c.sort.domain[1]) name = '{}'.format(c.name) concepts[name] = Concept([X, Y], c(X, Y)) elif type(c.sort) is FunctionSort and c.sort.arity == 3: # add ternary concept X = Var('X', c.sort.domain[0]) Y = Var('Y', c.sort.domain[1]) Z = Var('Z', c.sort.domain[2]) name = '{}'.format(c.name) concepts[name] = Concept([X, Y, Z], c(X, Y, Z)) else: # skip other symbols pass return ConceptDomain(concepts, get_standard_combiners(), get_standard_combinations())
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
if sorts is not None: for (s, tt), sort in zip(pairs, sorts): unify(s, sort) return [tt() for s, tt in pairs] if __name__ == '__main__': S = UninterpretedSort('S') T = TopSort() UnaryRelationS = FunctionSort(S, Boolean) BinaryRelationS = FunctionSort(S, S, Boolean) UnaryRelationT = FunctionSort(T, Boolean) BinaryRelationT = FunctionSort(T, T, Boolean) XS, YS = (Var(n, S) for n in ['X', 'Y']) XT, YT = (Var(n, T) for n in ['X', 'Y']) xs, ys = (Const(n, S) for n in ['x', 'y']) xt, yt = (Const(n, T) for n in ['x', 'y']) rs = Const('r', BinaryRelationS) ps = Const('p', UnaryRelationS) rt = Const('r', BinaryRelationT) pt = Const('p', UnaryRelationT) tt = Const('tt', T) TT = Var('TT', T) f1 = And(ps(XS), ps(xs)) cf1 = concretize_sorts(f1) print repr(f1)
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))) c10 = Concept('x', [X], And(Eq(x, X), Not(Eq(y, X)))) c01 = Concept('y', [X], And(Not(Eq(x, X)), Eq(y, X))) c00 = Concept('other', [X], And(Not(Eq(x, X)), Not(Eq(y, X))))