def __init__(self, clauses, model, vocab, top_level=True): art.AnalysisGraph.__init__(self) self.clauses = clauses self.model = model self.vocab = vocab mod_clauses = islv.clauses_model_to_clauses(clauses, model=model, numerals=True) self.eqs = defaultdict(list) for fmla in mod_clauses.fmlas: if lg.is_eq(fmla): lhs, rhs = fmla.args if lg.is_app(lhs): self.eqs[lhs.rep].append(fmla) elif isinstance(fmla, lg.Not): app = fmla.args[0] if lg.is_app(app): self.eqs[app.rep].append(lg.Equals(app, lg.Or())) else: if lg.is_app(fmla): self.eqs[fmla.rep].append(lg.Equals(fmla, lg.And())) self.last_action = None self.sub = None self.returned = None self.top_level = top_level
def __init__(self, clauses, model, vocab, top_level=True): TraceBase.__init__(self) self.clauses = clauses self.model = model self.vocab = vocab self.top_level = top_level if clauses is not None: ignore = lambda s: islv.solver_name(s) == None mod_clauses = islv.clauses_model_to_clauses(clauses, model=model, numerals=True, ignore=ignore) self.eqs = defaultdict(list) for fmla in mod_clauses.fmlas: if lg.is_eq(fmla): lhs, rhs = fmla.args if lg.is_app(lhs): self.eqs[lhs.rep].append(fmla) elif isinstance(fmla, lg.Not): app = fmla.args[0] if lg.is_app(app): self.eqs[app.rep].append(lg.Equals(app, lg.Or())) else: if lg.is_app(fmla): self.eqs[fmla.rep].append(lg.Equals(fmla, lg.And()))
def match(pat,expr,mp): if il.is_variable(pat): if pat in mp: return expr == mp[pat] mp[pat] = expr return True if il.is_app(pat): return (il.is_app(expr) and pat.rep == expr.rep and all(match(x,y,mp) for x,y in zip(pat.args,expr.args))) if il.is_quantifier(pat): return False if type(pat) is not type(expr): return False if il.is_eq(expr): px,py = pat.args ex,ey = expr.args if px.sort != ex.sort: return False save = mp.copy() if match(px,ex,mp) and match(py,ey,mp): return True mp.clear() mp.update(save) return match(px,ey,mp) and match(py,ex,mp) return all(match(x,y,mp) for x,y in zip(pat.args,expr.args))
def __init__(self, clauses, model, vocab): # iu.dbg('clauses') self.clauses = clauses self.model = model self.vocab = vocab self.current = dict() mod_clauses = islv.clauses_model_to_clauses(clauses, model=model, numerals=True) # iu.dbg('mod_clauses') self.eqs = defaultdict(list) for fmla in mod_clauses.fmlas: if lg.is_eq(fmla): lhs, rhs = fmla.args if lg.is_app(lhs): self.eqs[lhs.rep].append(fmla) elif isinstance(fmla, lg.Not): app = fmla.args[0] if lg.is_app(app): self.eqs[app.rep].append(lg.Equals(app, lg.Or())) else: if lg.is_app(fmla): self.eqs[fmla.rep].append(lg.Equals(fmla, lg.And())) # for sym in vocab: # if not itr.is_new(sym) and not itr.is_skolem(sym): # self.show_sym(sym,sym) self.started = False self.renaming = dict() print print 'Trace follows...' print 80 * '*'
def heads_match(pat,inst,freesyms): """Returns true if the heads of two terms match. This means they have the same top-level operator and same number of arguments. Quantifiers do not match anything. A function symbol matches if it has the same name and if it agrees on the non-free sorts in its type. """ return (il.is_app(pat) and il.is_app(inst) and funcs_match(pat.rep,inst.rep,freesyms) and pat.rep not in freesyms or not il.is_app(pat) and not il.is_quantifier(pat) and type(pat) is type(inst) and len(pat.args) == len(inst.args))
def heads_match(pat,inst,freesyms): """Returns true if the heads of two terms match. This means they have the same top-level operator and same number of arguments. Quantifiers do not match anything. A function symbol matches if it has the same name and if it agrees on the non-free sorts in its type. """ return (il.is_app(pat) and il.is_app(inst) and funcs_match(pat.rep,inst.rep,freesyms) or not il.is_app(pat) and not il.is_quantifier(pat) and type(pat) is type(inst) and len(pat.args) == len(inst.args))
def map_fmla(fmla, strat_map): if il.is_binder(fmla): return map_fmla(fmla.body, strat_map) if il.is_variable(fmla): if fmla not in strat_map: res = UFNode() res.variables.add(fmla) strat_map[fmla] = res return strat_map[fmla] nodes = [map_fmla(f, strat_map) for f in fmla.args] if il.is_eq(fmla): unify(*nodes) if il.is_interpreted_sort(fmla.args[0].sort): unify(strat_map[(fmla.rep, 0)], nodes[0]) return None if il.is_ite(fmla): unify(*nodes[1:]) return nodes[1] if il.is_app(fmla): func = fmla.rep if func in symbols_over_universals or True: for idx, node in enumerate(nodes): if node is not None: unify(strat_map[(func, idx)], node) return strat_map[func] return None
def match(pat, inst, freesyms, constants): """ Match an instance to a pattern. A match is an assignment sigma to freesyms such that sigma pat =_alpha inst. """ if il.is_quantifier(pat): return match_quants(pat, inst, freesyms, constants) if heads_match(pat, inst, freesyms): matches = [ match(x, y, freesyms, constants) for x, y in zip(pat.args, inst.args) ] matches.extend([ match_sort(x, y, freesyms) for x, y in zip(term_sorts(pat), term_sorts(inst)) ]) if il.is_variable(pat): matches.append({pat: inst}) res = merge_matches(*matches) return res elif il.is_app(pat) and pat.rep in freesyms: B = extract_terms(inst, pat.args) if all(v in constants for v in lu.variables_ast(B)): matches = [{pat.rep: B}] matches.extend([ match_sort(x, y, freesyms) for x, y in zip(term_sorts(pat), lambda_sorts(B)) ]) res = merge_matches(*matches) return res
def compile_match(proof, prob, decl): """ Compiles match in a proof. Only the symbols in freesyms may be used in the match.""" schema = prob.schema matches = compile_match_list(proof, schema, decl) matches = [ compile_one_match(m.lhs(), m.rhs(), prob.freesyms, prob.constants) for m in matches ] res = merge_matches(*matches) return res freesyms = prob.freesyms res = dict() for m in proof.match(): if il.is_app(m.lhs()): res[m.defines()] = il.Lambda(m.lhs().args, m.rhs()) else: res[m.lhs()] = m.rhs() # iu.dbg('freesyms') # freesyms = apply_match_freesyms(res,freesyms) # iu.dbg('freesyms') # for sym in res: # if sym not in freesyms: # raise ProofError(proof,'{} is not a premise of schema {}'.format(repr(sym),schemaname)) return res
def map_fmla(fmla,strat_map): if il.is_binder(fmla): return map_fmla(fmla.body,strat_map) if il.is_variable(fmla): if fmla not in strat_map: res = UFNode() res.variables.add(fmla) strat_map[fmla] = res return strat_map[fmla] nodes = [map_fmla(f,strat_map) for f in fmla.args] if il.is_eq(fmla): unify(*nodes) if il.is_interpreted_sort(fmla.args[0].sort): unify(strat_map[(fmla.rep,0)],nodes[0]) return None if il.is_ite(fmla): unify(*nodes[1:]) return nodes[1] if il.is_app(fmla): func = fmla.rep if func in symbols_over_universals or True: for idx,node in enumerate(nodes): if node is not None: unify(strat_map[(func,idx)],node) return strat_map[func] return None
def get_strip_binding(ast,strip_map,strip_binding): [get_strip_binding(arg,strip_map,strip_binding) for arg in ast.args] if ivy_logic.is_app(ast): name = ast.rep.name strip_params = strip_map_lookup(name,strip_map) if not(len(ast.args) >= len(strip_params)): raise iu.IvyError(action,"cannot strip isolate parameters from {}",name) for sp,ap in zip(strip_params,ast.args): if ap in strip_binding and strip_binding[ap] != sp: raise iu.IvyError(action,"cannot strip parameter {} from {}",ap,name) strip_binding[ap] = sp
def get_trigger(expr,vs): if il.is_quantifier(expr) or il.is_variable(expr): return None for a in expr.args: r = get_trigger(a,vs) if r is not None: return r if il.is_app(expr) or il.is_eq(expr): evs = ilu.used_variables_ast(expr) if all(v in evs for v in vs): return expr
def apply_match_rec(match,fmla,env): args = [apply_match_rec(match,f,env) for f in fmla.args] if il.is_app(fmla): if fmla.rep in match: func = match[fmla.rep] return func(*args) return apply_match_func(match,fmla.rep)(*args) if il.is_variable(fmla) and fmla in match: return match[fmla] if il.is_binder(fmla): with il.BindSymbols(env,fmla.variables): fmla = fmla.clone_binder([apply_match_rec(match,v,env) for v in fmla.variables],args[0]) return fmla return fmla.clone(args)
def get_strip_binding(ast, strip_map, strip_binding): [get_strip_binding(arg, strip_map, strip_binding) for arg in ast.args] name = ast.rep.name if ivy_logic.is_app(ast) else ast.rep if isinstance( ast, ivy_ast.Atom) else None if name: strip_params = strip_map_lookup(name, strip_map) if not (len(ast.args) >= len(strip_params)): raise iu.IvyError( ast, "cannot strip isolate parameters from {}".format( presentable(name))) for sp, ap in zip(strip_params, ast.args): if ap in strip_binding and strip_binding[ap] != sp: raise iu.IvyError(action, "cannot strip parameter {} from {}", presentable(ap), presentable(name)) strip_binding[ap] = sp
def apply_match(match,fmla): """ apply a match to a formula. In effect, substitute all symbols in the match with the corresponding lambda terms and apply beta reduction """ args = [apply_match(match,f) for f in fmla.args] if il.is_app(fmla): if fmla.rep in match: func = match[fmla.rep] return func(*args) return apply_match_func(match,fmla.rep)(*args) if il.is_variable(fmla) and fmla in match: return match[fmla] return fmla.clone(args)
def apply_match(match, fmla): """ apply a match to a formula. In effect, substitute all symbols in the match with the corresponding lambda terms and apply beta reduction """ args = [apply_match(match, f) for f in fmla.args] if il.is_app(fmla): if fmla.rep in match: func = match[fmla.rep] return func(*args) return apply_match_func(match, fmla.rep)(*args) if il.is_variable(fmla) and fmla in match: return match[fmla] return fmla.clone(args)
def match(pat,inst,freesyms,constants): """ Match an instance to a pattern. A match is an assignment sigma to freesyms such that sigma pat =_alpha inst. """ if il.is_quantifier(pat): return match_quants(pat,inst,freesyms,constants) if heads_match(pat,inst,freesyms): matches = [match(x,y,freesyms,constants) for x,y in zip(pat.args,inst.args)] matches.extend([match_sort(x,y,freesyms) for x,y in zip(term_sorts(pat),term_sorts(inst))]) return merge_matches(*matches) if il.is_app(pat) and pat.rep in freesyms: B = extract_terms(inst,pat.args) if all(v in constants for v in lu.variables_ast(B)): return {pat.rep:B}
def apply_match(match,fmla): """ apply a match to a formula. In effect, substitute all symbols in the match with the corresponding lambda terms and apply beta reduction """ args = [apply_match(match,f) for f in fmla.args] if il.is_app(fmla): if fmla.rep in match: func = match[fmla.rep] return func(*args) elif il.is_binder(fmla): vs = [apply_match(match,v) for v in fmla.variables] return fmla.clone_binder(vs,apply_match(match,fmla.body)) elif il.is_variable(fmla): return il.Variable(fmla.name,match.get(fmla.sort,fmla.sort)) return fmla.clone(args)
def recur(expr): if il.is_app(expr): sym = expr.rep assert il.is_boolean_sort(sym.sort),"non-boolean sym in aiger output: {}".format(sym) try: return self.lit(sym) except KeyError: assert getdef is not None, "no definition for {} in aiger output".format(sym) return getdef(sym) else: args = map(recur,expr.args) if isinstance(expr,il.And): return self.andl(*args) if isinstance(expr,il.Or): return self.orl(*args) if isinstance(expr,il.Not): return self.notl(*args) assert False,"non-boolean op in aiger output: {}".format(type(expr))
def strip_action(ast, strip_map, strip_binding): if isinstance(ast, ia.CallAction): name = canon_act(ast.args[0].rep) args = [ strip_action(arg, strip_map, strip_binding) for arg in ast.args[0].args ] strip_params = get_strip_params(name, ast.args[0].args, strip_map, strip_binding, ast) call = ast.args[0].clone(args[len(strip_params):]) return ast.clone([call] + [ strip_action(arg, strip_map, strip_binding) for arg in ast.args[1:] ]) if isinstance(ast, ia.AssignAction): if ast.args[0].rep.name in ivy_logic.sig.symbols: lhs_params = strip_map_lookup(ast.args[0].rep.name, strip_map) if len(lhs_params) != num_isolate_params: raise iu.IvyError(ast, "assignment may be interfering") if (ivy_logic.is_constant(ast) or ivy_logic.is_variable(ast)) and ast in strip_binding: sname = strip_binding[ast] if sname not in ivy_logic.sig.symbols: ivy_logic.add_symbol(sname, ast.sort) strip_added_symbols.append(ivy_logic.Symbol(sname, ast.sort)) return ivy_logic.Symbol(sname, ast.sort) args = [strip_action(arg, strip_map, strip_binding) for arg in ast.args] if ivy_logic.is_app(ast): name = ast.rep.name strip_params = get_strip_params(name, ast.args, strip_map, strip_binding, ast) if strip_params: new_sort = strip_sort(ast.rep.sort, strip_params) new_args = args[len(strip_params):] new_symbol = ivy_logic.Symbol(name, new_sort) return new_symbol(*new_args) if isinstance(ast, ivy_ast.Atom): name = ast.rep strip_params = get_strip_params(name, ast.args, strip_map, strip_binding, ast) if strip_params: new_args = args[len(strip_params):] return ast.clone(new_args) return ast.clone(args)
def compile_match(proof, prob, schemaname): """ Compiles match in a proof. Only the symbols in freesyms may be used in the match.""" match = proof.match() freesyms = prob.freesyms res = dict() for m in proof.match(): if il.is_app(m.lhs()): res[m.defines()] = il.Lambda(m.lhs().args, m.rhs()) else: res[m.lhs()] = m.rhs() # iu.dbg('freesyms') # freesyms = apply_match_freesyms(res,freesyms) # iu.dbg('freesyms') # for sym in res: # if sym not in freesyms: # raise ProofError(proof,'{} is not a premise of schema {}'.format(repr(sym),schemaname)) return res
def compile_match(proof,prob,schemaname): """ Compiles match in a proof. Only the symbols in freesyms may be used in the match.""" match = proof.match() freesyms = prob.freesyms res = dict() for m in proof.match(): if il.is_app(m.lhs()): res[m.defines()] = il.Lambda(m.lhs().args,m.rhs()) else: res[m.lhs()] = m.rhs() # iu.dbg('freesyms') # freesyms = apply_match_freesyms(res,freesyms) # iu.dbg('freesyms') # for sym in res: # if sym not in freesyms: # raise ProofError(proof,'{} is not a premise of schema {}'.format(repr(sym),schemaname)) return res
def apply_match_alt(match,fmla): """ apply a match to a formula. In effect, substitute all symbols in the match with the corresponding lambda terms and apply beta reduction """ args = [apply_match_alt(match,f) for f in fmla.args] if il.is_app(fmla): func = apply_match_func(match,fmla.rep) if func in match: func = match[func] return func(*args) return func(*args) if il.is_variable(fmla): fmla = il.Variable(fmla.name,match.get(fmla.sort,fmla.sort)) fmla = match.get(fmla,fmla) return fmla return fmla.clone(args)
def recur(expr): if isinstance(expr,il.Ite): cond = recur(expr.args[0]) thenterm = recur(expr.args[1]) elseterm = recur(expr.args[2]) res = [self.sub.ite(cond[0],x,y) for x,y in zip(thenterm,elseterm)] elif il.is_app(expr): sym = expr.rep if sym in il.sig.constructors: m = sym.sort.defines().index(sym.name) res = self.binenc(m,ceillog2(len(sym.sort.defines()))) elif sym.is_numeral() and il.is_interpreted_sort(sym.sort): n = get_encoding_bits(sym.sort) res = self.binenc(int(sym.name),n) elif sym.name in self.ops and il.is_interpreted_sort(sym.sort.dom[0]): args = map(recur,expr.args) res = self.ops[sym.name](expr.args[0].sort,*args) else: assert len(expr.args) == 0 try: res = self.lit(sym) except KeyError: assert getdef is not None, "no definition for {} in aiger output".format(sym) res = getdef(sym) else: args = map(recur,expr.args) if isinstance(expr,il.And): res = self.andl(*args) elif isinstance(expr,il.Or): res = self.orl(*args) elif isinstance(expr,il.Not): res = self.notl(*args) elif isinstance(expr,il.Implies): res = self.implies(*args) elif isinstance(expr,il.Iff): res = self.iff(*args) elif il.is_eq(expr): res = self.encode_equality(expr.args[0].sort,*args) else: assert False,"unimplemented op in aiger output: {}".format(type(expr)) # iu.dbg('expr') # iu.dbg('res') return res
def apply_match_alt_rec(match,fmla,env): args = [apply_match_alt_rec(match,f,env) for f in fmla.args] if il.is_app(fmla): if fmla.rep in match: return apply_fun(match_get(match,fmla.rep,env),args) func = apply_match_func(match,fmla.rep) func = match_get(match,func,env,func) return func(*args) if il.is_variable(fmla): if fmla in match: return match_get(match,fmla,env) fmla = il.Variable(fmla.name,apply_match_sort(match,fmla.sort)) fmla = match_get(match,fmla,env,fmla) return fmla if il.is_binder(fmla): with il.BindSymbols(env,fmla.variables): fmla = fmla.clone_binder([apply_match_alt_rec(match,v,env) for v in fmla.variables],args[0]) return fmla return fmla.clone(args)
def apply_match_alt(match, fmla): """ apply a match to a formula. In effect, substitute all symbols in the match with the corresponding lambda terms and apply beta reduction """ args = [apply_match_alt(match, f) for f in fmla.args] if il.is_app(fmla): func = apply_match_func(match, fmla.rep) if func in match: func = match[func] return func(*args) return func(*args) if il.is_variable(fmla): fmla = il.Variable(fmla.name, match.get(fmla.sort, fmla.sort)) fmla = match.get(fmla, fmla) return fmla return fmla.clone(args)
def term_ord(x,y): t1,t2 = str(type(x)),str(type(y)) if t1 < t2: return -1 if t1 > t2: return 1 if il.is_app(x): if x.rep.name < y.rep.name: return -1 if x.rep.name > y.rep.name: return 1 l1,l2 = len(x.args),len(y.args) if l1 < l2: return -1 if l1 > l2: return 1 for x1,y1 in zip(x.args,y.args): res = term_ord(x1,y1) if res != 0: return res return 0
def strip_action(ast,strip_map,strip_binding): if isinstance(ast,ia.CallAction): name = ast.args[0].rep args = [strip_action(arg,strip_map,strip_binding) for arg in ast.args[0].args] strip_params = get_strip_params(name,ast.args[0].args,strip_map,strip_binding,ast) call = ast.args[0].clone(args[len(strip_params):]) return ast.clone([call]+[strip_action(arg,strip_map,strip_binding) for arg in ast.args[1:]]) if (ivy_logic.is_constant(ast) or ivy_logic.is_variable(ast)) and ast in strip_binding: sname = strip_binding[ast] if sname not in ivy_logic.sig.symbols: ivy_logic.add_symbol(sname,ast.sort) return ivy_logic.Symbol(sname,ast.sort) args = [strip_action(arg,strip_map,strip_binding) for arg in ast.args] if ivy_logic.is_app(ast): name = ast.rep.name strip_params = get_strip_params(name,ast.args,strip_map,strip_binding,ast) if strip_params: new_sort = strip_sort(ast.rep.sort,strip_params) new_args = args[len(strip_params):] new_symbol = ivy_logic.Symbol(name,new_sort) return new_symbol(*new_args) return ast.clone(args)
def unroll(self, card, body=None): cond = self.args[0] while isinstance(cond, And) and len(cond.args) > 0: cond = cond.args[0] if is_app(cond) and cond.rep.name in ['<', '>', '<=', '>=']: idx_sort = cond.args[0].sort elif isinstance(cond, Not) and is_eq(cond.args[0]): idx_sort = cond.args[0].args[0].sort else: raise IvyError(self, 'cannot determine an index sort for loop') cardsort = card(idx_sort) if cardsort is None: raise IvyError( self, 'cannot determine an iteration bound for loop over {}'.format( idx_sort)) res = AssumeAction(Not(self.args[0])) for idx in range(cardsort): res = IfAction(self.args[0], Sequence(body or self.args[1], res)) if hasattr(self, 'formal_params'): res.formal_params = self.formal_params if hasattr(self, 'formal_returns'): res.formal_returns = self.formal_returns return res
def term_sorts(term): """ Returns a list of the domain and range sorts of the head function of a term, if any """ return func_sorts(term.rep) if il.is_app(term) else []
def map_fmla(lineno, fmla, pol): """ Add all of the subterms of `fmla` to the stratification graph. """ global universally_quantified_variables global macro_var_map global macro_dep_map global macro_map global macro_val_map global strat_map global arcs if il.is_binder(fmla): return map_fmla(lineno, fmla.body, pol) if il.is_variable(fmla): if fmla in universally_quantified_variables: if fmla not in strat_map: res = UFNode() strat_map[fmla] = res return strat_map[fmla], set() node, vs = macro_var_map.get(fmla, None), macro_dep_map.get(fmla, set()) return node, vs reses = [ map_fmla(lineno, f, il.polar(fmla, pos, pol)) for pos, f in enumerate(fmla.args) ] nodes, uvs = iu.unzip_pairs(reses) all_uvs = iu.union_of_list(uvs) all_uvs.update(n for n in nodes if n is not None) if il.is_eq(fmla): if not il.is_interpreted_sort(fmla.args[0].sort): S_sigma = strat_map[il.Symbol('=', fmla.args[0])] for x, uv in zip(nodes, uvs): if x is not None: unify(x, S_sigma) arcs.extend((v, S_sigma, fmla, lineno) for v in uv) else: check_interpreted(fmla, nodes, uvs, lineno, pol) return None, all_uvs if il.is_ite(fmla): # S_sigma = strat_map[il.Symbol('=',fmla.args[1])] # for x,uv in zip(nodes[1:],uvs[1:]): # if x is not None: # unify(x,S_sigma) # arcs.extend((v,S_sigma,fmla,lineno) for v in uv) # TODO: treat ite as pseudo-macro: does this work? if nodes[1] and nodes[2]: unify(*nodes[1:]) return nodes[1] or nodes[2], all_uvs if il.is_app(fmla): func = fmla.rep if not il.is_interpreted_symbol(func): if func in macro_value_map: return macro_value_map[func] if func in macro_map: defn, lf = macro_map[func] res = map_fmla(lf.lineno, defn.rhs(), None) macro_value_map[func] = res return res for idx, node in enumerate(nodes): anode = strat_map[(func, idx)] if node is not None: unify(anode, node) arcs.extend((v, anode, fmla, lineno) for v in uvs[idx]) else: check_interpreted(fmla, nodes, uvs, lineno, pol) return None, all_uvs return None, all_uvs
def term_sorts(term): """ Returns a list of the domain and range sorts of the head function of a term, if any """ return func_sorts(term.rep) if il.is_app(term) else []