refactor(library/blast): make sure all actions return action_result, add macros for simplifying strategy definition
revert is not an action, but a procedure for helping us to build actions.
This commit is contained in:
parent
59e676e4fa
commit
453e90261b
13 changed files with 118 additions and 148 deletions
|
@ -1,5 +1,5 @@
|
||||||
add_library(blast OBJECT expr.cpp state.cpp blast.cpp blast_tactic.cpp
|
add_library(blast OBJECT expr.cpp state.cpp blast.cpp blast_tactic.cpp
|
||||||
init_module.cpp simplifier.cpp simple_actions.cpp intros_action.cpp proof_expr.cpp
|
init_module.cpp simplifier.cpp simple_actions.cpp intros_action.cpp proof_expr.cpp
|
||||||
options.cpp choice_point.cpp simple_strategy.cpp backward_action.cpp util.cpp
|
options.cpp choice_point.cpp simple_strategy.cpp backward_action.cpp util.cpp
|
||||||
gexpr.cpp revert_action.cpp subst_action.cpp no_confusion_action.cpp
|
gexpr.cpp revert.cpp subst_action.cpp no_confusion_action.cpp
|
||||||
simplify_actions.cpp strategy.cpp recursor_action.cpp congruence_closure.cpp)
|
simplify_actions.cpp strategy.cpp recursor_action.cpp congruence_closure.cpp)
|
||||||
|
|
|
@ -21,9 +21,9 @@ public:
|
||||||
private:
|
private:
|
||||||
kind m_kind;
|
kind m_kind;
|
||||||
expr m_proof;
|
expr m_proof;
|
||||||
|
public:
|
||||||
action_result(bool b = true):m_kind(b ? NewBranch : Failed) {}
|
action_result(bool b = true):m_kind(b ? NewBranch : Failed) {}
|
||||||
action_result(expr const & pr):m_kind(Solved), m_proof(pr) {}
|
action_result(expr const & pr):m_kind(Solved), m_proof(pr) {}
|
||||||
public:
|
|
||||||
kind get_kind() const { return m_kind; }
|
kind get_kind() const { return m_kind; }
|
||||||
expr get_proof() const { lean_assert(m_kind == Solved); return m_proof; }
|
expr get_proof() const { lean_assert(m_kind == Solved); return m_proof; }
|
||||||
static action_result failed() { return action_result(false); }
|
static action_result failed() { return action_result(false); }
|
||||||
|
@ -34,4 +34,7 @@ public:
|
||||||
|
|
||||||
inline bool failed(action_result const & r) { return r.get_kind() == action_result::Failed; }
|
inline bool failed(action_result const & r) { return r.get_kind() == action_result::Failed; }
|
||||||
inline bool solved(action_result const & r) { return r.get_kind() == action_result::Solved; }
|
inline bool solved(action_result const & r) { return r.get_kind() == action_result::Solved; }
|
||||||
|
|
||||||
|
#define Try(Code) { action_result r = Code; if (!failed(r)) return r; }
|
||||||
|
#define TrySolve(Code) { action_result r = Code; if (solved(r)) return r.to_opt_expr(); }
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -23,13 +23,13 @@ struct intros_proof_step_cell : public proof_step_cell {
|
||||||
virtual bool is_silent() const override { return true; }
|
virtual bool is_silent() const override { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
bool intros_action(unsigned max) {
|
action_result intros_action(unsigned max) {
|
||||||
if (max == 0)
|
if (max == 0)
|
||||||
return true;
|
return action_result::new_branch();
|
||||||
state & s = curr_state();
|
state & s = curr_state();
|
||||||
expr target = whnf(s.get_target());
|
expr target = whnf(s.get_target());
|
||||||
if (!is_pi(target))
|
if (!is_pi(target))
|
||||||
return false;
|
return action_result::failed();
|
||||||
auto pcell = new intros_proof_step_cell();
|
auto pcell = new intros_proof_step_cell();
|
||||||
s.push_proof_step(pcell);
|
s.push_proof_step(pcell);
|
||||||
buffer<expr> new_hs;
|
buffer<expr> new_hs;
|
||||||
|
@ -48,10 +48,10 @@ bool intros_action(unsigned max) {
|
||||||
}
|
}
|
||||||
pcell->m_new_hs = to_list(new_hs);
|
pcell->m_new_hs = to_list(new_hs);
|
||||||
s.set_target(target);
|
s.set_target(target);
|
||||||
return true;
|
return action_result::new_branch();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool intros_action() {
|
action_result intros_action() {
|
||||||
return intros_action(std::numeric_limits<unsigned>::max());
|
return intros_action(std::numeric_limits<unsigned>::max());
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -5,11 +5,13 @@ Released under Apache 2.0 license as described in the file LICENSE.
|
||||||
Author: Leonardo de Moura
|
Author: Leonardo de Moura
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include "library/blast/action_result.h"
|
||||||
namespace lean {
|
namespace lean {
|
||||||
namespace blast {
|
namespace blast {
|
||||||
/** \brief Introduce upto \c max hypotheses.
|
/** \brief Introduce upto \c max hypotheses.
|
||||||
Return false if there is nothing to introduce, that is, target is not a Pi-type. */
|
Return failed if there is nothing to introduce, that is, target is not a Pi-type.
|
||||||
bool intros_action(unsigned max);
|
\remark if max == 0, and it returns new_branch. */
|
||||||
|
action_result intros_action(unsigned max);
|
||||||
/** \brief Keep introducing until target is not a Pi-type. */
|
/** \brief Keep introducing until target is not a Pi-type. */
|
||||||
bool intros_action();
|
action_result intros_action();
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -7,7 +7,7 @@ Author: Leonardo de Moura
|
||||||
#include "kernel/instantiate.h"
|
#include "kernel/instantiate.h"
|
||||||
#include "kernel/inductive/inductive.h"
|
#include "kernel/inductive/inductive.h"
|
||||||
#include "library/user_recursors.h"
|
#include "library/user_recursors.h"
|
||||||
#include "library/blast/revert_action.h"
|
#include "library/blast/revert.h"
|
||||||
#include "library/blast/blast.h"
|
#include "library/blast/blast.h"
|
||||||
|
|
||||||
namespace lean {
|
namespace lean {
|
||||||
|
@ -174,7 +174,7 @@ action_result recursor_action(hypothesis_idx hidx, name const & R) {
|
||||||
s.collect_direct_forward_deps(hidx, to_revert);
|
s.collect_direct_forward_deps(hidx, to_revert);
|
||||||
for (auto i : indices)
|
for (auto i : indices)
|
||||||
s.collect_direct_forward_deps(href_index(i), to_revert);
|
s.collect_direct_forward_deps(href_index(i), to_revert);
|
||||||
revert_action(to_revert);
|
revert(to_revert);
|
||||||
|
|
||||||
expr target = s.get_target();
|
expr target = s.get_target();
|
||||||
auto target_level = get_type_context().get_level_core(target);
|
auto target_level = get_type_context().get_level_core(target);
|
||||||
|
@ -290,4 +290,40 @@ action_result recursor_action(hypothesis_idx hidx) {
|
||||||
}
|
}
|
||||||
return action_result::failed();
|
return action_result::failed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
action_result recursor_preprocess_action(hypothesis_idx hidx) {
|
||||||
|
if (optional<name> R = is_recursor_action_target(hidx)) {
|
||||||
|
unsigned num_minor = get_num_minor_premises(*R);
|
||||||
|
if (num_minor == 1) {
|
||||||
|
action_result r = recursor_action(hidx, *R);
|
||||||
|
if (!failed(r)) {
|
||||||
|
// if (!preprocess) display_action("recursor");
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// If the hypothesis recursor has more than 1 minor premise, we
|
||||||
|
// put it in a priority queue.
|
||||||
|
// TODO(Leo): refine
|
||||||
|
|
||||||
|
// TODO(Leo): the following weight computation is too simple...
|
||||||
|
double w = 1.0 / (static_cast<double>(hidx) + 1.0);
|
||||||
|
if (!is_recursive_recursor(*R)) {
|
||||||
|
// TODO(Leo): we need a better strategy for handling recursive recursors...
|
||||||
|
w += static_cast<double>(num_minor);
|
||||||
|
curr_state().add_to_rec_queue(hidx, w);
|
||||||
|
return action_result::new_branch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return action_result::failed();
|
||||||
|
}
|
||||||
|
|
||||||
|
action_result recursor_action() {
|
||||||
|
while (auto hidx = curr_state().select_rec_hypothesis()) {
|
||||||
|
if (optional<name> R = is_recursor_action_target(*hidx)) {
|
||||||
|
Try(recursor_action(*hidx, *R));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return action_result::failed();
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -9,13 +9,6 @@ Author: Leonardo de Moura
|
||||||
#include "library/blast/hypothesis.h"
|
#include "library/blast/hypothesis.h"
|
||||||
namespace lean {
|
namespace lean {
|
||||||
namespace blast {
|
namespace blast {
|
||||||
/** \brief Return the name of the recursor that can be used with the given hypothesis */
|
action_result recursor_preprocess_action(hypothesis_idx hidx);
|
||||||
optional<name> is_recursor_action_target(hypothesis_idx hidx);
|
action_result recursor_action();
|
||||||
|
|
||||||
/** \brief Return the number of minor premises of the given recursor */
|
|
||||||
unsigned get_num_minor_premises(name const & R);
|
|
||||||
bool is_recursive_recursor(name const & R);
|
|
||||||
|
|
||||||
action_result recursor_action(hypothesis_idx hidx, name const & R);
|
|
||||||
action_result recursor_action(hypothesis_idx hidx);
|
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
|
||||||
|
|
||||||
Author: Leonardo de Moura
|
Author: Leonardo de Moura
|
||||||
*/
|
*/
|
||||||
#include "library/blast/revert_action.h"
|
#include "library/blast/revert.h"
|
||||||
#include "library/blast/blast.h"
|
#include "library/blast/blast.h"
|
||||||
|
|
||||||
namespace lean {
|
namespace lean {
|
||||||
|
@ -23,7 +23,7 @@ struct revert_proof_step_cell : public proof_step_cell {
|
||||||
virtual bool is_silent() const override { return true; }
|
virtual bool is_silent() const override { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned revert_action(hypothesis_idx_buffer_set & hidxs) {
|
unsigned revert(hypothesis_idx_buffer_set & hidxs) {
|
||||||
state & s = curr_state();
|
state & s = curr_state();
|
||||||
unsigned hidxs_size = hidxs.as_buffer().size();
|
unsigned hidxs_size = hidxs.as_buffer().size();
|
||||||
for (unsigned i = 0; i < hidxs_size; i++) {
|
for (unsigned i = 0; i < hidxs_size; i++) {
|
||||||
|
@ -40,8 +40,8 @@ unsigned revert_action(hypothesis_idx_buffer_set & hidxs) {
|
||||||
return hidxs.as_buffer().size();
|
return hidxs.as_buffer().size();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned revert_action(buffer<hypothesis_idx> & hidxs) {
|
unsigned revert(buffer<hypothesis_idx> & hidxs) {
|
||||||
hypothesis_idx_buffer_set _hidxs(hidxs);
|
hypothesis_idx_buffer_set _hidxs(hidxs);
|
||||||
return revert_action(_hidxs);
|
return revert(_hidxs);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
|
@ -11,6 +11,6 @@ namespace lean {
|
||||||
namespace blast {
|
namespace blast {
|
||||||
/** \brief Revert the given hypotheses and their dependencies.
|
/** \brief Revert the given hypotheses and their dependencies.
|
||||||
Return the total number of hypotheses reverted. */
|
Return the total number of hypotheses reverted. */
|
||||||
unsigned revert_action(buffer<hypothesis_idx> & hidxs);
|
unsigned revert(buffer<hypothesis_idx> & hidxs);
|
||||||
unsigned revert_action(hypothesis_idx_buffer_set & hidxs);
|
unsigned revert(hypothesis_idx_buffer_set & hidxs);
|
||||||
}}
|
}}
|
|
@ -11,16 +11,16 @@ Author: Leonardo de Moura
|
||||||
namespace lean {
|
namespace lean {
|
||||||
namespace blast {
|
namespace blast {
|
||||||
// TODO(Leo): we should create choice points when there are meta-variables
|
// TODO(Leo): we should create choice points when there are meta-variables
|
||||||
optional<expr> assumption_action() {
|
action_result assumption_action() {
|
||||||
state const & s = curr_state();
|
state const & s = curr_state();
|
||||||
expr const & target = s.get_target();
|
expr const & target = s.get_target();
|
||||||
for (hypothesis_idx hidx : s.get_head_related()) {
|
for (hypothesis_idx hidx : s.get_head_related()) {
|
||||||
hypothesis const * h = s.get_hypothesis_decl(hidx);
|
hypothesis const * h = s.get_hypothesis_decl(hidx);
|
||||||
lean_assert(h);
|
lean_assert(h);
|
||||||
if (is_def_eq(h->get_type(), target))
|
if (is_def_eq(h->get_type(), target))
|
||||||
return some_expr(h->get_self());
|
return action_result(h->get_self());
|
||||||
}
|
}
|
||||||
return none_expr();
|
return action_result::failed();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Close branch IF h is of the form (H : a ~ a) where ~ is a reflexive relation */
|
/* Close branch IF h is of the form (H : a ~ a) where ~ is a reflexive relation */
|
||||||
|
@ -39,20 +39,20 @@ static optional<expr> try_not_refl_relation(hypothesis const & h) {
|
||||||
return none_expr();
|
return none_expr();
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<expr> assumption_contradiction_actions(hypothesis_idx hidx) {
|
action_result assumption_contradiction_actions(hypothesis_idx hidx) {
|
||||||
state const & s = curr_state();
|
state const & s = curr_state();
|
||||||
app_builder & b = get_app_builder();
|
app_builder & b = get_app_builder();
|
||||||
hypothesis const * h = s.get_hypothesis_decl(hidx);
|
hypothesis const * h = s.get_hypothesis_decl(hidx);
|
||||||
lean_assert(h);
|
lean_assert(h);
|
||||||
expr const & type = h->get_type();
|
expr const & type = h->get_type();
|
||||||
if (blast::is_false(type)) {
|
if (blast::is_false(type)) {
|
||||||
return some_expr(b.mk_false_rec(s.get_target(), h->get_self()));
|
return action_result(b.mk_false_rec(s.get_target(), h->get_self()));
|
||||||
}
|
}
|
||||||
if (is_def_eq(type, s.get_target())) {
|
if (is_def_eq(type, s.get_target())) {
|
||||||
return some_expr(h->get_self());
|
return action_result(h->get_self());
|
||||||
}
|
}
|
||||||
if (auto pr = try_not_refl_relation(*h))
|
if (auto pr = try_not_refl_relation(*h))
|
||||||
return pr;
|
return action_result(*pr);
|
||||||
expr p1 = type;
|
expr p1 = type;
|
||||||
bool is_neg1 = is_not(type, p1);
|
bool is_neg1 = is_not(type, p1);
|
||||||
/* try to find complement */
|
/* try to find complement */
|
||||||
|
@ -64,39 +64,39 @@ optional<expr> assumption_contradiction_actions(hypothesis_idx hidx) {
|
||||||
if (is_neg1 != is_neg2) {
|
if (is_neg1 != is_neg2) {
|
||||||
if (is_def_eq(p1, p2)) {
|
if (is_def_eq(p1, p2)) {
|
||||||
if (is_neg1) {
|
if (is_neg1) {
|
||||||
return some_expr(b.mk_app(get_absurd_name(), {s.get_target(), h2->get_self(), h->get_self()}));
|
return action_result(b.mk_app(get_absurd_name(), {s.get_target(), h2->get_self(), h->get_self()}));
|
||||||
} else {
|
} else {
|
||||||
lean_assert(is_neg2);
|
lean_assert(is_neg2);
|
||||||
return some_expr(b.mk_app(get_absurd_name(), {s.get_target(), h->get_self(), h2->get_self()}));
|
return action_result(b.mk_app(get_absurd_name(), {s.get_target(), h->get_self(), h2->get_self()}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return none_expr();
|
return action_result::failed();
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<expr> trivial_action() {
|
action_result trivial_action() {
|
||||||
try {
|
try {
|
||||||
state s = curr_state();
|
state s = curr_state();
|
||||||
expr target = s.get_target();
|
expr target = s.get_target();
|
||||||
/* ignore if target contains meta-variables */
|
/* ignore if target contains meta-variables */
|
||||||
if (has_expr_metavar(target))
|
if (has_expr_metavar(target))
|
||||||
return none_expr();
|
return action_result::failed();
|
||||||
|
|
||||||
/* true */
|
/* true */
|
||||||
if (target == mk_true()) {
|
if (target == mk_true()) {
|
||||||
return some_expr(mk_true_intro());
|
return action_result(mk_true_intro());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* a ~ a */
|
/* a ~ a */
|
||||||
name rop; expr lhs, rhs;
|
name rop; expr lhs, rhs;
|
||||||
if (is_relation_app(target, rop, lhs, rhs) && is_def_eq(lhs, rhs)) {
|
if (is_relation_app(target, rop, lhs, rhs) && is_def_eq(lhs, rhs)) {
|
||||||
return some_expr(get_app_builder().mk_refl(rop, lhs));
|
return action_result(get_app_builder().mk_refl(rop, lhs));
|
||||||
}
|
}
|
||||||
|
|
||||||
return none_expr();
|
return action_result::failed();
|
||||||
} catch (app_builder_exception &) {
|
} catch (app_builder_exception &) {
|
||||||
return none_expr();
|
return action_result::failed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,4 +129,13 @@ bool discard(hypothesis_idx hidx) {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
action_result discard_action(hypothesis_idx hidx) {
|
||||||
|
if (discard(hidx)) {
|
||||||
|
curr_state().del_hypothesis(hidx);
|
||||||
|
return action_result::new_branch();
|
||||||
|
} else {
|
||||||
|
return action_result::failed();
|
||||||
|
}
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -7,14 +7,15 @@ Author: Leonardo de Moura
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "kernel/expr.h"
|
#include "kernel/expr.h"
|
||||||
#include "library/blast/hypothesis.h"
|
#include "library/blast/hypothesis.h"
|
||||||
|
#include "library/blast/action_result.h"
|
||||||
namespace lean {
|
namespace lean {
|
||||||
namespace blast {
|
namespace blast {
|
||||||
optional<expr> assumption_action();
|
action_result assumption_action();
|
||||||
/** \brief Apply assumption and contradiction actions using the given hypothesis.
|
/** \brief Apply assumption and contradiction actions using the given hypothesis.
|
||||||
\remark This action is supposed to be applied when a hypothesis is activated. */
|
\remark This action is supposed to be applied when a hypothesis is activated. */
|
||||||
optional<expr> assumption_contradiction_actions(hypothesis_idx hidx);
|
action_result assumption_contradiction_actions(hypothesis_idx hidx);
|
||||||
/** \brief Solve trivial targets (e.g., true, a = a, a <-> a, etc). */
|
/** \brief Solve trivial targets (e.g., true, a = a, a <-> a, etc). */
|
||||||
optional<expr> trivial_action();
|
action_result trivial_action();
|
||||||
|
|
||||||
/** \brief Return true if the given hypothesis is "redundant". We consider a hypothesis
|
/** \brief Return true if the given hypothesis is "redundant". We consider a hypothesis
|
||||||
redundant if it is a proposition, no other hypothesis type depends on it,
|
redundant if it is a proposition, no other hypothesis type depends on it,
|
||||||
|
@ -30,5 +31,5 @@ optional<expr> trivial_action();
|
||||||
(well, it may be useful for the HoTT library).
|
(well, it may be useful for the HoTT library).
|
||||||
|
|
||||||
TODO(Leo): subsumption. 3 is just a very simple case of subsumption. */
|
TODO(Leo): subsumption. 3 is just a very simple case of subsumption. */
|
||||||
bool discard(hypothesis_idx hidx);
|
action_result discard_action(hypothesis_idx hidx);
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -25,54 +25,13 @@ class simple_strategy : public strategy {
|
||||||
action_result activate_hypothesis(bool preprocess) {
|
action_result activate_hypothesis(bool preprocess) {
|
||||||
auto hidx = curr_state().activate_hypothesis();
|
auto hidx = curr_state().activate_hypothesis();
|
||||||
if (!hidx) return action_result::failed();
|
if (!hidx) return action_result::failed();
|
||||||
|
|
||||||
if (!preprocess) display_action("activate");
|
if (!preprocess) display_action("activate");
|
||||||
|
|
||||||
if (auto pr = assumption_contradiction_actions(*hidx)) {
|
Try(assumption_contradiction_actions(*hidx));
|
||||||
if (!preprocess) display_action("assumption-contradiction");
|
Try(subst_action(*hidx));
|
||||||
return action_result::solved(*pr);
|
Try(no_confusion_action(*hidx));
|
||||||
}
|
Try(discard_action(*hidx));
|
||||||
|
Try(recursor_preprocess_action(*hidx));
|
||||||
if (subst_action(*hidx)) {
|
|
||||||
if (!preprocess) display_action("subst");
|
|
||||||
return action_result::new_branch();
|
|
||||||
}
|
|
||||||
|
|
||||||
action_result r = no_confusion_action(*hidx);
|
|
||||||
if (!failed(r)) {
|
|
||||||
if (!preprocess) display_action("no_confusion");
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (discard(*hidx)) {
|
|
||||||
if (!preprocess) display_action("discard redudant hypothesis");
|
|
||||||
curr_state().del_hypothesis(*hidx);
|
|
||||||
return action_result::new_branch();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (optional<name> R = is_recursor_action_target(*hidx)) {
|
|
||||||
unsigned num_minor = get_num_minor_premises(*R);
|
|
||||||
if (num_minor == 1) {
|
|
||||||
action_result r = recursor_action(*hidx, *R);
|
|
||||||
if (!failed(r)) {
|
|
||||||
if (!preprocess) display_action("recursor");
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// If the hypothesis recursor has more than 1 minor premise, we
|
|
||||||
// put it in a priority queue.
|
|
||||||
// TODO(Leo): refine
|
|
||||||
|
|
||||||
// TODO(Leo): the following weight computation is too simple...
|
|
||||||
double w = 1.0 / (static_cast<double>(*hidx) + 1.0);
|
|
||||||
if (!is_recursive_recursor(*R)) {
|
|
||||||
// TODO(Leo): we need a better strategy for handling recursive recursors...
|
|
||||||
w += static_cast<double>(num_minor);
|
|
||||||
curr_state().add_to_rec_queue(*hidx, w);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return action_result::new_branch();
|
return action_result::new_branch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,57 +41,24 @@ class simple_strategy : public strategy {
|
||||||
virtual optional<expr> preprocess() {
|
virtual optional<expr> preprocess() {
|
||||||
display_msg("* Preprocess");
|
display_msg("* Preprocess");
|
||||||
while (true) {
|
while (true) {
|
||||||
if (intros_action())
|
if (!failed(intros_action()))
|
||||||
continue;
|
continue;
|
||||||
auto r = activate_hypothesis(true);
|
auto r = activate_hypothesis(true);
|
||||||
if (solved(r)) return r.to_opt_expr();
|
if (solved(r)) return r.to_opt_expr();
|
||||||
if (failed(r)) break;
|
if (failed(r)) break;
|
||||||
}
|
}
|
||||||
if (auto pr = assumption_action())
|
TrySolve(assumption_action());
|
||||||
return pr;
|
TrySolve(simplify_target_action());
|
||||||
return simplify_target_action().to_opt_expr();
|
return none_expr();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual action_result next_action() {
|
virtual action_result next_action() {
|
||||||
if (intros_action()) {
|
Try(intros_action());
|
||||||
display_action("intros");
|
Try(activate_hypothesis(false));
|
||||||
return action_result::new_branch();
|
Try(trivial_action());
|
||||||
}
|
Try(assumption_action());
|
||||||
|
Try(recursor_action());
|
||||||
action_result r = activate_hypothesis(false);
|
Try(constructor_action());
|
||||||
if (!failed(r)) return r;
|
|
||||||
|
|
||||||
if (auto pr = trivial_action()) {
|
|
||||||
display_action("trivial");
|
|
||||||
return action_result::solved(*pr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto pr = assumption_action()) {
|
|
||||||
// Remark: this action is only relevant
|
|
||||||
// when the target has been modified.
|
|
||||||
display_action("assumption");
|
|
||||||
return action_result::solved(*pr);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (auto hidx = curr_state().select_rec_hypothesis()) {
|
|
||||||
if (optional<name> R = is_recursor_action_target(*hidx)) {
|
|
||||||
r = recursor_action(*hidx, *R);
|
|
||||||
if (!failed(r)) {
|
|
||||||
display_action("recursor");
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r = constructor_action();
|
|
||||||
if (!failed(r)) {
|
|
||||||
display_action("constructor");
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(Leo): add more actions...
|
|
||||||
|
|
||||||
display_msg(">>> FAILED <<<");
|
|
||||||
return action_result::failed();
|
return action_result::failed();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,7 +6,7 @@ Author: Leonardo de Moura
|
||||||
*/
|
*/
|
||||||
#include "kernel/abstract.h"
|
#include "kernel/abstract.h"
|
||||||
#include "kernel/instantiate.h"
|
#include "kernel/instantiate.h"
|
||||||
#include "library/blast/revert_action.h"
|
#include "library/blast/revert.h"
|
||||||
#include "library/blast/intros_action.h"
|
#include "library/blast/intros_action.h"
|
||||||
#include "library/blast/blast.h"
|
#include "library/blast/blast.h"
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ bool subst_core(hypothesis_idx hidx) {
|
||||||
to_revert,
|
to_revert,
|
||||||
[&](hypothesis_idx d) { return d != hidx; });
|
[&](hypothesis_idx d) { return d != hidx; });
|
||||||
s.collect_direct_forward_deps(hidx, to_revert);
|
s.collect_direct_forward_deps(hidx, to_revert);
|
||||||
unsigned num = revert_action(to_revert);
|
unsigned num = revert(to_revert);
|
||||||
expr target = s.get_target();
|
expr target = s.get_target();
|
||||||
expr new_target = abstract(target, h->get_self());
|
expr new_target = abstract(target, h->get_self());
|
||||||
bool dep = !closed(new_target);
|
bool dep = !closed(new_target);
|
||||||
|
@ -84,7 +84,7 @@ bool subst_core(hypothesis_idx hidx) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool subst_action(hypothesis_idx hidx) {
|
action_result subst_action(hypothesis_idx hidx) {
|
||||||
state & s = curr_state();
|
state & s = curr_state();
|
||||||
app_builder & b = get_app_builder();
|
app_builder & b = get_app_builder();
|
||||||
hypothesis const * h = s.get_hypothesis_decl(hidx);
|
hypothesis const * h = s.get_hypothesis_decl(hidx);
|
||||||
|
@ -92,14 +92,14 @@ bool subst_action(hypothesis_idx hidx) {
|
||||||
expr type = h->get_type();
|
expr type = h->get_type();
|
||||||
expr lhs, rhs;
|
expr lhs, rhs;
|
||||||
if (!is_eq(type, lhs, rhs))
|
if (!is_eq(type, lhs, rhs))
|
||||||
return false;
|
return action_result::failed();
|
||||||
if (is_href(rhs)) {
|
if (is_href(rhs)) {
|
||||||
return subst_core(hidx);
|
return action_result(subst_core(hidx));
|
||||||
} else if (is_href(lhs)) {
|
} else if (is_href(lhs)) {
|
||||||
if (s.has_forward_deps(href_index(lhs))) {
|
if (s.has_forward_deps(href_index(lhs))) {
|
||||||
// TODO(Leo): we don't handle this case yet.
|
// TODO(Leo): we don't handle this case yet.
|
||||||
// Other hypotheses depend on this equality.
|
// Other hypotheses depend on this equality.
|
||||||
return false;
|
return action_result::failed();
|
||||||
}
|
}
|
||||||
state saved = s;
|
state saved = s;
|
||||||
try {
|
try {
|
||||||
|
@ -107,17 +107,17 @@ bool subst_action(hypothesis_idx hidx) {
|
||||||
expr new_pr = b.mk_eq_symm(h->get_self());
|
expr new_pr = b.mk_eq_symm(h->get_self());
|
||||||
expr new_href = s.mk_hypothesis(new_eq, new_pr);
|
expr new_href = s.mk_hypothesis(new_eq, new_pr);
|
||||||
if (subst_core(href_index(new_href))) {
|
if (subst_core(href_index(new_href))) {
|
||||||
return true;
|
return action_result::new_branch();
|
||||||
} else {
|
} else {
|
||||||
s = saved;
|
s = saved;
|
||||||
return false;
|
return action_result::failed();
|
||||||
}
|
}
|
||||||
} catch (app_builder_exception &) {
|
} catch (app_builder_exception &) {
|
||||||
s = saved;
|
s = saved;
|
||||||
return false;
|
return action_result::failed();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return action_result::failed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -9,6 +9,6 @@ Author: Leonardo de Moura
|
||||||
namespace lean {
|
namespace lean {
|
||||||
namespace blast {
|
namespace blast {
|
||||||
/** \brief If the given hypothesis is of the form (H : t = x) or (H : x = s), then
|
/** \brief If the given hypothesis is of the form (H : t = x) or (H : x = s), then
|
||||||
eliminate x (and H). Return true if success. */
|
eliminate x (and H). */
|
||||||
bool subst_action(hypothesis_idx hidx);
|
action_result subst_action(hypothesis_idx hidx);
|
||||||
}}
|
}}
|
||||||
|
|
Loading…
Reference in a new issue