fix(library/blast/subst): bug in subst action, add hypothesis_idx_buffer_set (helper class), refine revert_action interface

This commit is contained in:
Leonardo de Moura 2015-11-13 16:10:25 -08:00
parent 65b962dabd
commit 3849aff674
7 changed files with 85 additions and 61 deletions

View file

@ -47,4 +47,29 @@ public:
bool depends_on(expr const & h) const { return m_deps.contains(href_index(h)); }
bool is_assumption() const { return !m_value || is_local_non_href(*m_value); }
};
class hypothesis_idx_buffer_set {
friend class state;
hypothesis_idx_buffer m_buffer;
hypothesis_idx_set m_set;
public:
hypothesis_idx_buffer_set() {}
hypothesis_idx_buffer_set(hypothesis_idx_buffer const & b) {
for (auto hidx : b)
insert(hidx);
}
void insert(hypothesis_idx h) {
if (!m_set.contains(h)) {
m_set.insert(h);
m_buffer.push_back(h);
}
}
hypothesis_idx_buffer const & as_buffer() const {
return m_buffer;
}
hypothesis_idx_set const & as_set() const {
return m_set;
}
};
}}

View file

@ -23,26 +23,25 @@ struct revert_proof_step_cell : public proof_step_cell {
virtual bool is_silent() const override { return true; }
};
unsigned revert_action(buffer<hypothesis_idx> & hidxs, hypothesis_idx_set & hidxs_set) {
lean_assert(hidxs.size() == hidxs_set.size());
unsigned revert_action(hypothesis_idx_buffer_set & hidxs) {
state & s = curr_state();
unsigned hidxs_size = hidxs.size();
unsigned hidxs_size = hidxs.as_buffer().size();
for (unsigned i = 0; i < hidxs_size; i++) {
s.collect_forward_deps(hidxs[i], hidxs, hidxs_set);
s.collect_forward_deps(hidxs.as_buffer()[i], hidxs);
}
s.sort_hypotheses(hidxs);
buffer<expr> hs;
s.to_hrefs(hidxs, hs);
s.to_hrefs(hidxs.as_buffer(), hs);
expr target = s.get_target();
expr new_target = s.mk_pi(hs, target);
s.set_target(new_target);
s.push_proof_step(new revert_proof_step_cell(to_list(hs)));
lean_verify(s.del_hypotheses(hidxs));
return hidxs.size();
lean_verify(s.del_hypotheses(hidxs.as_buffer()));
return hidxs.as_buffer().size();
}
unsigned revert_action(buffer<hypothesis_idx> & hidxs) {
hypothesis_idx_set hidxs_set(hidxs);
return revert_action(hidxs, hidxs_set);
hypothesis_idx_buffer_set _hidxs(hidxs);
return revert_action(_hidxs);
}
}}

View file

@ -12,8 +12,5 @@ namespace blast {
/** \brief Revert the given hypotheses and their dependencies.
Return the total number of hypotheses reverted. */
unsigned revert_action(buffer<hypothesis_idx> & hidxs);
/** \brief Lower-level version of previous procedure.
\pre hidxs and hidxs_set contain the same elements. */
unsigned revert_action(buffer<hypothesis_idx> & hidxs, hypothesis_idx_set & hidxs_set);
unsigned revert_action(hypothesis_idx_buffer_set & hidxs);
}}

View file

