Example #1
0
def build_proof_rec_with_restrs (split_points, kind, searcher, p, restrs, hyps):
	sp = split_points[0]
	use_hyps = list (hyps)
	if p.node_tags[sp][0] != p.pairing.tags[1]:
		nrerr_hyp = check.non_r_err_pc_hyp (p.pairing.tags,
			restr_others (p, restrs, 2))
		use_hyps = use_hyps + [nrerr_hyp]
	limit = find_split_limit (p, sp, restrs, use_hyps, kind)
	# double-check this limit with a rep constructed without the 'fast' flag
	limit = find_split_limit (p, sp, restrs, use_hyps, kind,
		hints = [limit, limit + 1], use_rep = mk_graph_slice (p))
	if kind == 'Number':
		vc_opts = vc_upto (limit + 1)
	else:
		vc_opts = vc_offset_upto (limit + 1)
	restrs = restrs + ((sp, vc_opts), )
	if len (split_points) == 1:
		subproof = build_proof_rec (searcher, p, restrs, hyps)
	else:
		subproof = build_proof_rec_with_restrs (split_points[1:],
			kind, searcher, p, restrs, hyps)

	return ProofNode ('Restr', (sp, (kind, (0, limit + 1))), [subproof])
Example #2
0
def build_proof_rec_with_restrs (split_points, kind, searcher, p, restrs,
		hyps, must_find = True, name = "problem"):
	if not split_points:
		return build_proof_rec (searcher, p, restrs, hyps, name = name)

	sp = split_points[0]
	use_hyps = list (hyps)
	if p.node_tags[sp][0] != p.pairing.tags[1]:
		nrerr_hyp = check.non_r_err_pc_hyp (p.pairing.tags,
			restr_others (p, restrs, 2))
		use_hyps = use_hyps + [nrerr_hyp]

	if p.loop_id (sp):
		lim_pair = get_proof_split_limit (p, sp, restrs, use_hyps,
			kind, must_find = must_find)
	else:
		lim_pair = get_proof_visit_restr (p, sp, restrs, use_hyps,
			kind, must_find = must_find)

	if not lim_pair:
		assert not must_find
		return build_proof_rec_with_restrs (split_points[1:],
			kind, searcher, p, restrs, hyps, must_find = must_find,
			name = name)

	(min_v, max_v) = lim_pair
	if kind == 'Number':
		vc_opts = rep_graph.vc_options (range (min_v, max_v), [])
	else:
		vc_opts = rep_graph.vc_options ([], range (min_v, max_v))

	restrs = restrs + ((sp, vc_opts), )
	subproof = build_proof_rec_with_restrs (split_points[1:],
		kind, searcher, p, restrs, hyps, must_find = must_find,
		name = name)

	return ProofNode ('Restr', (sp, (kind, (min_v, max_v))), [subproof])
Example #3
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