This makes TheoryUF use a standard theory inference manager, which thus makes it proof producing when proof-new is enabled.
This additionally cleans HoExtension so that it does not keep a backwards reference to TheoryUF and instead takes its inference manager. This additionally adds two rules for higher-order that are required to make its equality engine proofs correct.
Co-authored-by: Haniel Barbosa <hanielbbarbosa@gmail.com>
case PfRule::TRUE_ELIM: return "TRUE_ELIM";
case PfRule::FALSE_INTRO: return "FALSE_INTRO";
case PfRule::FALSE_ELIM: return "FALSE_ELIM";
+ case PfRule::HO_APP_ENCODE: return "HO_APP_ENCODE";
+ case PfRule::HO_CONG: return "HO_CONG";
//================================================= Quantifiers rules
case PfRule::WITNESS_INTRO: return "WITNESS_INTRO";
case PfRule::EXISTS_INTRO: return "EXISTS_INTRO";
// ----------------------------------------
// Conclusion: (not F)
FALSE_ELIM,
+ // ======== HO trust
+ // Children: none
+ // Arguments: (t)
+ // ---------------------
+ // Conclusion: (= t TheoryUfRewriter::getHoApplyForApplyUf(t))
+ // For example, this rule concludes (f x y) = (HO_APPLY (HO_APPLY f x) y)
+ HO_APP_ENCODE,
+ // ======== Congruence
+ // Children: (P1:(= f g), P2:(= t1 s1), ..., Pn+1:(= tn sn))
+ // Arguments: ()
+ // ---------------------------------------------
+ // Conclusion: (= (f t1 ... tn) (g s1 ... sn))
+ // Notice that this rule is only used when the application kinds are APPLY_UF.
+ HO_CONG,
//================================================= Quantifiers rules
// ======== Witness intro
#include "expr/node_algorithm.h"
#include "options/uf_options.h"
#include "theory/theory_model.h"
-#include "theory/uf/theory_uf.h"
#include "theory/uf/theory_uf_rewriter.h"
using namespace std;
namespace theory {
namespace uf {
-HoExtension::HoExtension(TheoryUF& p, TheoryState& state)
- : d_parent(p),
- d_state(state),
+HoExtension::HoExtension(TheoryState& state, TheoryInferenceManager& im)
+ : d_state(state),
+ d_im(im),
d_extensionality(state.getUserContext()),
d_uf_std_skolem(state.getUserContext())
{
Node lem = NodeManager::currentNM()->mkNode(OR, deq[0], conc);
Trace("uf-ho-lemma") << "uf-ho-lemma : extensionality : " << lem
<< std::endl;
- d_parent.getOutputChannel().lemma(lem);
+ d_im.lemma(lem);
return 1;
}
return 0;
Trace("uf-ho-lemma")
<< "uf-ho-lemma : Skolem definition for apply-conversion : " << lem
<< std::endl;
- d_parent.getOutputChannel().lemma(lem);
+ d_im.lemma(lem);
d_uf_std_skolem[f] = new_f;
}
else
Node lem = nm->mkNode(OR, deq.negate(), eq);
Trace("uf-ho") << "HoExtension: cmi extensionality lemma " << lem
<< std::endl;
- d_parent.getOutputChannel().lemma(lem);
+ d_im.lemma(lem);
return 1;
}
}
Node ret = TheoryUfRewriter::getHoApplyForApplyUf(n);
if (!ee->hasTerm(ret) || !ee->areEqual(ret, n))
{
- Node eq = ret.eqNode(n);
+ Node eq = n.eqNode(ret);
Trace("uf-ho-lemma") << "uf-ho-lemma : infer, by apply-expand : " << eq
<< std::endl;
- ee->assertEquality(eq, true, d_true);
+ d_im.assertInternalFact(eq, true, PfRule::HO_APP_ENCODE, {}, {n});
return 1;
}
Trace("uf-ho-debug") << " ...already have " << ret << " == " << n << "."
Node eq = n.eqNode(hn);
Trace("uf-ho") << "HoExtension: cmi app completion lemma " << eq
<< std::endl;
- d_parent.getOutputChannel().lemma(eq);
+ d_im.lemma(eq);
return false;
}
}
#include "context/cdhashset.h"
#include "context/cdo.h"
#include "expr/node.h"
+#include "theory/theory_inference_manager.h"
#include "theory/theory_model.h"
#include "theory/theory_state.h"
typedef context::CDHashMap<Node, Node, NodeHashFunction> NodeNodeMap;
public:
- HoExtension(TheoryUF& p, TheoryState& state);
+ HoExtension(TheoryState& state, TheoryInferenceManager& im);
/** expand definition
*
private:
/** common constants */
Node d_true;
- /** the parent of this extension */
- TheoryUF& d_parent;
/** Reference to the state object */
TheoryState& d_state;
+ /** Reference to the inference manager */
+ TheoryInferenceManager& d_im;
/** extensionality has been applied to these disequalities */
NodeSet d_extensionality;
#include "theory/uf/proof_checker.h"
+#include "theory/uf/theory_uf_rewriter.h"
+
using namespace CVC4::kind;
namespace CVC4 {
pc->registerChecker(PfRule::TRUE_ELIM, this);
pc->registerChecker(PfRule::FALSE_INTRO, this);
pc->registerChecker(PfRule::FALSE_ELIM, this);
+ pc->registerChecker(PfRule::HO_CONG, this);
+ pc->registerChecker(PfRule::HO_APP_ENCODE, this);
}
Node UfProofRuleChecker::checkInternal(PfRule id,
}
return children[0][0].notNode();
}
+ if (id == PfRule::HO_CONG)
+ {
+ Assert(children.size() > 0);
+ std::vector<Node> lchildren;
+ std::vector<Node> rchildren;
+ for (size_t i = 0, nchild = children.size(); i < nchild; ++i)
+ {
+ Node eqp = children[i];
+ if (eqp.getKind() != EQUAL)
+ {
+ return Node::null();
+ }
+ lchildren.push_back(eqp[0]);
+ rchildren.push_back(eqp[1]);
+ }
+ NodeManager* nm = NodeManager::currentNM();
+ Node l = nm->mkNode(kind::APPLY_UF, lchildren);
+ Node r = nm->mkNode(kind::APPLY_UF, rchildren);
+ return l.eqNode(r);
+ }
+ else if (id == PfRule::HO_APP_ENCODE)
+ {
+ Assert(args.size() == 1);
+ Node ret = TheoryUfRewriter::getHoApplyForApplyUf(args[0]);
+ return args[0].eqNode(ret);
+ }
// no rule
return Node::null();
}
d_ho(nullptr),
d_functionsTerms(c),
d_symb(u, instanceName),
- d_state(c, u, valuation)
+ d_state(c, u, valuation),
+ d_im(*this, d_state, pnm)
{
d_true = NodeManager::currentNM()->mkConst( true );
{
d_ufProofChecker.registerTo(pc);
}
- // indicate we are using the default theory state object
+ // indicate we are using the default theory state and inference managers
d_theoryState = &d_state;
+ d_inferManager = &d_im;
}
TheoryUF::~TheoryUF() {
if (options::ufHo())
{
d_equalityEngine->addFunctionKind(kind::HO_APPLY);
- d_ho.reset(new HoExtension(*this, d_state));
+ d_ho.reset(new HoExtension(d_state, d_im));
}
}
exp = mkAnd(assumptions);
}
-TrustNode TheoryUF::explain(TNode literal)
-{
- Node explanation;
- explain(literal, explanation);
- return TrustNode::mkTrustPropExp(literal, explanation, nullptr);
-}
+TrustNode TheoryUF::explain(TNode literal) { return d_im.explainLit(literal); }
bool TheoryUF::collectModelValues(TheoryModel* m, const std::set<Node>& termSet)
{
i != newClauses.end();
++i) {
Debug("uf") << "uf: generating a lemma: " << *i << std::endl;
- d_out->lemma(*i);
+ // no proof generator provided
+ d_im.lemma(*i);
}
}
if( d_thss ){
void TheoryUF::conflict(TNode a, TNode b)
{
- Node conf;
- explain(a.eqNode(b), conf);
- d_out->conflict(conf);
- d_state.notifyInConflict();
+ // call the inference manager, which will construct the conflict (possibly
+ // with proofs from the underlying proof equality engine), and notify the
+ // state object.
+ d_im.conflictEqConstantMerge(a, b);
}
void TheoryUF::eqNotifyNewClass(TNode t) {
#include "theory/theory.h"
#include "theory/uf/equality_engine.h"
#include "theory/uf/proof_checker.h"
+#include "theory/uf/proof_equality_engine.h"
#include "theory/uf/symmetry_breaker.h"
#include "theory/uf/theory_uf_rewriter.h"
UfProofRuleChecker d_ufProofChecker;
/** A (default) theory state object */
TheoryState d_state;
+ /** A (default) inference manager */
+ TheoryInferenceManager d_im;
};/* class TheoryUF */
}/* CVC4::theory::uf namespace */
#include "expr/node_algorithm.h"
#include "options/uf_options.h"
+#include "theory/rewriter.h"
#include "theory/substitutions.h"
#include "theory/theory_rewriter.h"