def testfunc(mod): # for testing/ debugging ns = logic.UninterpretedSort("node") ids = logic.UninterpretedSort('id') n1 = logic.Var('Node0', ns) n2 = logic.Var('Node1', ns) ineq = logic.Not(logic.Eq(n2, n1)) leadsorts = [ns, logic.BooleanSort()] leadfunc = logic.Const("leader", logic.FunctionSort(*leadsorts)) idsorts = [ns, logic.UninterpretedSort("id")] idfunc = logic.Const("idn", logic.FunctionSort(*idsorts)) lesorts = [ids, ids, logic.BooleanSort()] lefunc = logic.Const('le', logic.FunctionSort(*lesorts)) leadterm = logic.Apply(leadfunc, *[n1]) leterm = logic.Apply( lefunc, *[logic.Apply(idfunc, *[n1]), logic.Apply(idfunc, *[n2])]) fmla = logic.Not(logic.And(*[ineq, leadterm, leterm])) candInv, coincide = Clauses([fmla]), false_clauses() print "<plearn> CandInv", candInv for actname in sorted(mod.public_actions): spos, sneg = samplePos(mod, candInv, coincide, actname), sampleNeg(mod, candInv, actname) spos, sneg = Sample(spos, '1'), Sample(sneg, '0') if hasattr(spos, 'interp'): print "<plearn> + interp: ", spos.interp spos.displaySample() if hasattr(sneg, 'interp'): print "<plearn> - interp: ", sneg.interp sneg.displaySample() exit(0)
def interp_from_unsat_core(clauses1, clauses2, core, interpreted): used_syms = used_symbols_clauses(core) vars = used_variables_clauses(core) if vars: # print "interpolant would require skolem constants" return None core_consts = used_constants_clauses(core) clauses2_consts = used_constants_clauses(clauses2) # print "interp_from_unsat_core core_consts = {}".format(map(str,core_consts)) # print "interp_from_unsat_core clauses2_consts = {}".format(map(str,clauses2_consts)) renaming = dict() i = 0 for v in core_consts: if v not in clauses2_consts or v.is_skolem( ): # and v not in interpreted: renaming[v] = Variable('V' + str(i), Constant(v).get_sort()) i += 1 # print "interp_from_unsat_core core = {}".format(core) # print "interp_from_unsat_core renaming = {}".format(renaming) renamed_core = substitute_constants_clauses(core, renaming) # print "interp_from_unsat_core renamed_core = {}".format(renamed_core) res = simplify_clauses( Clauses([Or(*[negate(c) for c in renamed_core.fmlas])])) # print "interp_from_unsat_core res = {}".format(res) return res
def mk_variant_assign_clauses(lhs, rhs): n = lhs.rep new_n = new(n) args = lhs.args dlhs = new_n(*sym_placeholders(n)) vs = dlhs.args eqs = [ eq_atom(v, a) for (v, a) in zip(vs, args) if not isinstance(a, Variable) ] rn = dict((a.rep, v) for v, a in zip(vs, args) if isinstance(a, Variable)) drhs = substitute_ast(rhs, rn) nondet = n.suffix("_nd").skolem() if eqs: nondet = Ite(And(*eqs), nondet, n(*dlhs.args)) lsort, rsort = lhs.sort, rhs.sort fmlas = [ Iff( pto(lsort, rsort)(dlhs, Variable('X', rsort)), Equals(Variable('X', rsort), drhs)) ] for s in ivy_module.module.variants[lsort.name]: if s != rsort: fmlas.append(Not(pto(lsort, s)(dlhs, Variable('X', s)))) new_clauses = Clauses(fmlas, [Definition(dlhs, nondet)]) return new_clauses
def autodetect_transitive(self): import logic as lg from ivy_logic_utils import Clauses from ivy_solver import clauses_imply from concept import Concept # self.edge_display_checkboxes['=']['transitive'].value = True # self.edge_display_checkboxes['=']['all_to_all'].value = True self.transitive_relations = [] self.transitive_relation_concepts = [] axioms = im.module.background_theory() for c in il.all_symbols(): if (type(c.sort) is lg.FunctionSort and c.sort.arity == 2 and c.sort.domain[0] == c.sort.domain[1] and c.sort.range == lg.Boolean): X = lg.Var('X', c.sort.domain[0]) Y = lg.Var('Y', c.sort.domain[0]) Z = lg.Var('Z', c.sort.domain[0]) transitive = lg.ForAll([X, Y, Z], lg.Or(lg.Not(c(X, Y)), lg.Not(c(Y, Z)), c(X, Z))) defined_symmetry = lg.ForAll([X, Y], lg.Or(c(X, X), lg.Not(c(Y, Y)))) t = Clauses([transitive, defined_symmetry]) if clauses_imply(axioms, t): self.transitive_relations.append(c.name) concept = self.current_concept_graph.g.formula_to_concept( c(X, Y)) self.transitive_relation_concepts.append(concept) self.current_concept_graph.show_relation(concept, 'T') if self.transitive_relations: self.current_concept_graph.update()
def unsat_core(clauses1, clauses2, implies=None, unlikely=lambda x: False): # print "unsat_core clauses1 = {}, clauses2 = {}".format(clauses1,clauses2) # assert clauses1.defs == [] fmlas = clauses1.fmlas s2 = z3.Solver() alits = [z3.Const("__c%s" % n, z3.BoolSort()) for n, c in enumerate(fmlas)] cc = [z3.Or(z3.Not(a), formula_to_z3(c)) for a, c in zip(alits, fmlas)] foo = [(a, f) for a, f in zip(alits, fmlas) if unlikely(f)] unlikely_lits = [a for a, f in foo] for d in clauses1.defs: s2.add(formula_to_z3(d.to_constraint())) for c in cc: s2.add(c) s2.add(clauses_to_z3(clauses2)) if implies is not None: s2.add(not_clauses_to_z3(implies)) is_sat = s2.check(alits) if is_sat == z3.sat: # print "unsat_core model = {}".format(get_model(s2)) return None if unlikely_lits: core = biased_core(s2, alits, unlikely_lits) else: core = minimize_core(s2) core_ids = [get_id(a) for a in core] res = [c for a, c in zip(alits, fmlas) if get_id(a) in core_ids] # print "unsat_core res = {}".format(res) return Clauses(res, list(clauses1.defs))
def model_facts(h, ignore, clauses1, upclose=False): # define the universe for each sort: uc = [ fact for s in h.sorts() for fact in model_universe_facts(h, s, upclose) ] # values of constants in formula temp = [[(ivy_logic.Constant(c), get_model_constant(h.model, ivy_logic.Constant(c)))] for c in used_constants_clauses(clauses1) if not ignore(c) and c not in ivy_logic.sig.constructors] # print "temp = {}".format(temp) vc = [[ ivy_logic._eq_lit(ivy_logic.Constant(c), get_model_constant(h.model, ivy_logic.Constant(c))) ] for c in used_constants_clauses(clauses1) if not ignore(c) and c not in ivy_logic.sig.constructors] # print "model_facts vc = {}".format(vc) # values of relations in formula # print "used_relations_clauses = {}".format(used_relations_clauses(clauses1)) vr = [[l] for (r, n) in used_relations_clauses(clauses1).iteritems() if not ignore(r) for l in relation_model_to_clauses(h, r, n)] # values of functions in formula fns = set(f for (f, arity) in functions_clauses(clauses1) if not ignore(f) and arity >= 1) vf = [[l] for f in fns for l in function_model_to_clauses(h, f)] res = uc + vc + vr + vf return Clauses(res)
def filter_redundant_facts(clauses, axioms): """ Filter out redundant constraints from "clauses", given the "axioms". Currently, this removes only negative formulas that are implied by the positive formulas, so it should work well for facts about total orders, for example. """ fmlas = clauses.fmlas pos_fmlas = [fmla for fmla in fmlas if not isinstance(fmla, ivy_logic.Not)] neg_fmlas = [fmla for fmla in fmlas if isinstance(fmla, ivy_logic.Not)] s2 = z3.Solver() alits = [ z3.Const("__c%s" % n, z3.BoolSort()) for n, c in enumerate(neg_fmlas) ] cc = [ z3.Or(z3.Not(a), z3.Not(formula_to_z3(c))) for a, c in zip(alits, neg_fmlas) ] s2.add(clauses_to_z3(axioms)) for d in clauses.defs: s2.add(formula_to_z3(d.to_constraint())) for fmla in pos_fmlas: s2.add(formula_to_z3(fmla)) for c in cc: s2.add(c) keep = [] for fmla, alit in zip(neg_fmlas, alits): if decide(s2, [alit]) == z3.sat: keep.append(fmla) # print "unsat_core res = {}".format(res) return Clauses(pos_fmlas + keep, list(clauses.defs))
def minimize_conjecture(self, button=None, bound=None): import ivy_transrel import ivy_solver from proof import ProofGoal from ivy_logic_utils import Clauses, and_clauses, dual_clauses, used_symbols_clauses, negate from ivy_solver import unsat_core from logic_util import free_variables, substitute if self.bmc_conjecture(bound=bound): # found a BMC counter-example return with self.ui_parent.run_context(): step_action = im.module.actions['ext'] n_steps = self.current_bound ag = self.parent.new_ag() with ag.context as ac: post = ac.new_state(ag.init_cond) if 'initialize' in im.module.actions: init_action = im.module.actions['initialize'] post = ag.execute(init_action, None, None, 'initialize') for n in range(n_steps): post = ag.execute(step_action, None, None, 'ext') axioms = im.module.background_theory() post_clauses = and_clauses(post.clauses, axioms) used_names = (frozenset(x.name for x in il.sig.symbols.values()) | frozenset( x.name for x in used_symbols_clauses(post_clauses))) facts = self.get_active_facts() assert not any(c.is_skolem() and c.name in used_names for c in lu.used_constants(*facts)) core = unsat_core(Clauses(facts), post_clauses) if core is None: core = Clauses([]) ## can happen if we are proving true # assert core is not None, "bmc_conjecture returned False but unsat core is None" core_formulas = frozenset(core.fmlas) self.set_facts([fact for fact in facts if fact in core_formulas]) self.highlight_selected_facts() self.ui_parent.text_dialog( "BMC found the following possible conjecture:", str(self.get_selected_conjecture()))
def get_selected_conjecture(self): """ Return a positive universal conjecture based on the selected facts. The result is a Clauses object """ from logic_util import used_constants, free_variables, substitute from ivy_logic_utils import negate, Clauses, simplify_clauses facts = self.get_active_facts() assert len(free_variables( * facts)) == 0, "conjecture would contain existential quantifiers..." sig_symbols = frozenset(il.sig.symbols.values()) facts_consts = used_constants(*facts) subs = {} rn = iu.VariableGenerator() for c in sorted(facts_consts, key=lambda c: c.name): if c.is_numeral() and il.is_uninterpreted_sort(c.sort): # prefix = str(c.sort)[:2].upper() + c.name subs[c] = lg.Var(rn(c.sort.name), c.sort) literals = [negate(substitute(f, subs)) for f in facts] result = Clauses([lg.Or(*literals)]) result = simplify_clauses(result) # now rename again to get a pretty clause, since some # variables have been eliminated by simplify_clauses # assert len(result.fmlas) == 1 # clause = result.fmlas[0] # subs = {} # count = defaultdict(int) # for c in free_variables(clause): # prefix = str(c.sort)[0].upper() # count[prefix] += 1 # subs[c] = lg.Var(prefix + str(count[prefix]), c.sort) # result = Clauses([substitute(clause, subs)]) # change to negation of conjunction rather than disjunction assert len(result.fmlas) == 1 if type(result.fmlas[0]) is lg.Or: result = Clauses( [lg.Not(lg.And(*(negate(lit) for lit in result.fmlas[0])))]) return result
def satisfy(self, axioms, _get_model_clauses=None, final_cond=None): """ Produce a state sequence if the symbolic history contains one. Returns the sort universes and a sequence of states, or None if the history is vacuous. """ if _get_model_clauses is None: _get_model_clauses = small_model_clauses # print "axioms: {}".format(axioms) # A model of the post-state embeds a valuation for each time # in the history. # print "concrete state: {}".format(self.post) # print "background: {}".format(axioms) post = and_clauses(self.post, axioms) # print "bounded check {" model = _get_model_clauses(post, final_cond=final_cond) # print "} bounded check" if model == None: # print "core = {}".format(unsat_core(post,true_clauses())) return None # we reconstruct the sub-model for each state composing the # recorded renamings in reverse order. Here "renaming" maps # symbols representing a past time onto current time skolems renaming, states, maps = {}, [], reversed(self.maps) while True: # ignore all symbols except those representing the given past time img = set(renaming[s] for s in renaming if not s.is_skolem()) ignore = lambda s: self.ignore(s, img, renaming) # get the sub-mode for the given past time as a formula if isinstance(final_cond, list): final_cond = or_clauses(*[fc.cond() for fc in final_cond]) all_clauses = and_clauses( post, final_cond) if final_cond != None else post clauses = clauses_model_to_clauses(all_clauses, ignore=ignore, model=model, numerals=use_numerals()) # map this formula into the past using inverse map clauses = rename_clauses(clauses, inverse_map(renaming)) # remove tautology equalities, TODO: not sure if this is correct here clauses = Clauses( [f for f in clauses.fmlas if not is_tautology_equality(f)], clauses.defs) states.append(clauses) try: # update the inverse map by composing it with inverse # of the next renaming (in reverse order) renaming = compose_maps(next(maps), renaming) except StopIteration: break uvs = model.universes(numerals=use_numerals()) # print "uvs: {}".format(uvs) return uvs, [pure_state(clauses) for clauses in reversed(states)]
def action_update(self, domain, pvars): lhs, rhs = self.args n = lhs.rep # Handle the hierarchical case if n in domain.hierarchy: asgns = [ postfix_atoms_ast(self, Atom(x, [])) for x in domain.hierarchy[n] ] res = unzip_append( [asgn.action_update(domain, pvars) for asgn in asgns]) return res # If the lhs application is partial, make it total by adding parameters xtra = len(lhs.rep.sort.dom) - len(lhs.args) if xtra < 0: raise IvyError(self, "too many parameters in assignment to " + lhs.rep) if xtra > 0: extend = sym_placeholders(lhs.rep)[-xtra:] extend = variables_distinct_list_ast(extend, self) # get unused variables lhs = add_parameters_ast(lhs, extend) # Assignment of individual to a boolean is a special case if is_individual_ast(rhs) and not is_individual_ast(lhs): rhs = eq_atom(extend[-1], add_parameters_ast(rhs, extend[0:-1])) else: rhs = add_parameters_ast(rhs, extend) type_check(domain, rhs) if is_individual_ast(lhs) != is_individual_ast(rhs): # print type(lhs.rep) # print str(lhs.rep) # print type(lhs.rep.sort) # print "lhs: %s: %s" % (lhs,type(lhs)) # print "rhs: %s: %s" % (rhs,type(rhs)) raise IvyError(self, "sort mismatch in assignment to {}".format(lhs.rep)) new_n = new(n) args = lhs.args dlhs = new_n(*sym_placeholders(n)) vs = dlhs.args eqs = [ eq_atom(v, a) for (v, a) in zip(vs, args) if not isinstance(a, Variable) ] rn = dict( (a.rep, v) for v, a in zip(vs, args) if isinstance(a, Variable)) drhs = substitute_ast(rhs, rn) if eqs: drhs = Ite(And(*eqs), drhs, n(*dlhs.args)) new_clauses = Clauses([], [Definition(dlhs, drhs)]) # print "assign new_clauses = {}".format(new_clauses) return ([n], new_clauses, false_clauses())
def sampleNeg(mod, candInv, actname): lcs = mod.labeled_conjs conjs = [Clauses([lc.formula]) for lc in lcs] fcs = [icheck.ConjChecker(c) for c in lcs] # also negates the fmla preclause = and_clauses(candInv, *conjs) # print "<plearn> checking for action- ", actname res = sampleUtil(mod, preclause, fcs, actname) # print candInv # a = raw_input('tried for neg sample') return res
def arg_remove_facts(node, *facts): """ Remove facts from arg node facts should be formulas from node.clauses.fmlas """ c = node.clauses to_remove = frozenset(facts) node.clauses = Clauses( [f for f in c.fmlas if f not in to_remove], list(c.defs), )
def frame_update(update, in_scope, sig): """ Modify an update so all symbols in "in_scope" are on the update list, preserving semantics. """ updated, clauses, pre = update moded = set(updated) dfns = [] for sym in in_scope: if sym not in moded: updated.append(sym) dfns.append(frame_def(sym, new)) return (updated, and_clauses(clauses, Clauses([], dfns)), pre)
def interpolant_case(pre_state,post,axioms,interpreted): # print "interpolant_case: before clauses_case" # print "interpolant_case post: {}".format(post) post_case = clauses_case(post) # print "interpolant_case: after clauses_case" ## print "post_case1: {}".format(post_case) post_case = Clauses([cl for cl in post_case.clauses if len(cl) <= 1 and is_ground_clause(cl) and not any(is_skolem(r) for r,n in relations_clause(cl))]) # print "interpolant_case: after filtering" # print "post_case2: {}".format(post_case) return interpolant(pre_state,post_case,axioms,interpreted)
def mk_assign_clauses(lhs,rhs): n = lhs.rep new_n = new(n) args = lhs.args dlhs = new_n(*sym_placeholders(n)) vs = dlhs.args eqs = [eq_atom(v,a) for (v,a) in zip(vs,args) if not isinstance(a,Variable)] rn = dict((a.rep,v) for v,a in zip(vs,args) if isinstance(a,Variable)) drhs = substitute_ast(rhs,rn) if eqs: drhs = Ite(And(*eqs),drhs,n(*dlhs.args)) new_clauses = Clauses([],[Definition(dlhs,drhs)]) return new_clauses
def toClauses(self): ''' converts decision tree to Clause. ''' bintree = self.clf.tree_ # the underlying decision tree of clf # first we will build a formula and then build a Clause def tofmla(node): ''' encodes the subtree with root represented by node to fmla node is of type int ''' global featureset if bintree.children_right[node] != bintree.children_left[ node]: # not a leaf assert bintree.feature[ node] != _tree.TREE_UNDEFINED, "parent node uses undefined feature" assert isinstance(bintree.feature[node], int), "feature returned is not int" threshold = bintree.threshold[node] assert not (threshold == 0 or threshold == 1 ), "threshold=({}, {}) adds no information".format( type(threshold), threshold) feat = featureset[ bintree.feature[node]] # object of class Predicate ivyFeat = predToivyFmla(feat) fmlaleft = tofmla( bintree.children_left[node] ) # left branch means case when ivyFeat is false fmlaright = tofmla(bintree.children_right[node]) if fmlaright == logic.And(): # fmlaright == True return simplifyOr(ivyFeat, fmlaleft) if fmlaleft == logic.And(): return simplifyOr(logic.Not(ivyFeat), fmlaright) f1 = simplifyAnd(logic.Not(ivyFeat), fmlaleft) f2 = simplifyAnd(ivyFeat, fmlaright) return simplifyOr(f1, f2) else: # is leaf numdata = bintree.value[node][ 0] # gives number of data points for each class, 0 here because its a unioutput clf if numdata[0] != 0: assert len(numdata) == 1 or numdata[ 1] == 0, "leaf node has mixed data points" ntype = self.clf.classes_[0] else: assert len(numdata) == 2 and numdata[ 1] != 0, "clf is not a biclass clf" ntype = self.clf.classes_[1] return logic.And() if ntype == '1' else logic.Or( ) # and with no argument is true, or with no args is false seprfmla = tofmla(0) # 0 is the root of tree return Clauses([seprfmla])
def update_frame_constraint(update, relations): """ Return a clause list constraining all updated symbols to keep their previous values """ clauses = [] for sym in update[0]: if sym in relations: arity = relations[sym] vs = [Variable("V{}".format(i)) for i in range(0, arity)] lit1 = Literal(1, Atom(sym, vs)) lit2 = Literal(1, Atom(new(sym), vs)) clauses += [[~lit1, lit2], [lit1, ~lit2]] else: clauses.append([eq_lit(Constant(sym), Constant(new(sym)))]) return Clauses(clauses)
def samplePos(mod, candInv, coincide, actname): lcs = mod.labeled_conjs conjs = [Clauses([lc.formula]) for lc in lcs] fcs = [icheck.ConjChecker(c, invert=False) for c in lcs] negateci, negateCoincide = negate_clauses(candInv), negate_clauses( coincide) assert isinstance(negateci, Clauses) and isinstance( negateCoincide, Clauses), "negation causes type change" preclause = and_clauses(negateci, negateCoincide, *conjs) print "preclause: ", preclause print "not coincide: ", negateCoincide # print "<plearn> checking for action+ ", actname res = sampleUtil(mod, preclause, fcs, actname) a = raw_input('tried for pos sample') return res
def post_step(self, concept_spaces): if self.unsat: return false_clauses() self.inferred = [] # print "cs: {}".format(concept_spaces) for atom, cs in concept_spaces: if log: print "concept space: %s" % atom concepts = cs.enumerate(self.memo, self.test_cube) if log: print "result: {}".format([str(c) for c in concepts]) self.memo[atom.relname] = ([t.rep for t in atom.args], concepts) res = self.inferred if log: print "inferred: {}".format([[str(c) for c in cls] for cls in res]) del self.inferred return Clauses(res)
def bound_quantifiers_clauses(h,clauses,reps): """ Bound the universal quantifiers in "clauses" to just the terms in Herbrand model h. This applies only to quantifiers in the constraints of "clauses" and not to the definitions. The map reps gives representatives for the terms in the Herbrand universe.""" def bdv(v): """ Return a formula bounding a variable of ubninterpreted sort """ eqs = [ivy_logic.Equals(v,reps[c.rep]) for c in h.sort_universe(v.sort)] return ivy_logic.Or(*eqs) def bq(fmla): """ Bound the free variables in fmla of uninterpeted sort """ vs = list(sorted(used_variables_ast(fmla))) vs = [v for v in vs if not ivy_logic.is_interpreted_sort(v.sort)] cnsts = [bdv(v) for v in vs] bq_res = ivy_logic.Implies(ivy_logic.And(*cnsts),fmla) if cnsts else fmla return bq_res new_fmlas = map(bq,clauses.fmlas) return Clauses(fmlas=new_fmlas,defs=list(clauses.defs))
def checkInitialCond(mod): print "\nChecking if Initialization establishes the learned invariants" print "\n Invariants are: " for lc in mod.labeled_conjs: print " {}".format(Clauses([lc.formula])) print '' with itp.EvalContext(check=False): ag = ivy_art.AnalysisGraph(initializer=lambda x: None) lcs = mod.labeled_conjs fcs = [icheck.ConjChecker(c) for c in lcs] history = ag.get_history(ag.states[0]) gmc = lambda cls, final_cond: itr.small_model_clauses( cls, final_cond, shrink=True) axioms = mod.background_theory() model = history.satisfy(axioms, gmc, fcs) smpl = Sample(model, '-1') # this sample has no post state if hasattr(smpl, 'interp'): # smpl is not None print "<plearn> + sample interpretation : ", smpl.interp, "\n" # for detailed information smpl.displaySample() # for displaying the sample print "\nInitialization establishes the learned Invariant: FAIL" else: print "\nInitialization establishes the learned Invariant: PASS"
def action_update(self,domain,pvars): lhs,rhs = self.args n = lhs.rep # Handle the hierarchical case if n in domain.hierarchy: asgns = [postfix_atoms_ast(self,Atom(x,[])) for x in domain.hierarchy[n]] res = unzip_append([asgn.action_update(domain,pvars) for asgn in asgns]) return res # If the lhs application is partial, make it total by adding parameters xtra = len(lhs.rep.sort.dom) - len(lhs.args) if xtra < 0: raise IvyError(self,"too many parameters in assignment to " + lhs.rep) if xtra > 0: extend = sym_placeholders(lhs.rep)[-xtra:] extend = variables_distinct_list_ast(extend,self) # get unused variables lhs = add_parameters_ast(lhs,extend) # Assignment of individual to a boolean is a special case if is_individual_ast(rhs) and not is_individual_ast(lhs): rhs = eq_atom(extend[-1],add_parameters_ast(rhs,extend[0:-1])) else: rhs = add_parameters_ast(rhs,extend) lhs_vars = used_variables_ast(lhs) if any(v not in lhs_vars for v in used_variables_ast(rhs)): print self raise IvyError(self,"multiply assigned: {}".format(lhs.rep)) type_check(domain,rhs) if is_individual_ast(lhs) != is_individual_ast(rhs): # print type(lhs.rep) # print str(lhs.rep) # print type(lhs.rep.sort) # print "lhs: %s: %s" % (lhs,type(lhs)) # print "rhs: %s: %s" % (rhs,type(rhs)) raise IvyError(self,"sort mismatch in assignment to {}".format(lhs.rep)) # For a destructor assignment, we actually mutate the first argument if n.name in ivy_module.module.destructor_sorts: mut = lhs.args[0] rest = list(lhs.args[1:]) mut_n = mut.rep nondet = mut_n.suffix("_nd").skolem() new_clauses = mk_assign_clauses(mut_n,nondet(*sym_placeholders(mut_n))) fmlas = [] nondet_lhs = lhs.rep(*([nondet(*mut.args)]+rest)) fmlas.append(equiv_ast(nondet_lhs,rhs)) vs = sym_placeholders(n) dlhs = n(*([nondet(*mut.args)] + vs[1:])) drhs = n(*([mut] + vs[1:])) eqs = [eq_atom(v,a) for (v,a) in zip(vs,lhs.args)[1:] if not isinstance(a,Variable)] if eqs: fmlas.append(Or(And(*eqs),equiv_ast(dlhs,drhs))) for destr in ivy_module.module.sort_destructors[mut.sort.name]: if destr != n: phs = sym_placeholders(destr) a1 = [nondet(*mut.args)] + phs[1:] a2 = [mut] + phs[1:] fmlas.append(eq_atom(destr(*a1),destr(*a2))) new_clauses = and_clauses(new_clauses,Clauses(fmlas)) return ([mut_n], new_clauses, false_clauses()) new_clauses = mk_assign_clauses(lhs,rhs) # print "assign new_clauses = {}".format(new_clauses) return ([n], new_clauses, false_clauses())
def remove_taut_eqs_clauses(clauses): return Clauses([f for f in clauses.fmlas if not is_tautology_equality(f)], clauses.defs)
def diff_frame(updated1, updated2, relations, op): if updated1 == None or updated2 == None: return Clauses([]) updated = list_diff(updated2, updated1) return frame(updated, relations, op)
def diff_frame(updated1, updated2, op, axioms): if updated1 == None or updated2 == None: return Clauses([]) updated = list_diff(updated2, updated1) defnd = set(df.defines() for df in axioms.defs) updated = [sym for sym in updated if sym not in defnd] return frame(updated, op)
def symbol_frame_cond(sym, sig): """ Return transition relation implying that sym remains unchanged """ return Clauses([], [frame_def(sym, new)])
def frame(updated, relations, op): """ Return a clause list constraining all updated symbols to keep their op values, for op = new,old """ return Clauses([], [frame_def(sym, op) for sym in updated])
def remove_duplicates_clauses(clauses): # tricky: store all z3 fmlas in list so not GC'd until all id's computed! z3fs = [(c, formula_to_z3(c)) for c in clauses.fmlas] return Clauses(list(ivy_utils.unique2((x, get_id(y)) for x, y in z3fs)), clauses.defs)
def clauses_model_to_diagram(clauses1, ignore=None, implied=None, model=None, axioms=None, weaken=True): """ Return a diagram of a model of clauses1 or None. The function "ignore", if provided, returns true for symbols that should be ignored in the diagram. """ print "clauses_model_to_diagram clauses1 = {}".format(clauses1) if axioms == None: axioms = true_clauses h = model_if_none(and_clauses(clauses1, axioms), implied, model) ignore = ignore if ignore != None else lambda x: False res = model_facts(h, (lambda x: False), clauses1, upclose=True) # why not pass axioms? print "clauses_model_to_diagram res = {}".format(res) # find representative elements # find representatives of universe elements reps = dict() for c in used_constants_clauses(clauses1): # print "constant: {}".format(c) mc = get_model_constant(h.model, ivy_logic.Constant(c)) # print "value: {}".format(mc) if mc.rep not in reps or reps[ mc.rep].rep.is_skolem() and not c.is_skolem(): reps[mc.rep] = ivy_logic.Constant(c) for s in h.sorts(): for e in h.sort_universe(s): if e.rep not in reps: reps[e.rep] = e.rep.skolem()() print "clauses_model_to_diagram reps = {}".format(reps) # filter out clauses using universe elements without reps # res = [cls for cls in res if all(c in reps for c in used_constants_clause(cls))] # replace universe elements with their reps print "clauses_model_to_diagram res = {}".format(res) res = substitute_constants_clauses(res, reps) # filter defined skolems # this caused a bug in the leader example. the generated diagram did not satisfy clauses1 res.fmlas = [ f for f in res.fmlas if not any((x.is_skolem() and x in clauses1.defidx) for x in used_symbols_ast(f)) ] print "clauses_model_to_diagram res = {}".format(res) uc = Clauses([[ ivy_logic._eq_lit(ivy_logic.Variable('X', c.get_sort()), reps[c.rep]) for c in h.sort_universe(s) ] for s in h.sorts()]) print "clauses_model_to_diagram uc = {}".format(uc) # uc = true_clauses() if weaken: res = unsat_core(res, and_clauses(uc, axioms), clauses1) # implied not used here print "clauses_model_to_diagram res = {}".format(res) # print "foo = {}".format(unsat_core(and_clauses(uc,axioms),true_clauses(),clauses1)) # filter out non-rep skolems repset = set(c.rep for e, c in reps.iteritems()) print "clauses_model_to_diagram repset = {}".format(repset) ign = lambda x, ignore=ignore: (ignore(x) and not x in repset) res = Clauses([ cl for cl in res.fmlas if not any(ign(c) for c in used_symbols_ast(cl)) ]) print "clauses_model_to_diagram res = {}".format(res) return res