Ejemplo n.º 1
0
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, ())
Ejemplo n.º 2
0
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)
Ejemplo n.º 3
0
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]))
Ejemplo n.º 4
0
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
Ejemplo n.º 5
0
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
Ejemplo n.º 6
0
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))
    ]
Ejemplo n.º 7
0
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
Ejemplo n.º 8
0
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
Ejemplo n.º 9
0
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))]
Ejemplo n.º 10
0
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
Ejemplo n.º 11
0
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))
    ]
Ejemplo n.º 12
0
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)]
Ejemplo n.º 13
0
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)
    ]
Ejemplo n.º 14
0
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)]
Ejemplo n.º 15
0
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.')]
Ejemplo n.º 16
0
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))]
Ejemplo n.º 17
0
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))]
Ejemplo n.º 18
0
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
Ejemplo n.º 19
0
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
Ejemplo n.º 20
0
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
Ejemplo n.º 21
0
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
Ejemplo n.º 22
0
                                 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
Ejemplo n.º 23
0
	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:
Ejemplo n.º 24
0
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))
Ejemplo n.º 25
0
def get_pc_hyp_local(rep, n):
    return rep_graph.pc_true_hyp(get_vis(rep.p, n))
Ejemplo n.º 26
0
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