diff --git a/library/init/logic.lean b/library/init/logic.lean index ded3cf685..2ad5df110 100644 --- a/library/init/logic.lean +++ b/library/init/logic.lean @@ -243,6 +243,7 @@ notation a ∧ b := and a b variables {a b c d : Prop} attribute and.rec [elim] +attribute and.intro [intro] theorem and.elim (H₁ : a ∧ b) (H₂ : a → b → c) : c := and.rec H₂ H₁ diff --git a/src/library/blast/grinder/grinder_actions.cpp b/src/library/blast/grinder/grinder_actions.cpp index b3419da21..95aa883bd 100644 --- a/src/library/blast/grinder/grinder_actions.cpp +++ b/src/library/blast/grinder/grinder_actions.cpp @@ -5,6 +5,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Author: Leonardo de Moura */ #include "library/blast/blast.h" +#include "library/blast/trace.h" #include "library/blast/actions/recursor_action.h" #include "library/blast/backward/backward_action.h" #include "library/blast/grinder/intro_elim_lemmas.h" @@ -18,7 +19,9 @@ struct grinder_branch_extension : public branch_extension { name_map m_elim_lemmas; grinder_branch_extension() {} - grinder_branch_extension(grinder_branch_extension const &) {} + grinder_branch_extension(grinder_branch_extension const & e): + m_intro_lemmas(e.m_intro_lemmas), + m_elim_lemmas(e.m_elim_lemmas) {} virtual ~grinder_branch_extension() {} virtual branch_extension * clone() override { return new grinder_branch_extension(*this); } virtual void initialized() override { diff --git a/src/library/blast/grinder/grinder_strategy.cpp b/src/library/blast/grinder/grinder_strategy.cpp index 78b66d623..2246e2a4a 100644 --- a/src/library/blast/grinder/grinder_strategy.cpp +++ b/src/library/blast/grinder/grinder_strategy.cpp @@ -42,9 +42,16 @@ action_result grinder_strategy_core_fn::next_action() { } strategy grind_and_then(strategy const & S) { - return [=]() { return grinder_strategy_fn([](hypothesis_idx) { return action_result::failed(); }, // NOLINT - [](hypothesis_idx) { return action_result::failed(); }, // NOLINT - [=]() { TryStrategy(S); return action_result::failed(); })(); // NOLINT + return [=]() { // NOLINT + curr_state().deactivate_all(); + return grinder_strategy_fn([](hypothesis_idx) { return action_result::failed(); }, // NOLINT + [](hypothesis_idx) { return action_result::failed(); }, // NOLINT + [=]() { // NOLINT + if (optional pf = S()) { + return action_result::solved(*pf); + } + return action_result::failed(); + })(); }; } }} diff --git a/src/library/blast/grinder/grinder_strategy.h b/src/library/blast/grinder/grinder_strategy.h index 4b6ea0832..933e91d9d 100644 --- a/src/library/blast/grinder/grinder_strategy.h +++ b/src/library/blast/grinder/grinder_strategy.h @@ -37,5 +37,5 @@ public: m_pre(pre), m_post(post), m_next(next) {} }; -strategy grind_and_then(strategy & S); +strategy grind_and_then(strategy const & S); }} diff --git a/src/library/blast/state.cpp b/src/library/blast/state.cpp index 4ce3bd00d..4d1f9878e 100644 --- a/src/library/blast/state.cpp +++ b/src/library/blast/state.cpp @@ -595,6 +595,11 @@ double state::compute_weight(unsigned hidx, expr const & /* type */) { return 1.0 / (static_cast(hidx) + 1.0); } +void state::add_todo_queue(hypothesis_idx hidx) { + double w = compute_weight(hidx, get_hypothesis_decl(hidx).get_type()); + m_branch.m_todo_queue.insert(w, hidx); +} + expr state::mk_hypothesis(unsigned new_hidx, name const & n, expr const & type, optional const & value) { hypothesis new_h; expr r = mk_href(new_hidx); @@ -607,8 +612,7 @@ expr state::mk_hypothesis(unsigned new_hidx, name const & n, expr const & type, m_branch.m_hyp_decls.insert(new_hidx, new_h); if (new_h.is_assumption()) m_branch.m_assumption.insert(new_hidx); - double w = compute_weight(new_hidx, type); - m_branch.m_todo_queue.insert(w, new_hidx); + add_todo_queue(new_hidx); return r; } @@ -780,6 +784,21 @@ branch_extension & state::get_extension(unsigned extid) { } } +void state::deactivate_all() { + m_branch.m_head_to_hyps = head_map(); + unsigned n = get_extension_manager().get_num_extensions(); + for (unsigned i = 0; i < n; i++) { + if (m_branch.m_extensions[i]) { + m_branch.m_extensions[i]->dec_ref(); + m_branch.m_extensions[i] = nullptr; + } + } + m_branch.m_active.for_each([&](hypothesis_idx hidx) { + add_todo_queue(hidx); + }); + m_branch.m_active = hypothesis_idx_set(); +} + void state::update_indices(hypothesis_idx hidx) { hypothesis const & h = get_hypothesis_decl(hidx); /* update m_head_to_hyps */ diff --git a/src/library/blast/state.h b/src/library/blast/state.h index e965a8cbd..4244ea052 100644 --- a/src/library/blast/state.h +++ b/src/library/blast/state.h @@ -183,6 +183,8 @@ class state { void add_deps(hypothesis & h_user, hypothesis_idx hidx_user); void del_forward_dep(unsigned hidx_user, unsigned hidx_provider); + void add_todo_queue(hypothesis_idx hidx); + expr mk_hypothesis(hypothesis_idx new_hidx, name const & n, expr const & type, optional const & value); unsigned add_metavar_decl(metavar_decl const & decl); @@ -297,6 +299,9 @@ public: optional select_hypothesis_to_activate(); void activate_hypothesis(hypothesis_idx hidx); + /** \brief Deactivate all active hypotheses */ + void deactivate_all(); + /** \brief Store in \c r the hypotheses in this branch sorted by dependency depth */ void get_sorted_hypotheses(hypothesis_idx_buffer & r) const; /** \brief Sort hypotheses in r */ diff --git a/src/library/blast/strategies/portfolio.cpp b/src/library/blast/strategies/portfolio.cpp index aa56a30f8..2ab8255e4 100644 --- a/src/library/blast/strategies/portfolio.cpp +++ b/src/library/blast/strategies/portfolio.cpp @@ -12,6 +12,7 @@ Author: Leonardo de Moura #include "library/blast/forward/ematch.h" #include "library/blast/backward/backward_action.h" #include "library/blast/backward/backward_strategy.h" +#include "library/blast/grinder/grinder_strategy.h" #include "library/blast/strategies/simple_strategy.h" #include "library/blast/strategies/preprocess_strategy.h" #include "library/blast/strategies/debug_action_strategy.h" @@ -62,6 +63,14 @@ static optional apply_unit() { []() { return action_result::failed(); })(); } +static optional apply_grind() { + return preprocess_and_then(grind_and_then([]() { return none_expr(); }))(); +} + +static optional apply_core_grind() { + return grind_and_then([]() { return none_expr(); })(); +} + optional apply_strategy() { std::string s_name(get_config().m_strategy); if (s_name == "preprocess") { @@ -77,6 +86,10 @@ optional apply_strategy() { return apply_simple(); } else if (s_name == "cc") { return apply_cc(); + } else if (s_name == "grind") { + return apply_grind(); + } else if (s_name == "core_grind") { + return apply_core_grind(); } else if (s_name == "ematch") { return apply_ematch(); } else if (s_name == "constructor") { diff --git a/tests/lean/run/blast_grind1.lean b/tests/lean/run/blast_grind1.lean new file mode 100644 index 000000000..05f47291a --- /dev/null +++ b/tests/lean/run/blast_grind1.lean @@ -0,0 +1,33 @@ +set_option blast.strategy "core_grind" + +example (a b c : nat) : a = b ∨ a = c → b = c → b = a := +by blast + +example (f : nat → nat) (a b c : nat) : f a = f b ∨ f a = f c → f b = f c → f b = f a := +by blast + +definition ex1 (a : nat) : a = 0 → (λ x, x + a) = (λ x, x + 0) := +by blast + +print ex1 + +attribute Exists.intro [intro] + +example (p q : nat → Prop) : (∃ x, p x ∧ q x) → (∃ x, q x) ∧ (∃ x, p x) := +by blast + +set_option blast.strategy "grind" + +example (a b c : nat) : a = b ∨ a = c → b = c → b = a := +by blast + +example (f : nat → nat) (a b c : nat) : f a = f b ∨ f a = f c → f b = f c → f b = f a := +by blast + +example (a : nat) : a = 0 → (λ x, x + a) = (λ x, x + 0) := +by blast + +attribute Exists.intro [intro] + +example (p q : nat → Prop) : (∃ x, p x ∧ q x) → (∃ x, q x) ∧ (∃ x, p x) := +by blast