(proof-new) Fix missing connection in trust substitution proofs (#6685)
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>
Mon, 7 Jun 2021 17:44:20 +0000 (12:44 -0500)
committerGitHub <noreply@github.com>
Mon, 7 Jun 2021 17:44:20 +0000 (17:44 +0000)
This PR fixes a missing connection in trust substitution proofs, which was the cause of open proofs when solved equalities from ppAssert were not justified by proofs.

Also distinguishes TRUST_SUBS_EQ from TRUST_SUBS_MAP for clarity.

src/proof/proof_rule.cpp
src/proof/proof_rule.h
src/theory/builtin/proof_checker.cpp
src/theory/theory.h
src/theory/trust_substitutions.cpp
test/regress/CMakeLists.txt
test/regress/regress0/bv/core/bitvec1.smtv1.smt2
test/regress/regress0/bv/core/bitvec3.smtv1.smt2
test/regress/regress0/bv/core/constant_core.smt2
test/regress/regress0/cores/issue3455.smt2
test/regress/regress0/proofs/trust-subs-eq-open.smt2 [new file with mode: 0644]

index 0cefe1209e1ed7f10e8e7e32723995723b39445a..676fa6a63e377265f2e504630b4f11e0626dfc94 100644 (file)
@@ -46,6 +46,7 @@ const char* toString(PfRule id)
     case PfRule::TRUST_REWRITE: return "TRUST_REWRITE";
     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";
     //================================================= Boolean rules
     case PfRule::RESOLUTION: return "RESOLUTION";
     case PfRule::CHAIN_RESOLUTION: return "CHAIN_RESOLUTION";
index 107285cc3a08ed340e45d6b966cc012ddf77c480..a42b3077345393947bd5c332382ad1bc8e0a2c5e 100644 (file)
@@ -219,11 +219,13 @@ enum class PfRule : uint32_t
   THEORY_REWRITE,
   // The remaining rules in this section have the signature of a "trusted rule":
   //
-  // Children: none
+  // Children: ?
   // Arguments: (F)
   // ---------------------------------------------------------------
   // Conclusion: F
   //
+  // Unless stated below, the expected children vector of the rule is empty.
+  //
   // where F is an equality of the form t = t' where t was replaced by t'
   // based on some preprocessing pass, or otherwise F was added as a new
   // assertion by some preprocessing pass.
@@ -248,8 +250,13 @@ enum class PfRule : uint32_t
   // could not be replayed during proof postprocessing.
   TRUST_SUBS,
   // where F is an equality (= t t') that holds by a form of substitution that
-  // could not be determined by the TrustSubstitutionMap.
+  // could not be determined by the TrustSubstitutionMap. This inference may
+  // contain possibly multiple children corresponding to the formulas used to
+  // derive the substitution.
   TRUST_SUBS_MAP,
+  // 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,
   // ========= SAT Refutation for assumption-based unsat cores
   // Children: (P1, ..., Pn)
   // Arguments: none
index 7ec0525c9048d9bb27ed9a0f552f1ca8f864bf84..dae3922e682acc40391e7a0e56f778e66ee40f43 100644 (file)
@@ -52,6 +52,7 @@ void BuiltinProofRuleChecker::registerTo(ProofChecker* pc)
   pc->registerTrustedChecker(PfRule::TRUST_REWRITE, this, 1);
   pc->registerTrustedChecker(PfRule::TRUST_SUBS, this, 1);
   pc->registerTrustedChecker(PfRule::TRUST_SUBS_MAP, this, 1);
+  pc->registerTrustedChecker(PfRule::TRUST_SUBS_EQ, this, 3);
 }
 
 Node BuiltinProofRuleChecker::applySubstitutionRewrite(
@@ -399,7 +400,7 @@ Node BuiltinProofRuleChecker::checkInternal(PfRule id,
            || 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_MAP || id == PfRule::TRUST_SUBS_EQ)
   {
     // "trusted" rules
     Assert(!args.empty());
index d71348ce3a865b8f39977bda24877e1f335892f7..378305c75d4bf48cdacd20eb01dea23107707e09 100644 (file)
@@ -675,8 +675,8 @@ class Theory {
    * add the solved substitutions to the map, if any. The method should return
    * true if the literal can be safely removed from the input problem.
    *
-   * Note that tin has trude node kind LEMMA. Its proof generator should be
-   * take into account when adding a substitution to outSubstitutions when
+   * Note that tin has trust node kind LEMMA. Its proof generator should be
+   * taken into account when adding a substitution to outSubstitutions when
    * proofs are enabled.
    */
   virtual PPAssertStatus ppAssert(TrustNode tin,
index 7a2fb19bd4a6449bb781e8f93c485f05da10a6f4..7934231b9f9b6ab28811cbd50a8eaa214643a193 100644 (file)
@@ -115,11 +115,10 @@ ProofGenerator* TrustSubstitutionMap::addSubstitutionSolved(TNode x,
   // Try to transform tn.getProven() to (= x t) here, if necessary
   if (!d_tspb->applyPredTransform(proven, eq, {}))
   {
-    // failed to rewrite, it is critical for unsat cores that proven is a
-    // premise here, since the conclusion depends on it
-    addSubstitution(x, t, PfRule::TRUST_SUBS_MAP, {proven}, {eq});
-    Trace("trust-subs") << "...failed to rewrite" << std::endl;
-    return nullptr;
+    // failed to rewrite, we add a trust step which assumes eq is provable
+    // from proven, and proceed as normal.
+    Trace("trust-subs") << "...failed to rewrite " << proven << std::endl;
+    d_tspb->addStep(PfRule::TRUST_SUBS_EQ, {proven}, {eq}, eq);
   }
   Trace("trust-subs") << "...successful rewrite" << std::endl;
   solvePg->addSteps(*d_tspb.get());
index 237ca77ddfdd0ef141acbb09bcfeb3790cfc141a..20784051650b666cab5621731ceae7333cbfa656 100644 (file)
@@ -806,6 +806,7 @@ set(regress_0_tests
   regress0/printer/tuples_and_records.cvc
   regress0/proofs/issue277-circuit-propagator.smt2
   regress0/proofs/scope.smt2
+  regress0/proofs/trust-subs-eq-open.smt2
   regress0/push-pop/boolean/fuzz_12.smt2
   regress0/push-pop/boolean/fuzz_13.smt2
   regress0/push-pop/boolean/fuzz_14.smt2
index 78dd44d66c799fc23f457d024e97da6e3708d731..63273b899f021e3da0b695151c050a5e3aee0910 100644 (file)
@@ -1,4 +1,4 @@
-; COMMAND-LINE:  --no-check-proofs
+; COMMAND-LINE:
 ; EXPECT: unsat
 (set-option :incremental false)
 (set-info :source "Hand-crafted bit-vector benchmarks.  Some are from the SVC benchmark suite.
index b149c05705b1988bb8c09fc3560fa1dadc2ab64b..79af1ce94f6cb889bb899e6ae8b9910f51a538ea 100644 (file)
@@ -1,4 +1,4 @@
-; COMMAND-LINE:  --no-check-proofs
+; COMMAND-LINE:
 ; EXPECT: unsat
 (set-option :incremental false)
 (set-info :source "Hand-crafted bit-vector benchmarks.  Some are from the SVC benchmark suite.
index f9d2e022d13cbe48e03f572299dbe72a7fa8ed37..e433e58e220bac030bea78073cfa07f20254ea46 100644 (file)
@@ -1,4 +1,4 @@
-; COMMAND-LINE:  --no-check-proofs
+; COMMAND-LINE:
 ; EXPECT: unsat
 (set-logic QF_BV)
 (set-info :smt-lib-version 2.6)
index ec72daa32bd06909c7719b0c758aa196a05045cb..7050e8c7dd58120981e00077b86a13dc69d80d6f 100644 (file)
@@ -13,4 +13,4 @@
 (assert (<= x0 (- 13)))
 (check-sat)
 (check-sat)
-(check-sat)
\ No newline at end of file
+(check-sat)
diff --git a/test/regress/regress0/proofs/trust-subs-eq-open.smt2 b/test/regress/regress0/proofs/trust-subs-eq-open.smt2
new file mode 100644 (file)
index 0000000..5f6bd9e
--- /dev/null
@@ -0,0 +1,8 @@
+(set-logic ALL)
+(set-info :status unsat)
+(declare-fun c () (_ BitVec 3))
+(check-sat-assuming (
+(and 
+(= (_ bv0 1) ((_ extract 1 1) c)) 
+(= (_ bv1 1) ((_ extract 0 0) c)) 
+(not (= (_ bv1 2) ((_ extract 1 0) c))))))