@ -363,6 +363,10 @@ void state::sort_hypotheses(hypothesis_idx_buffer & r) const {
std::sort(r.begin(), r.end(), hypothesis_dep_depth_lt(*this));
}
void state::sort_hypotheses(hypothesis_idx_buffer_set & r) const {
std::sort(r.m_buffer.begin(), r.m_buffer.end(), hypothesis_dep_depth_lt(*this));
}
void state::to_hrefs(hypothesis_idx_buffer const & hidxs, buffer<expr> & r) const {
for (hypothesis_idx hidx : hidxs)
r.push_back(get_hypothesis_decl(hidx)->get_self());
@ -485,19 +489,15 @@ void state::del_hypotheses(buffer<hypothesis_idx> const & to_delete, hypothesis_
}
}
void state::collect_forward_deps(hypothesis_idx hidx, buffer<hypothesis_idx> & result, hypothesis_idx_set & already_found) {
unsigned qhead = result.size();
void state::collect_forward_deps(hypothesis_idx hidx, hypothesis_idx_buffer_set & result) {
hypothesis_idx_buffer const & b = result.as_buffer();
unsigned qhead = b.size();
while (true) {
hypothesis_idx_set s = get_forward_deps(hidx);
s.for_each([&](hypothesis_idx h_dep) {
if (already_found.contains(h_dep))
hypothesis_idx_set s = get_direct_forward_deps(hidx);
s.for_each([&](hypothesis_idx h_dep) { result.insert(h_dep); });
if (qhead == b.size())
return;
already_found.insert(h_dep);
result.push_back(h_dep);
});
if (qhead == result.size())
return;
hidx = result[qhead];
hidx = b[qhead];
qhead++;
}
}
@ -514,38 +514,29 @@ bool state::safe_to_delete(buffer<hypothesis_idx> const & to_delete) {
return true;
}
void state::collect_forward_deps(hypothesis_idx hidx, buffer<hypothesis_idx> & result) {
hypothesis_idx_set found;
collect_forward_deps(hidx, result, found);
}
bool state::del_hypotheses(buffer<hypothesis_idx> const & hs) {
hypothesis_idx_set found;
buffer<hypothesis_idx> to_delete;
hypothesis_idx_buffer_set to_delete;
for (hypothesis_idx hidx : hs) {
to_delete.push_back(hidx);
found.insert(hidx);
collect_forward_deps(hidx, to_delete, found);
to_delete.insert(hidx);
collect_forward_deps(hidx, to_delete);
}
if (!safe_to_delete(to_delete))
if (!safe_to_delete(to_delete.as_buffer()))
return false;
del_hypotheses(to_delete, found);
del_hypotheses(to_delete.as_buffer(), to_delete.as_set());
return true;
}
bool state::del_hypothesis(hypothesis_idx hidx) {
hypothesis_idx_set found;
buffer<hypothesis_idx> to_delete;
to_delete.push_back(hidx);
found.insert(hidx);
collect_forward_deps(hidx, to_delete, found);
if (!safe_to_delete(to_delete))
hypothesis_idx_buffer_set to_delete;
to_delete.insert(hidx);
collect_forward_deps(hidx, to_delete);
if (!safe_to_delete(to_delete.as_buffer()))
return false;
del_hypotheses(to_delete, found);
del_hypotheses(to_delete.as_buffer(), to_delete.as_set());
return true;
}
hypothesis_idx_set state::get_forward_deps(hypothesis_idx hidx) const {
hypothesis_idx_set state::get_direct_forward_deps(hypothesis_idx hidx) const {
if (auto r = m_branch.m_forward_deps.find(hidx))
return *r;
else

View file

@ -219,9 +219,22 @@ public:
bool del_hypothesis(hypothesis_idx hidx);
bool del_hypotheses(buffer<hypothesis_idx> const & hs);
/** \brief Return the set of hypotheses that (directly) depend on the given one */
hypothesis_idx_set get_direct_forward_deps(hypothesis_idx hidx) const;
/** \brief Collect in \c result the hypotheses that (directly) depend on \c hidx and satisfy \c pred. */
template<typename P>
void collect_direct_forward_deps(hypothesis_idx hidx, hypothesis_idx_buffer_set & result, P && pred) {
get_direct_forward_deps(hidx).for_each([&](hypothesis_idx d) {
if (pred(d)) result.insert(d);
});
}
/** \brief Collect in \c result the hypotheses that (directly) depend on \c hidx and satisfy \c pred. */
void collect_direct_forward_deps(hypothesis_idx hidx, hypothesis_idx_buffer_set & result) {
return collect_direct_forward_deps(hidx, result, [](hypothesis_idx) { return true; });
}
/** \brief Collect all hypothesis in \c result that depend directly or indirectly on hidx */
void collect_forward_deps(hypothesis_idx hidx, buffer<hypothesis_idx> & result);
void collect_forward_deps(hypothesis_idx hidx, buffer<hypothesis_idx> & result, hypothesis_idx_set & already_found);
void collect_forward_deps(hypothesis_idx hidx, hypothesis_idx_buffer_set & result);
/** \brief Return true iff the hypothesis with index \c hidx_user depends on the hypothesis with index
\c hidx_provider. */
@ -244,6 +257,7 @@ public:
void get_sorted_hypotheses(hypothesis_idx_buffer & r) const;
/** \brief Sort hypotheses in r */
void sort_hypotheses(hypothesis_idx_buffer & r) const;
void sort_hypotheses(hypothesis_idx_buffer_set & r) const;
/** \brief Convert hypotheses indices into hrefs */
void to_hrefs(hypothesis_idx_buffer const & hidxs, buffer<expr> & r) const;
@ -261,13 +275,6 @@ public:
/** \brief Return (active) hypotheses whose head symbol is equal to target or it is the negation of */
list<hypothesis_idx> get_head_related() const;
/** \brief Return the set of hypotheses that (directly) depend on the given one */
hypothesis_idx_set get_forward_deps(hypothesis_idx hidx) const;
template<typename F>
void for_each_forward_dep(hypothesis_idx hidx, F && f) const {
get_forward_deps(hidx).for_each(f);
}
/************************
Abstracting hypotheses
*************************/

View file

@ -52,13 +52,11 @@ bool subst_core(hypothesis_idx hidx) {
lean_verify(is_eq(type, lhs, rhs));
lean_assert(is_href(rhs));
try {
hypothesis_idx_buffer to_revert;
s.for_each_forward_dep(href_index(rhs),
[&](hypothesis_idx d) {
if (d != hidx) to_revert.push_back(d);
});
s.for_each_forward_dep(hidx,
[&](hypothesis_idx d) { to_revert.push_back(d); });
hypothesis_idx_buffer_set to_revert;
s.collect_direct_forward_deps(href_index(rhs),
to_revert,
[&](hypothesis_idx d) { return d != hidx; });
s.collect_direct_forward_deps(hidx, to_revert);
unsigned num = revert_action(to_revert);
expr target = s.get_target();
expr new_target = abstract(target, h->get_self());
@ -90,7 +88,7 @@ bool subst_action(hypothesis_idx hidx) {
if (is_href(rhs)) {
return subst_core(hidx);
} else if (is_href(lhs)) {
if (!s.get_forward_deps(href_index(lhs)).empty()) {
if (!s.get_direct_forward_deps(href_index(lhs)).empty()) {
// TODO(Leo): we don't handle this case yet.
// Other hypotheses depend on this equality.
return false;

View file

@ -0,0 +1,7 @@
set_option blast.init_depth 10
lemma lemma1 (bv : nat → Type) (n m : nat) (H : n = m) (b1 : bv n) (b2 : bv m) (H2 : eq.rec_on H b1 = b2) : b1 = eq.rec_on (eq.symm H) b2 :=
by blast
reveal lemma1
print lemma1