This enables default support for equality proofs in the theory of sets.
This is in preparation for proofs in the central equality engine, which requires that all active theories that use the central equality engine at least support the default interaction with the equality engine.
case PfRule::TRUST_SUBS: return "TRUST_SUBS";
case PfRule::TRUST_SUBS_MAP: return "TRUST_SUBS_MAP";
case PfRule::TRUST_SUBS_EQ: return "TRUST_SUBS_EQ";
+ case PfRule::THEORY_INFERENCE: return "THEORY_INFERENCE";
//================================================= Boolean rules
case PfRule::RESOLUTION: return "RESOLUTION";
case PfRule::CHAIN_RESOLUTION: return "CHAIN_RESOLUTION";
// where F is a solved equality of the form (= x t) derived as the solved
// form of F', where F' is given as a child.
TRUST_SUBS_EQ,
+ // where F is a fact derived by a theory-specific inference
+ THEORY_INFERENCE,
// ========= SAT Refutation for assumption-based unsat cores
// Children: (P1, ..., Pn)
// Arguments: none
pc->registerTrustedChecker(PfRule::TRUST_SUBS, this, 1);
pc->registerTrustedChecker(PfRule::TRUST_SUBS_MAP, this, 1);
pc->registerTrustedChecker(PfRule::TRUST_SUBS_EQ, this, 3);
+ pc->registerTrustedChecker(PfRule::THEORY_INFERENCE, this, 3);
}
Node BuiltinProofRuleChecker::applySubstitutionRewrite(
|| id == PfRule::THEORY_EXPAND_DEF || id == PfRule::WITNESS_AXIOM
|| id == PfRule::THEORY_LEMMA || id == PfRule::THEORY_REWRITE
|| id == PfRule::TRUST_REWRITE || id == PfRule::TRUST_SUBS
- || id == PfRule::TRUST_SUBS_MAP || id == PfRule::TRUST_SUBS_EQ)
+ || id == PfRule::TRUST_SUBS_MAP || id == PfRule::TRUST_SUBS_EQ
+ || id == PfRule::THEORY_INFERENCE)
{
// "trusted" rules
Assert(!args.empty());
case InferenceId::SEP_DISTINCT_REF: return "SEP_DISTINCT_REF";
case InferenceId::SEP_REF_BOUND: return "SEP_REF_BOUND";
+ case InferenceId::SETS_CG_SPLIT: return "SETS_CG_SPLIT";
case InferenceId::SETS_COMPREHENSION: return "SETS_COMPREHENSION";
case InferenceId::SETS_DEQ: return "SETS_DEQ";
case InferenceId::SETS_DOWN_CLOSURE: return "SETS_DOWN_CLOSURE";
+ case InferenceId::SETS_EQ_CONFLICT: return "SETS_EQ_CONFLICT";
case InferenceId::SETS_EQ_MEM: return "SETS_EQ_MEM";
case InferenceId::SETS_EQ_MEM_CONFLICT: return "SETS_EQ_MEM_CONFLICT";
case InferenceId::SETS_MEM_EQ: return "SETS_MEM_EQ";
// ---------------------------------- sets theory
//-------------------- sets core solver
+ // split when computing care graph
+ SETS_CG_SPLIT,
SETS_COMPREHENSION,
SETS_DEQ,
SETS_DOWN_CLOSURE,
+ // conflict when two singleton/emptyset terms merge
+ SETS_EQ_CONFLICT,
SETS_EQ_MEM,
SETS_EQ_MEM_CONFLICT,
SETS_MEM_EQ,
|| (atom.getKind() == EQUAL && atom[0].getType().isSet()))
{
// send to equality engine
- if (assertInternalFact(atom, polarity, id, exp))
+ if (assertSetsFact(atom, polarity, id, exp))
{
// return true if this wasn't redundant
return true;
}
return false;
}
+
+bool InferenceManager::assertSetsFact(Node atom,
+ bool polarity,
+ InferenceId id,
+ Node exp)
+{
+ Node conc = polarity ? atom : atom.notNode();
+ return assertInternalFact(
+ atom, polarity, id, PfRule::THEORY_INFERENCE, {exp}, {conc});
+}
+
void InferenceManager::assertInference(Node fact,
InferenceId id,
Node exp,
InferenceId id,
std::vector<Node>& exp,
int inferType = 0);
+ /**
+ * Immediately assert an internal fact with the default handling of proofs.
+ */
+ bool assertSetsFact(Node atom, bool polarity, InferenceId id, Node exp);
/** flush the splitting lemma ( n OR (NOT n) )
*
: Theory(THEORY_SETS, c, u, out, valuation, logicInfo, pnm),
d_skCache(),
d_state(c, u, valuation, d_skCache),
- d_im(*this, d_state, nullptr),
+ d_im(*this, d_state, pnm),
d_internal(new TheorySetsPrivate(*this, d_state, d_im, d_skCache, pnm)),
d_notify(*d_internal.get(), d_im)
{
// infer equality between elements of singleton
Node exp = s1.eqNode(s2);
Node eq = s1[0].eqNode(s2[0]);
- d_im.assertInternalFact(eq, true, InferenceId::SETS_SINGLETON_EQ, exp);
+ d_im.assertSetsFact(eq, true, InferenceId::SETS_SINGLETON_EQ, exp);
}
else
{
// singleton equal to emptyset, conflict
Trace("sets-prop")
<< "Propagate conflict : " << s1 << " == " << s2 << std::endl;
- d_im.conflictEqConstantMerge(s1, s2);
+ Node eqs = s1.eqNode(s2);
+ d_im.conflict(eqs, InferenceId::SETS_EQ_CONFLICT);
return;
}
}
Assert(f.getKind() == kind::IMPLIES);
Trace("sets-prop") << "Propagate eq-mem eq inference : " << f[0] << " => "
<< f[1] << std::endl;
- d_im.assertInternalFact(f[1], true, InferenceId::SETS_EQ_MEM, f[0]);
+ d_im.assertSetsFact(f[1], true, InferenceId::SETS_EQ_MEM, f[0]);
}
}
}
Trace("sets-prop") << "Propagate mem-eq : " << pexp << std::endl;
Node eq = s[0].eqNode(atom[0]);
// triggers an internal inference
- d_im.assertInternalFact(eq, true, InferenceId::SETS_MEM_EQ, pexp);
+ d_im.assertSetsFact(eq, true, InferenceId::SETS_MEM_EQ, pexp);
}
}
else
{
Trace("sets-cg-lemma")
<< "Should split on : " << x << "==" << y << std::endl;
- d_im.split(x.eqNode(y), InferenceId::UNKNOWN);
+ d_im.split(x.eqNode(y), InferenceId::SETS_CG_SPLIT);
}
}
}
Assert(d_ee != nullptr);
Trace("infer-manager") << "TheoryInferenceManager::assertInternalFact: "
<< (pol ? Node(atom) : atom.notNode()) << " from "
- << expn << std::endl;
+ << expn << " / " << iid << " " << id << std::endl;
if (Configuration::isAssertionBuild())
{
// check that all facts hold in the equality engine, to ensure that we
}
d_numCurrentFacts++;
// Now, assert the fact. How to do so depends on whether proofs are enabled.
- // If no proof production, or no proof rule was given
bool ret = false;
- if (d_pfee == nullptr || id == PfRule::UNKNOWN)
+ if (d_pfee == nullptr)
{
+ Trace("infer-manager") << "...assert without proofs..." << std::endl;
if (atom.getKind() == kind::EQUAL)
{
ret = d_ee->assertEquality(atom, pol, expn);
}
else
{
+ Assert(id != PfRule::UNKNOWN);
+ Trace("infer-manager") << "...assert with proofs..." << std::endl;
// Note that we reconstruct the original literal lit here, since both the
// original literal is needed for bookkeeping proofs. It is possible to
// optimize this so that a few less nodes are created, but at the cost
// call the notify fact method with isInternal = true
d_theory.notifyFact(atom, pol, expn, true);
Trace("infer-manager")
- << "TheoryInferenceManager::finished assertInternalFact" << std::endl;
+ << "TheoryInferenceManager::finished assertInternalFact, ret=" << ret
+ << std::endl;
return ret;
}
* Theory's preNotifyFact and notifyFact method have been called with
* isInternal = true.
*
+ * Note this method should never be used when proofs are enabled.
+ *
* @param atom The atom of the fact to assert
* @param pol Its polarity
* @param exp Its explanation, i.e. ( exp => (~) atom ) is valid.