def subactions(self) : if isinstance(self.args[0],ivy_ast.Some): ps = list(self.args[0].params()) fmla = self.args[0].fmla() vs = [Variable('V{}'.format(idx),x.sort) for idx,x in enumerate(ps)] subst = dict((c,v) for c,v in zip(ps,vs)) sfmla = substitute_constants_ast(fmla,subst) if isinstance(self.args[0],ivy_ast.SomeMinMax): idx = self.args[0].index() if idx not in ps: ltsym = Symbol('<',RelationSort([idx.sort,idx.sort])) operator = lambda x,y: Not(ltsym(x,y)) ivar = substitute_constants_ast(idx,subst) comp = operator(ivar,idx) if isinstance(self.args[0],ivy_ast.SomeMin) else operator(idx,ivar) fmla = And(fmla,Implies(sfmla,comp)) else : leqsym = Symbol('<=',RelationSort([idx.sort,idx.sort])) operator = lambda x,y: And(leqsym(x,y),Not(Equals(x,y))) ivar = next(v for p,v in zip(ps,vs) if p == idx) comp = operator(ivar,idx) if isinstance(self.args[0],ivy_ast.SomeMin) else operator(idx,ivar) fmla = And(fmla,Not(And(sfmla,comp))) if_part = LocalAction(*(ps+[Sequence(AssumeAction(fmla),self.args[1])])) else_action = self.args[2] if len(self.args) >= 3 else Sequence() else_part = Sequence(AssumeAction(Not(sfmla)),else_action) # iu.dbg('if_part') # iu.dbg('else_part') else: if not is_boolean(self.args[0]): raise IvyError(self,'condition must be boolean') if_part = Sequence(AssumeAction(self.args[0]),self.args[1]) else_action = self.args[2] if len(self.args) >= 3 else Sequence() else_part = Sequence(AssumeAction(dual_formula(self.args[0])),else_action) return if_part,else_part
def decompose(self, pre, post, fail=False): v = self.get_callee() if not isinstance(v, Action): return [] actual_params = self.args[0].args actual_returns = self.args[1:] vocab = list(symbols_asts(actual_params + actual_returns)) formals = v.formal_params + v.formal_returns premap, pre = hide_state_map(formals, pre) postmap, post = hide_state_map(formals, post) actual_params = [rename_ast(p, premap) for p in actual_params] actual_returns = [rename_ast(p, postmap) for p in actual_returns] pre = constrain_state( pre, And(* [Equals(x, y) for x, y in zip(actual_params, v.formal_params)])) if not fail: post = constrain_state( post, And(*[ Equals(x, y) for x, y in zip(actual_returns, v.formal_returns) ])) ren = dict((x, x.prefix('__hide:')) for x in actual_returns) post = (post[0], rename_clauses(post[1], ren), post[2]) callee = v.clone(v.args) # drop the formals res = [(pre, [callee], post)] print "decompose call:" print "pre = {}".format(pre) print "callee = {}".format(callee) print "post = {}".format(post) return res
def reset(self): concept_domain = initial_concept_domain(self.sorts) self.new_relations = [] self.concept_session = cis.ConceptInteractiveSession(concept_domain, And(), And(), cache={}, recompute=True) if hasattr(self.parent_state, 'universe'): for n in self.nodes: if n.sort in self.parent_state.universe: self.splatter(n, self.parent_state.universe[n.sort])
def action_update(self,domain,pvars): lhs = self.args[0] n = lhs.rep new_n = new(n) args = lhs.args vs = [Variable("X%d" % i,s) for i,s in enumerate(n.sort.dom)] eqs = [eq_atom(v,a) for (v,a) in zip(vs,args) if not isinstance(a,Variable)] if is_atom(lhs): clauses = And(*([Or(Not(Atom(new_n,vs)),Atom(n,vs),eq) for eq in eqs] + [Or(Atom(new_n,vs),Not(Atom(n,vs)),eq) for eq in eqs])) elif is_individual_ast(lhs.rep): clauses = And(*[Or(eq_atom(type(lhs)(new_n,vs),type(lhs)(n,vs)),eq) for eq in eqs]) else: # TODO: ??? clauses = And() clauses = formula_to_clauses(clauses) return ([n], clauses, false_clauses())
def implies(s1, s2): assert isinstance(s1, SemValue) and type(s1) is type(s2) op = s1.op axioms = im.background_theory() u1, c1, p1 = s1.comps u2, c2, p2 = s2.comps if u1 == None and u2 != None: return False # print "c1: {}".format(c1) # print "axioms: {}".format(axioms) # print "df: {}".format(diff_frame(u1,u2,relations,op)) c1 = and_clauses(c1, axioms, diff_frame(u1, u2, op)) if isinstance(c2, Clauses): if not c2.is_universal_first_order( ) or not p2.is_universal_first_order(): return False c2 = and_clauses(c2, diff_frame(u2, u1, op)) return clauses_imply(p1, p2) and clauses_imply(c1, c2) else: if not is_prenex_universal(c2) or not is_prenex_universal(p2): return False c2 = And(c2, clauses_to_formula(diff_frame(u2, u1, op))) return clauses_imply_formula_cex(p1, p2) and clauses_imply_formula_cex( c1, c2)
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 destr_asgn_val(lhs, fmlas): mut = lhs.args[0] rest = list(lhs.args[1:]) mut_n = mut.rep if mut_n.name in ivy_module.module.destructor_sorts: lval, new_clauses, mutated = destr_asgn_val(mut, fmlas) else: nondet = mut_n.suffix("_nd").skolem() new_clauses = (mk_assign_clauses(mut_n, nondet(*sym_placeholders(mut_n)))) lval = nondet(*mut.args) mutated = mut_n n = lhs.rep vs = sym_placeholders(n) dlhs = n(*([lval] + 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 = [lval] + phs[1:] a2 = [mut] + phs[1:] fmlas.append(eq_atom(destr(*a1), destr(*a2))) return lhs.rep(*([lval] + rest)), new_clauses, mutated
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 action_update(self,domain,pvars): lit = self.args[0] n = lit.atom.relname new_n = new(n) args = lit.atom.args vs = sym_placeholders(n) eqs = [Atom(equals,[v,a]) for (v,a) in zip(vs,args) if not isinstance(a,Variable)] new_clauses = And(*([Or(sign(lit.polarity,Atom(new_n,vs)),sign(1-lit.polarity,Atom(n,vs))), sign(lit.polarity,Atom(new_n,args))] + [Or(*([sign(0,Atom(new_n,vs)),sign(1,Atom(n,vs))] + [eq])) for eq in eqs] + [Or(*([sign(1,Atom(new_n,vs)),sign(0,Atom(n,vs))] + [eq])) for eq in eqs])) new_clauses = formula_to_clauses(new_clauses) return ([n], new_clauses, false_clauses())
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 expand(self, domain, pvars): modset, pre, post = self.args[1].int_update( domain, pvars) # TODO:cheaper way to get modset asserts = self.args[2:] assumes = [a.assert_to_assume() for a in asserts] havocs = [HavocAction(sym) for sym in modset] res = Sequence(*(asserts + havocs + assumes + [ ChoiceAction( Sequence(), Sequence(*([AssumeAction(self.args[0]), self.args[1]] + asserts + [AssumeAction(And())]))), AssumeAction(Not(self.args[0])) ])) return res
def implies(s1,s2,axioms,relations,op): u1,c1,p1 = s1 u2,c2,p2 = s2 if u1 == None and u2 != None: return False # print "c1: {}".format(c1) # print "axioms: {}".format(axioms) # print "df: {}".format(diff_frame(u1,u2,relations,op)) c1 = and_clauses(c1,axioms,diff_frame(u1,u2,relations,op)) if isinstance(c2,Clauses): if not c2.is_universal_first_order() or not p2.is_universal_first_order(): return False c2 = and_clauses(c2,diff_frame(u2,u1,relations,op)) return clauses_imply(p1,p2) and clauses_imply(c1,c2) else: if not is_prenex_universal(c2) or not is_prenex_universal(p2): return False c2 = And(c2,clauses_to_formula(diff_frame(u2,u1,relations,op))) return clauses_imply_formula_cex(p1,p2) and clauses_imply_formula_cex(c1,c2)
def entry(ensures = And()): return RME(And(),[],ensures)
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 equiv_ast(ast1,ast2): if is_individual_ast(ast1): # ast2 had better be the same! return eq_atom(ast1,ast2) return And(Or(ast1,Not(ast2)),Or(Not(ast1),ast2))