def find_case_split (p, head, restrs, hyps, tags = None): # are there multiple paths to the loop head 'head' and can we # restrict to one of them? preds = set () frontier = list (set ([n2 for n in p.loop_body (head) for n2 in p.preds[n] if p.loop_id (n2) != head])) while frontier: n2 = frontier.pop () if n2 in preds: continue preds.add (n2) frontier.extend (p.preds[n2]) divs = [n2 for n2 in preds if len (set ([n3 for n3 in p.nodes[n2].get_conts () if n3 in preds or n3 == head])) > 1 if n2 not in p.loop_data] trace ('find_case_split: possible divs %s.' % divs) rep = mk_graph_slice (p) err_restrs = restr_others (p, restrs, 2) if tags: l_tag, r_tag = tags else: l_tag, r_tag = p.pairing.tags hvis_restrs = tuple ([(head, rep_graph.vc_num (0))]) + restrs lhyps = hyps + [rep_graph.pc_false_hyp ((('Err', err_restrs), r_tag)), rep_graph.pc_true_hyp (((head, hvis_restrs), p.node_tags[head][0]))] # for this to be a usable case split, both paths must be possible for div in divs: dhyps = lhyps + [rep_graph.pc_true_hyp (((div, restrs), p.node_tags[div][0]))] assert p.nodes[div].kind == 'Cond' (_, env) = rep.get_node_pc_env ((div, restrs)) c = to_smt_expr (p.nodes[div].cond, env, rep.solv) if (rep.test_hyp_whyps (c, dhyps) or rep.test_hyp_whyps (mk_not (c), dhyps)): continue trace ("attempting case split at %d" % div) sides = [n for n in p.nodes[div].get_conts () if n not in p.loop_data if p.preds[n] == [div]] if not sides: trace ("skipping case split, no notable succ") n = sides[0] return ('CaseSplit', (n, p.node_tags[n][0])) trace ('find_case_split: no case splits possible') return (None, ())
def find_split (rep, head, restrs, hyps, i_opts, j_opts, unfold_limit = None, tags = None): knowledge = setup_split_search (rep, head, restrs, hyps, i_opts, j_opts, unfold_limit = unfold_limit, tags = tags) res = split_search (head, knowledge) if res[0]: return res (models, facts, n_vcs) = most_common_path (head, knowledge) if not n_vcs: return res [tag, _] = knowledge.tags knowledge = setup_split_search (rep, head, restrs, hyps + [rep_graph.pc_true_hyp ((n_vc, tag)) for n_vc in n_vcs], i_opts, j_opts, unfold_limit, tags) knowledge.facts.update (facts) for m in models: knowledge.add_model (m) res = split_search (head, knowledge) if res[0] == None: return res (_, split) = res checks = check.split_init_step_checks (rep.p, restrs, hyps, split) return derive_case_split (rep, n_vcs, checks)
def derive_case_split (rep, n_vcs, checks): last_derive_case_split[0] = (rep.p, n_vcs, checks) # remove duplicate pcs n_vcs_uniq = dict ([(rep.get_pc (n_vc), (i, n_vc)) for (i, n_vc) in enumerate (n_vcs)]).values () n_vcs = [n_vc for (i, n_vc) in sorted (n_vcs_uniq)] assert n_vcs tag = rep.p.node_tags[n_vcs[0][0]][0] keep_n_vcs = [] test_n_vcs = n_vcs mk_thyps = lambda n_vcs: [rep_graph.pc_true_hyp ((n_vc, tag)) for n_vc in n_vcs] while len (test_n_vcs) > 1: i = len (test_n_vcs) / 2 test_in = test_n_vcs[:i] test_out = test_n_vcs[i:] checks2 = [(hyps + mk_thyps (test_in + keep_n_vcs), hyp, nm) for (hyps, hyp, nm) in checks] (verdict, _) = check.test_hyp_group (rep, checks2) if verdict: # forget n_vcs that were tested out test_n_vcs = test_in else: # focus on n_vcs that were tested out test_n_vcs = test_out keep_n_vcs.extend (test_in) [(n, vc)] = test_n_vcs return ('CaseSplit', ((n, tag), [n]))
def proof_subproblems (p, kind, args, restrs, hyps, path): tags = p.pairing.tags if kind == 'Leaf': return [] elif kind == 'Restr': restr = get_proof_restr (args[0], args[1]) hyps = hyps + [restr_trivial_hyp (p, args[0], args[1], restrs)] return [((restr,) + restrs, hyps, '%s (%d limited)' % (path, args[0]))] elif kind == 'Split': split = args return [(restrs, hyps + split_no_loop_hyps (tags, split, restrs), '%d init case in %s' % (split[0][0], path)), (restrs, hyps + split_loop_hyps (tags, split, restrs, exit = True), '%d loop case in %s' % (split[0][0], path))] elif kind == 'CaseSplit': (point, tag) = args visit = ((point, restrs), tag) true_hyps = hyps + [pc_true_hyp (visit)] false_hyps = hyps + [pc_false_hyp (visit)] return [(restrs, true_hyps, 'true case (%d visited) in %s' % (point, path)), (restrs, false_hyps, 'false case (%d not visited) in %s' % (point, path))] else: assert not 'proof node kind understood', proof.kind
def proof_subproblems(p, kind, args, restrs, hyps, path): tags = p.pairing.tags if kind == 'Leaf': return [] elif kind == 'Restr': restr = get_proof_restr(args[0], args[1]) hyps = hyps + [restr_trivial_hyp(p, args[0], args[1], restrs)] return [((restr, ) + restrs, hyps, '%s (%d limited)' % (path, args[0])) ] elif kind == 'SingleRevInduct': hyp = single_induct_resulting_hyp(p, restrs, args) return [(restrs, hyps + [hyp], path)] elif kind == 'Split': split = args return [ (restrs, hyps + split_no_loop_hyps(tags, split, restrs), '%d init case in %s' % (split[0][0], path)), (restrs, hyps + split_loop_hyps(tags, split, restrs, exit=True), '%d loop case in %s' % (split[0][0], path)) ] elif kind == 'CaseSplit': (point, tag) = args visit = ((point, restrs), tag) true_hyps = hyps + [pc_true_hyp(visit)] false_hyps = hyps + [pc_false_hyp(visit)] return [(restrs, true_hyps, 'true case (%d visited) in %s' % (point, path)), (restrs, false_hyps, 'false case (%d not visited) in %s' % (point, path))] else: assert not 'proof node kind understood', proof.kind
def single_loop_induct_step_checks(p, restrs, hyps, tag, split, n, eqs, eqs_assume=None): if eqs_assume == None: eqs_assume = [] details = (split, (0, 1), eqs_assume + eqs) cont = split_visit_one_visit(tag, details, restrs, vc_offs(n)) hyps = ([pc_true_hyp(cont)] + hyps + [ h for i in range(n) for (h, _) in loop_eq_hyps_at_visit(tag, split, eqs_assume + eqs, restrs, vc_offs(i)) ]) return [ (hyps, hyp, 'Induct check (%s) at inductive step for %d' % (desc, split)) for ( hyp, desc) in loop_eq_hyps_at_visit(tag, split, eqs, restrs, vc_offs(n)) ]
def linear_eq_induct_base_checks (p, restrs, hyps, tag, split, eqs): tests = [] details = (split, (0, 1), eqs) for i in [0, 1]: reach = split_visit_one_visit (tag, details, restrs, vc_num (i)) nhyps = [pc_true_hyp (reach)] tests.extend ([(hyps + nhyps, hyp, 'Base check (%s, %d) at induct step for %d' % (desc, i, split)) for (hyp, desc) in linear_eq_hyps_at_visit (tag, split, eqs, restrs, vc_num (i))]) return tests
def get_ptr_offsets(p, n_ptrs, bases, hyps=[], cache=None, fail_early=False): """detect which ptrs are guaranteed to be at constant offsets from some set of basis ptrs""" rep = rep_graph.mk_graph_slice(p, fast=True) if cache == None: cache = {} last_get_ptr_offsets[0] = (p, n_ptrs, bases, hyps) smt_bases = [] for (n, ptr, k) in bases: n_vc = default_n_vc(p, n) (_, env) = rep.get_node_pc_env(n_vc) smt = solver.smt_expr(ptr, env, rep.solv) smt_bases.append((smt, k)) ptr_typ = ptr.typ smt_ptrs = [] for (n, ptr) in n_ptrs: n_vc = default_n_vc(p, n) pc_env = rep.get_node_pc_env(n_vc) if not pc_env: continue smt = solver.smt_expr(ptr, pc_env[1], rep.solv) hyp = rep_graph.pc_true_hyp((n_vc, p.node_tags[n][0])) smt_ptrs.append(((n, ptr), smt, hyp)) hyps = hyps + mk_not_callable_hyps(p) for tag in set([p.node_tags[n][0] for (n, _) in n_ptrs]): hyps = hyps + init_correctness_hyps(p, tag) tags = set([p.node_tags[n][0] for (n, ptr) in n_ptrs]) ex_defs = {} for t in tags: ex_defs.update(get_extra_sp_defs(rep, t)) offs = [] for (v, ptr, hyp) in smt_ptrs: off = None for (ptr2, k) in smt_bases: off = offs_expr_const(ptr, ptr2, rep, [hyp] + hyps, cache=cache, extra_defs=ex_defs, typ=ptr_typ) if off != None: offs.append((v, off, k)) break if off == None: trace('get_ptr_offs fallthrough at %d: %s' % v) trace(str([hyp] + hyps)) assert not fail_early, (v, ptr) return offs
def linear_eq_induct_step_checks (p, restrs, hyps, tag, split, eqs): details = (split, (0, 1), eqs) cont = split_visit_one_visit (tag, details, restrs, vc_offs (1)) # the 'trivial' hyp here ensures the representation includes a loop # of the rhs when proving const equations on the lhs hyps = ([pc_true_hyp (cont)] + hyps + [h for (h, _) in linear_eq_hyps_at_visit (tag, split, eqs, restrs, vc_offs (0))]) return [(hyps, hyp, 'Induct check (%s) at inductive step for %d' % (desc, split)) for (hyp, desc) in linear_eq_hyps_at_visit (tag, split, eqs, restrs, vc_offs (1))]
def single_loop_induct_base_checks(p, restrs, hyps, tag, split, n, eqs): tests = [] details = (split, (0, 1), eqs) for i in range(n + 1): reach = split_visit_one_visit(tag, details, restrs, vc_num(i)) nhyps = [pc_true_hyp(reach)] tests.extend([ (hyps + nhyps, hyp, 'Base check (%s, %d) at induct step for %d' % (desc, i, split)) for (hyp, desc ) in loop_eq_hyps_at_visit(tag, split, eqs, restrs, vc_num(i)) ]) return tests
def linear_eq_induct_step_checks(p, restrs, hyps, tag, split, eqs_assume, eqs): details = (split, (0, 1), eqs_assume + eqs) cont = split_visit_one_visit(tag, details, restrs, vc_offs(1)) hyps = ( [pc_true_hyp(cont)] + hyps + [h for (h, _) in linear_eq_hyps_at_visit(tag, split, eqs_assume + eqs, restrs, vc_offs(0))] ) return [ (hyps, hyp, "Induct check (%s) at inductive step for %d" % (desc, split)) for (hyp, desc) in linear_eq_hyps_at_visit(tag, split, eqs, restrs, vc_offs(1)) ]
def split_loop_hyps (tags, split, restrs, exit): ((r_split, _, _), _, _, n, _) = split (l_visit, _) = split_visit_visits (tags, split, restrs, vc_offs (n - 1)) (l_cont, _) = split_visit_visits (tags, split, restrs, vc_offs (n)) (l_tag, r_tag) = tags l_enter = pc_true_hyp (l_visit) l_exit = pc_false_hyp (l_cont) if exit: hyps = [l_enter, l_exit] else: hyps = [l_enter] return hyps + [hyp for offs in map (vc_offs, range (n)) for (hyp, _) in split_hyps_at_visit (tags, split, restrs, offs)]
def split_loop_hyps(tags, split, restrs, exit): ((r_split, _, _), _, _, n, _) = split (l_visit, _) = split_visit_visits(tags, split, restrs, vc_offs(n - 1)) (l_cont, _) = split_visit_visits(tags, split, restrs, vc_offs(n)) (l_tag, r_tag) = tags l_enter = pc_true_hyp(l_visit) l_exit = pc_false_hyp(l_cont) if exit: hyps = [l_enter, l_exit] else: hyps = [l_enter] return hyps + [ hyp for offs in map(vc_offs, range(n)) for (hyp, _) in split_hyps_at_visit(tags, split, restrs, offs) ]
def single_loop_rev_induct_base_checks(p, restrs, hyps, tag, split, n_bound, eqs_assume, pred): details = (split, (0, 1), eqs_assume) cont = split_visit_one_visit(tag, details, restrs, vc_offs(1)) n_hyp = mk_loop_counter_eq_hyp(p, split, restrs, n_bound) split_details = (None, details, None, 1, 1) non_err = split_r_err_pc_hyp(p, split_details, restrs) hyps = (hyps + [n_hyp, pc_true_hyp(cont), non_err] + [ h for (h, _) in loop_eq_hyps_at_visit(tag, split, eqs_assume, restrs, vc_offs(0)) ]) goal = rep_graph.true_if_at_hyp(pred, cont) return [(hyps, goal, 'Pred true at %d check.' % n_bound)]
def single_loop_rev_induct_checks(p, restrs, hyps, tag, split, eqs_assume, pred): details = (split, (0, 1), eqs_assume) curr = split_visit_one_visit(tag, details, restrs, vc_offs(1)) cont = split_visit_one_visit(tag, details, restrs, vc_offs(2)) split_details = (None, details, None, 1, 1) non_err = split_r_err_pc_hyp(p, split_details, restrs) true_next = rep_graph.true_if_at_hyp(pred, cont) hyps = (hyps + [pc_true_hyp(curr), true_next, non_err] + [ h for (h, _) in loop_eq_hyps_at_visit( tag, split, eqs_assume, restrs, vc_offs(1), use_if_at=True) ]) goal = rep_graph.true_if_at_hyp(pred, curr) return [(hyps, goal, 'Pred reverse step.')]
def split_induct_step_checks (p, restrs, hyps, split, tags = None): ((l_split, _, _), _, _, n, _) = split if tags == None: tags = p.pairing.tags err_hyp = split_r_err_pc_hyp (p, split, restrs, tags = tags) (cont, r_cont) = split_visit_visits (tags, split, restrs, vc_offs (n)) # the 'trivial' hyp here ensures the representation includes a loop # of the rhs when proving const equations on the lhs hyps = ([err_hyp, pc_true_hyp (cont), rep_graph.pc_triv_hyp (r_cont)] + hyps + split_loop_hyps (tags, split, restrs, exit = False)) return [(hyps, hyp, 'Induct check (%s) at inductive step for %d' % (desc, l_split)) for (hyp, desc) in split_hyps_at_visit (tags, split, restrs, vc_offs (n))]
def split_induct_step_checks(p, restrs, hyps, split, tags=None): ((l_split, _, _), _, _, n, _) = split if tags == None: tags = p.pairing.tags err_hyp = split_r_err_pc_hyp(p, split, restrs, tags=tags) (cont, r_cont) = split_visit_visits(tags, split, restrs, vc_offs(n)) # the 'trivial' hyp here ensures the representation includes a loop # of the rhs when proving const equations on the lhs hyps = ( [err_hyp, pc_true_hyp(cont), rep_graph.pc_triv_hyp(r_cont)] + hyps + split_loop_hyps(tags, split, restrs, exit=False)) return [(hyps, hyp, 'Induct check (%s) at inductive step for %d' % (desc, l_split)) for (hyp, desc) in split_hyps_at_visit(tags, split, restrs, vc_offs(n))]
def split_init_step_checks(p, restrs, hyps, split, tags=None): (_, _, _, n, _) = split if tags == None: tags = p.pairing.tags err_hyp = split_r_err_pc_hyp(p, split, restrs, tags=tags) hyps = [err_hyp] + hyps checks = [] for i in range(n): (l_visit, r_visit) = split_visit_visits(tags, split, restrs, vc_num(i)) lpc_hyp = pc_true_hyp(l_visit) # this trivial 'hyp' ensures the rep is built to include # the matching rhs visits when checking lhs consts rpc_triv_hyp = rep_graph.pc_triv_hyp(r_visit) vis_hyps = split_hyps_at_visit(tags, split, restrs, vc_num(i)) for (hyp, desc) in vis_hyps: checks.append((hyps + [lpc_hyp, rpc_triv_hyp], hyp, 'Induct check at visit %d: %s' % (i, desc))) return checks
def split_init_step_checks (p, restrs, hyps, split, tags = None): (_, _, _, n, _) = split if tags == None: tags = p.pairing.tags err_hyp = split_r_err_pc_hyp (p, split, restrs, tags = tags) hyps = [err_hyp] + hyps checks = [] for i in range (n): (l_visit, r_visit) = split_visit_visits (tags, split, restrs, vc_num (i)) lpc_hyp = pc_true_hyp (l_visit) # this trivial 'hyp' ensures the rep is built to include # the matching rhs visits when checking lhs consts rpc_triv_hyp = rep_graph.pc_triv_hyp (r_visit) vis_hyps = split_hyps_at_visit (tags, split, restrs, vc_num (i)) for (hyp, desc) in vis_hyps: checks.append ((hyps + [lpc_hyp, rpc_triv_hyp], hyp, 'Induct check at visit %d: %s' % (i, desc))) return checks
def get_ptr_offsets (p, n_ptrs, bases, hyps = []): """detect which ptrs are guaranteed to be at constant offsets from some set of basis ptrs""" rep = rep_graph.mk_graph_slice (p, fast = True) cache = {} last_get_ptr_offsets[0] = (p, n_ptrs, bases, hyps) smt_bases = [] for (n, ptr, k) in bases: n_vc = default_n_vc (p, n) (_, env) = rep.get_node_pc_env (n_vc) smt = solver.smt_expr (ptr, env, rep.solv) smt_bases.append ((smt, k)) smt_ptrs = [] for (n, ptr) in n_ptrs: n_vc = default_n_vc (p, n) pc_env = rep.get_node_pc_env (n_vc) if not pc_env: continue smt = solver.smt_expr (ptr, pc_env[1], rep.solv) hyp = rep_graph.pc_true_hyp ((n_vc, p.node_tags[n][0])) smt_ptrs.append (((n, ptr), smt, hyp)) hyps = hyps + mk_not_callable_hyps (p) tags = set ([p.node_tags[n][0] for (n, ptr) in n_ptrs]) ex_defs = {} for t in tags: ex_defs.update (get_extra_sp_defs (rep, t)) offs = [] for (v, ptr, hyp) in smt_ptrs: for (ptr2, k) in smt_bases: off = offs_expr_const (ptr, ptr2, rep, [hyp] + hyps, cache = cache, extra_defs = ex_defs) if off != None: offs.append ((v, off, k)) break trace ('get_ptr_offs fallthrough at %d: %s' % v) return offs
def try_pairing_at_funcall(p, name, head=None, restrs=None, hyps=None, at='At'): pairs = set(pairings[name]) addrs = [ n for (n, name2) in p.function_call_addrs() if [pair for pair in pairings[name2] if pair in pairs] ] assert at in ['At', 'After'] if at == 'After': addrs = [p.nodes[n].cont for n in addrs] if head == None: tags = p.pairing.tags [head] = [ n for n in search.init_loops_to_split(p, ()) if p.node_tags[n][0] == tags[0] ] if restrs == None: restrs = () if hyps == None: hyps = check.init_point_hyps(p) while True: res = search.find_split_loop(p, head, restrs, hyps, node_restrs=set(addrs)) if res[0] == 'CaseSplit': (_, ((n, tag), _)) = res hyp = rep_graph.pc_true_hyp(((n, restrs), tag)) hyps = hyps + [hyp] else: return res
restr_others(p, (restr, ) + restrs, 2)) hyps = [ncerr_hyp] + hyps def visit(vc): return ((n, ((n, vc), ) + restrs), p.node_tags[n][0]) # this cannot be more uniform because the representation of visit # at offset 0 is all a bit odd, with n being the only node so visited: if kind == 'Offset': min_vc = vc_offs(max(0, x - 1)) elif x > 1: min_vc = vc_num(x - 1) else: min_vc = None if min_vc: init_check = [(hyps, pc_true_hyp(visit(min_vc)), 'Check of restr min %d %s for %d' % (x, kind, n))] else: init_check = [] # if we can reach node n with (y - 1) visits to n, then the next # node will have y visits to n, which we are disallowing # thus we show that this visit is impossible top_vc = VisitCount(kind, y - 1) top_check = (hyps, pc_false_hyp(visit(top_vc)), 'Check of restr max %d %s for %d' % (y, kind, n)) return init_check + [top_check] def split_init_step_checks(p, restrs, hyps, split, tags=None): (_, _, _, n, _) = split
ncerr_hyp = non_r_err_pc_hyp (p.pairing.tags, restr_others (p, (restr, ) + restrs, 2)) hyps = [ncerr_hyp] + hyps def visit (vc): return ((n, ((n, vc), ) + restrs), p.node_tags[n][0]) # this cannot be more uniform because the representation of visit # at offset 0 is all a bit odd, with n being the only node so visited: if kind == 'Offset': min_vc = vc_offs (max (0, x - 1)) elif x > 1: min_vc = vc_num (x - 1) else: min_vc = None if min_vc: init_check = [(hyps, pc_true_hyp (visit (min_vc)), 'Check of restr min %d %s for %d' % (x, kind, n))] else: init_check = [] # if we can reach node n with (y - 1) visits to n, then the next # node will have y visits to n, which we are disallowing # thus we show that this visit is impossible top_vc = VisitCount (kind, y - 1) top_check = (hyps, pc_false_hyp (visit (top_vc)), 'Check of restr max %d %s for %d' % (y, kind, n)) return init_check + [top_check] def split_init_step_checks (p, restrs, hyps, split, tags = None): (_, _, _, n, _) = split if tags == None:
def get_pc_hyp_local(rep, n, focused_loops=None): return rep_graph.pc_true_hyp(get_vis(rep.p, n, focused_loops=focused_loops))
def get_pc_hyp_local(rep, n): return rep_graph.pc_true_hyp(get_vis(rep.p, n))
def get_necessary_split_opts (p, head, restrs, hyps, tags = None, iters = None): if not tags: tags = p.pairing.tags [l_tag, r_tag] = tags assert p.node_tags[head][0] == l_tag l_seq_vs = get_interesting_linear_series_exprs (p, head) if not l_seq_vs: return None r_seq_vs = {} for n in init_loops_to_split (p, restrs): if p.node_tags[n][0] == r_tag: vs = get_interesting_linear_series_exprs (p, n) r_seq_vs.update (vs) if not r_seq_vs: return None rep = rep_graph.mk_graph_slice (p, fast = True) def vis (n, i): if n != p.loop_id (n): i = i + 1 return (n, tuple ([(p.loop_id (n), vc_num (i))]) + restrs) smt = lambda expr, n, i: rep.to_smt_expr (expr, vis (n, i)) smt_pc = lambda n, i: rep.get_pc (vis (n, i)) # remove duplicates by concretising l_seq_vs = dict ([(smt (expr, n, 2), (kind, n, expr)) for n in l_seq_vs for (kind, expr) in l_seq_vs[n]]).values () r_seq_vs = dict ([(smt (expr, n, 2), (kind, n, expr)) for n in r_seq_vs for (kind, expr) in r_seq_vs[n]]).values () if iters == None: if [n for n in p.loop_body (head) if p.nodes[n].kind == 'Call']: iters = 5 else: iters = 8 r_seq_end = 1 + 2 * iters l_seq_end = 1 + iters l_seq_ineq = 1 + max ([1 << n for n in range (iters) if 1 << n <= iters]) hyps = hyps + [rep_graph.pc_triv_hyp ((vis (n, r_seq_end), r_tag)) for n in set ([n for (_, n, _) in r_seq_vs])] hyps = hyps + [rep_graph.pc_triv_hyp ((vis (n, l_seq_end), l_tag)) for n in set ([n for (_, n, _) in l_seq_vs])] ex_restrs = [(n, rep_graph.vc_upto (r_seq_end + 1)) for n in set ([p.loop_id (n) for (_, n, _) in r_seq_vs])] hyps = hyps + [check.non_r_err_pc_hyp (tags, restr_others (p, restrs + tuple (ex_restrs), 2))] necessary_split_opts_trace[:] = [] necessary_split_opts_long_trace[:] = [] for (kind, n, expr) in sorted (l_seq_vs): rel_r_seq_vs = [v for v in r_seq_vs if v[0] == kind] if not rel_r_seq_vs: necessary_split_opts_trace.append ((n, 'NoneRelevant')) continue m = {} eq = mk_eq (smt (expr, n, 1), smt (expr, n, l_seq_ineq)) ex_hyps = [rep_graph.pc_true_hyp ((vis (n, i), l_tag)) for i in range (1, l_seq_end + 1)] res = rep.test_hyp_whyps (eq, hyps + ex_hyps, model = m) necessary_split_opts_long_trace.append ((n, eq, hyps + ex_hyps, res, m, smt, smt_pc, (kind, n, expr), r_seq_vs, iters)) if not m: necessary_split_opts_trace.append ((n, None)) continue seq_eq = get_linear_seq_eq (rep, m, smt, smt_pc, (kind, n, expr), r_seq_vs, iters) necessary_split_opts_trace.append ((n, ('Seq', seq_eq))) if not seq_eq: continue ((n2, expr2), (l_start, l_step), (r_start, r_step)) = seq_eq eqs = [rep_graph.eq_hyp ((expr, (vis (n, l_start + (i * l_step)), l_tag)), (expr2, (vis (n2, r_start + (i * r_step)), r_tag))) for i in range (10) if l_start + (i * l_step) <= l_seq_end if r_start + (i * r_step) <= r_seq_end] eq = foldr1 (mk_and, map (rep.interpret_hyp, eqs)) if rep.test_hyp_whyps (eq, hyps): mk_i = lambda i: (l_start + (i * l_step), l_step) mk_j = lambda j: (r_start + (j * r_step), r_step) return [([mk_i (0)], [mk_j (0)]), ([mk_i (0), mk_i (1)], [mk_j (0), mk_j (1)])] n_vcs = entry_path_no_loops (rep, l_tag, m, head) path_hyps = [rep_graph.pc_true_hyp ((n_vc, l_tag)) for n_vc in n_vcs] if rep.test_hyp_whyps (eq, hyps + path_hyps): # immediate case split on difference between entry paths checks = [(hyps, eq_hyp, 'eq') for eq_hyp in eqs] return derive_case_split (rep, n_vcs, checks) necessary_split_opts_trace.append ((n, 'Seq check failed')) return None