feat(library/blast): add action based on congruence closure module

This commit is contained in:
Leonardo de Moura 2015-11-19 12:20:40 -08:00
parent 6bd92e144a
commit ee3083c12c
8 changed files with 91 additions and 6 deletions

View file

@ -3,4 +3,4 @@ add_library(blast OBJECT expr.cpp state.cpp blast.cpp blast_tactic.cpp
options.cpp choice_point.cpp simple_strategy.cpp util.cpp
gexpr.cpp revert.cpp subst_action.cpp no_confusion_action.cpp
simplify_actions.cpp strategy.cpp recursor_action.cpp congruence_closure.cpp
trace.cpp)
trace.cpp assert_cc_action.cpp)

View file

@ -36,5 +36,6 @@ inline bool failed(action_result const & r) { return r.get_kind() == action_resu
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(); }
#define TrySolve(Code) { action_result r = Code; if (solved(r)) return r; }
#define TrySolveToOptExpr(Code) { action_result r = Code; if (solved(r)) return r.to_opt_expr(); }
}}

View file

@ -0,0 +1,61 @@
/*
Copyright (c) 2015 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura
*/
#include "library/blast/assert_cc_action.h"
#include "library/blast/congruence_closure.h"
#include "library/blast/blast.h"
#include "library/blast/trace.h"
namespace lean {
namespace blast {
static unsigned g_ext_id = 0;
struct cc_branch_extension : public branch_extension {
congruence_closure m_cc;
cc_branch_extension() {}
cc_branch_extension(cc_branch_extension const & o):m_cc(o.m_cc) {}
virtual ~cc_branch_extension() {}
virtual branch_extension * clone() { return new cc_branch_extension(*this); }
};
void initialize_assert_cc_action() {
g_ext_id = register_branch_extension(new cc_branch_extension());
}
void finalize_assert_cc_action() {}
static congruence_closure & get_cc() {
return static_cast<cc_branch_extension&>(curr_state().get_extension(g_ext_id)).m_cc;
}
action_result assert_cc_action(hypothesis_idx hidx) {
congruence_closure & cc = get_cc();
cc.add(hidx);
if (cc.is_inconsistent()) {
try {
app_builder & b = get_app_builder();
expr false_proof = *cc.get_inconsistency_proof();
trace_action("contradiction by congruence closure");
return action_result(b.mk_false_rec(curr_state().get_target(), false_proof));
} catch (app_builder_exception &) {
return action_result::failed();
}
} else {
expr const & target = curr_state().get_target();
name R; expr lhs, rhs;
if (is_relation_app(target, R, lhs, rhs) && cc.is_eqv(R, lhs, rhs)) {
expr proof = *cc.get_eqv_proof(R, lhs, rhs);
trace_action("equivalence by congruence closure");
return action_result(proof);
} else if (is_prop(target) && !is_false(target) && cc.proved(target)) {
expr proof = *cc.get_proof(target);
trace_action("equivalent to true by congruence closure");
return action_result(proof);
} else {
return action_result::new_branch();
}
}
}
}}

View file

@ -0,0 +1,18 @@
/*
Copyright (c) 2015 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura
*/
#pragma once
#include "library/blast/action_result.h"
#include "library/blast/hypothesis.h"
namespace lean {
namespace blast {
/** \brief Assert the given hypothesis into the congruence closure module */
action_result assert_cc_action(hypothesis_idx hidx);
void initialize_assert_cc_action();
void finalize_assert_cc_action();
}}

View file

@ -327,7 +327,7 @@ optional<expr> congruence_closure::get_inconsistency_proof() const {
}
}
bool congruence_closure::prove(expr const & e) const {
bool congruence_closure::proved(expr const & e) const {
return is_eqv(get_iff_name(), e, mk_true());
}

View file

@ -140,7 +140,7 @@ public:
optional<expr> get_uneqv_proof(name const & R, expr const & e1, expr const & e2) const;
/** \brief Return true iff \c e has been proved by this module. That is, the proposition \c e is inhabited */
bool prove(expr const & e) const;
bool proved(expr const & e) const;
optional<expr> get_proof(expr const & e) const;
/** \brief Return true iff \c (not e) has been proved by this module. That is, the proposition \c (not e) is inhabited */

View file

@ -11,6 +11,7 @@ Author: Leonardo de Moura
#include "library/blast/simplifier.h"
#include "library/blast/options.h"
#include "library/blast/recursor_action.h"
#include "library/blast/assert_cc_action.h"
#include "library/blast/backward/init_module.h"
#include "library/blast/forward/init_module.h"
@ -25,8 +26,10 @@ void initialize_blast_module() {
blast::initialize_forward_module();
initialize_blast_tactic();
blast::initialize_recursor_action();
blast::initialize_assert_cc_action();
}
void finalize_blast_module() {
blast::finalize_assert_cc_action();
blast::finalize_recursor_action();
finalize_blast_tactic();
blast::finalize_forward_module();

View file

@ -17,6 +17,7 @@ Author: Leonardo de Moura
#include "library/blast/no_confusion_action.h"
#include "library/blast/simplify_actions.h"
#include "library/blast/recursor_action.h"
#include "library/blast/assert_cc_action.h"
#include "library/blast/strategy.h"
#include "library/blast/trace.h"
@ -38,6 +39,7 @@ class simple_strategy : public strategy {
Try(discard_action(*hidx));
Try(forward_action(*hidx));
Try(recursor_preprocess_action(*hidx));
TrySolve(assert_cc_action(*hidx));
return action_result::new_branch();
}
@ -57,8 +59,8 @@ class simple_strategy : public strategy {
if (solved(r)) return r.to_opt_expr();
if (failed(r)) break;
}
TrySolve(assumption_action());
TrySolve(simplify_target_action());
TrySolveToOptExpr(assumption_action());
TrySolveToOptExpr(simplify_target_action());
return none_expr();
}