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_problem(schema, decl): """ Creating a matching problem from a schema and a declaration """ vocab = goal_vocab(schema) freesyms = set(vocab.symbols + vocab.sorts + vocab.variables) constants = set(v for v in goal_free(decl) if il.is_variable(v)) return MatchProblem(schema, goal_conc(schema), goal_conc(decl), freesyms, constants)
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,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 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 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 create_macro_maps(assumes, asserts, macros): global universally_quantified_variables global macro_var_map global macro_dep_map global macro_map global macro_value_map global strat_map macro_map = dict() for df, lf in macros: macro_map[df.defines()] = (df, lf) macro_dep_map = defaultdict(set) macro_var_map = dict() macro_value_map = dict() def var_map_add(w, vn): if w in macro_var_map: unify(macro_var_map[w], vn) else: macro_var_map[w] = vn for fmla, _ in assumes + asserts + list(reversed(macros)): for app in ilu.apps_ast(fmla): if app.rep in macro_map: mvs = macro_map[app.rep][0].args[0].args for v, w in zip(app.args, mvs): if il.is_variable(w): if il.is_variable(v): if v in universally_quantified_variables: var_map_add(w, strat_map[v]) if v in macro_var_map: var_map_add(w, macro_var_map[v]) if v in macro_dep_map: macro_dep_map[w].update(macro_dep_map[v]) else: for u in ilu.used_variables_ast(v): if u in universally_quantified_variables: macro_dep_map[w].add(strat_map[u]) if u in macro_var_map: macro_dep_map[w].add(macro_var_map[u]) if u in macro_dep_map: macro_dep_map[w].update(macro_var_map[u])
def avoid_capture_problem(prob, match): """ Rename a match problem to avoid capture when applying a match""" mrv = match_rhs_vars(match) matchnames = set(x.name for x in match_rhs_vars(match)) used = set(matchnames) used.update(x.name for x in goal_defns(prob.schema)) used.update(v.name for v in goal_free(prob.schema) if il.is_variable(v)) rn = iu.UniqueRenamer(used=used) cmatch = dict((v, v.rename(rn)) for v in prob.freesyms if v.name in matchnames and v not in match) rename_problem(cmatch, prob)
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 compile_one_match(lhs,rhs,freesyms,constants): if il.is_variable(lhs): return fo_match(lhs,rhs,freesyms,constants) rhsvs = dict((v.name,v) for v in lu.used_variables_ast(rhs)) vmatches = [{v.sort:rhsvs[v.name].sort} for v in lu.used_variables_ast(lhs) if v.name in rhsvs and v.sort in freesyms] vmatch = merge_matches(*vmatches) if vmatch is None: return None lhs = apply_match_alt(vmatch,lhs) newfreesyms = apply_match_freesyms(vmatch,freesyms) somatch = match(lhs,rhs,newfreesyms,constants) somatch = compose_matches(freesyms,vmatch,somatch,vmatch) fmatch = merge_matches(vmatch,somatch) return fmatch
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 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 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 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 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 fo_match(pat,inst,freesyms,constants): """ Compute a partial first-order match. Matches free FO variables to ground terms, but ignores variable occurrences under free second-order symbols. """ if il.is_variable(pat): if pat in freesyms and all(x in constants for x in lu.variables_ast(inst)): res = {pat:inst} if pat.sort == inst.sort: return res if pat.sort in freesyms: res[pat.sort] = inst.sort return res if il.is_quantifier(pat) and il.is_quantifier(inst): with RemoveSymbols(freesyms,pat.variables): return fo_match(pat.body,inst.body,freesyms,constants) if heads_match(pat,inst,freesyms): matches = [fo_match(x,y,freesyms,constants) for x,y in zip(pat.args,inst.args)] res = merge_matches(*matches) return res return dict()
def fo_match(pat,inst,freesyms,constants): """ Compute a partial first-order match. Matches free FO variables to ground terms, but ignores variable occurrences under free second-order symbols. """ if il.is_variable(pat): if pat in freesyms and all(x in constants for x in lu.variables_ast(inst)): res = {pat:inst} if pat.sort in freesyms: res[pat.sort] = inst.sort return res if pat.sort == inst.sort: return res if il.is_quantifier(pat) and il.is_quantifier(inst): with RemoveSymbols(freesyms,pat.variables): return fo_match(pat.body,inst.body,freesyms,constants) if heads_match(pat,inst,freesyms): matches = [fo_match(x,y,freesyms,constants) for x,y in zip(pat.args,inst.args)] res = merge_matches(*matches) return res return dict()
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 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 apply_match_sym(match,sym): if il.is_variable(sym): return il.Variable(sym.name,match.get(sym.sort,sym.sort)) return match.get(sym,sym) if isinstance(sym,il.UninterpretedSort) else apply_match_func(match,sym)
def apply_match_sym(match, sym): if il.is_variable(sym): return il.Variable(sym.name, match.get(sym.sort, sym.sort)) return match.get(sym, sym) if isinstance( sym, il.UninterpretedSort) else apply_match_func(match, sym)
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 [term.sort] if il.is_variable(term) else []