summaryrefslogtreecommitdiff
path: root/src/proof
diff options
context:
space:
mode:
authorHaniel Barbosa <hanielbbarbosa@gmail.com>2020-09-01 19:08:23 -0300
committerGitHub <noreply@github.com>2020-09-01 19:08:23 -0300
commit8ad308b23c705e73507a42d2425289e999d47f86 (patch)
tree29e3ac78844bc57171e0d122d758a8371a292a93 /src/proof
parent62ec0666dd4d409ee85603ae94d7ab1a2b4c9dcc (diff)
Removes old proof code (#4964)
This deletes much of the old proof code. Basically everything but the minimal necessary infra-structure for producing unsat cores. That includes dependency tracking in preprocessing, the prop engine proof and the unsat core computation code in the old proof manager. These should also go once we fully integrate into master the new proof infrastructure. It also cleans interfaces that were using old-proof-code-specific constructs (such as LemmaProofRecipe). When possible or when it made sense standalone local proof production code was kept, but deactivated (such is in the equality engine and in the arithmetic solver).
Diffstat (limited to 'src/proof')
-rw-r--r--src/proof/arith_proof.cpp1207
-rw-r--r--src/proof/arith_proof.h217
-rw-r--r--src/proof/arith_proof_recorder.cpp89
-rw-r--r--src/proof/arith_proof_recorder.h107
-rw-r--r--src/proof/array_proof.cpp1350
-rw-r--r--src/proof/array_proof.h121
-rw-r--r--src/proof/bitvector_proof.cpp792
-rw-r--r--src/proof/bitvector_proof.h280
-rw-r--r--src/proof/clausal_bitvector_proof.cpp412
-rw-r--r--src/proof/clausal_bitvector_proof.h189
-rw-r--r--src/proof/clause_id.h7
-rw-r--r--src/proof/cnf_proof.cpp863
-rw-r--r--src/proof/cnf_proof.h134
-rw-r--r--src/proof/dimacs.cpp120
-rw-r--r--src/proof/dimacs.h69
-rw-r--r--src/proof/drat/drat_proof.cpp291
-rw-r--r--src/proof/drat/drat_proof.h140
-rw-r--r--src/proof/er/er_proof.cpp399
-rw-r--r--src/proof/er/er_proof.h218
-rw-r--r--src/proof/lemma_proof.cpp254
-rw-r--r--src/proof/lemma_proof.h115
-rw-r--r--src/proof/lfsc_proof_printer.cpp217
-rw-r--r--src/proof/lfsc_proof_printer.h154
-rw-r--r--src/proof/lrat/lrat_proof.cpp343
-rw-r--r--src/proof/lrat/lrat_proof.h184
-rw-r--r--src/proof/proof.h70
-rw-r--r--src/proof/proof_manager.cpp1032
-rw-r--r--src/proof/proof_manager.h317
-rw-r--r--src/proof/proof_output_channel.cpp102
-rw-r--r--src/proof/proof_output_channel.h79
-rw-r--r--src/proof/proof_utils.cpp126
-rw-r--r--src/proof/proof_utils.h229
-rw-r--r--src/proof/resolution_bitvector_proof.cpp523
-rw-r--r--src/proof/resolution_bitvector_proof.h113
-rw-r--r--src/proof/sat_proof.h1
-rw-r--r--src/proof/sat_proof_implementation.h21
-rw-r--r--src/proof/simplify_boolean_node.cpp183
-rw-r--r--src/proof/simplify_boolean_node.h27
-rw-r--r--src/proof/skolemization_manager.cpp69
-rw-r--r--src/proof/skolemization_manager.h55
-rw-r--r--src/proof/theory_proof.cpp1756
-rw-r--r--src/proof/theory_proof.h510
-rw-r--r--src/proof/uf_proof.cpp759
-rw-r--r--src/proof/uf_proof.h106
44 files changed, 84 insertions, 14266 deletions
diff --git a/src/proof/arith_proof.cpp b/src/proof/arith_proof.cpp
deleted file mode 100644
index 635767b97..000000000
--- a/src/proof/arith_proof.cpp
+++ /dev/null
@@ -1,1207 +0,0 @@
-/********************* */
-/*! \file arith_proof.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir, Liana Hadarean, Guy Katz
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** [[ Add lengthier description here ]]
-
- ** \todo document this file
-
-**/
-#include "proof/arith_proof.h"
-
-#include <memory>
-#include <stack>
-
-#include "base/check.h"
-#include "expr/node.h"
-#include "expr/type_checker_util.h"
-#include "proof/proof_manager.h"
-#include "proof/theory_proof.h"
-#include "theory/arith/constraint_forward.h"
-#include "theory/arith/normal_form.h"
-#include "theory/arith/theory_arith.h"
-
-#define CVC4_ARITH_VAR_TERM_PREFIX "term."
-
-namespace CVC4 {
-
-inline static Node eqNode(TNode n1, TNode n2) {
- return NodeManager::currentNM()->mkNode(kind::EQUAL, n1, n2);
-}
-
-// congrence matching term helper
-inline static bool match(TNode n1, TNode n2) {
- Debug("pf::arith") << "match " << n1 << " " << n2 << std::endl;
- if(ProofManager::currentPM()->hasOp(n1)) {
- n1 = ProofManager::currentPM()->lookupOp(n1);
- }
- if(ProofManager::currentPM()->hasOp(n2)) {
- n2 = ProofManager::currentPM()->lookupOp(n2);
- }
- Debug("pf::arith") << "+ match " << n1 << " " << n2 << std::endl;
- if(n1 == n2) {
- return true;
- }
- if(n1.getType().isFunction() && n2.hasOperator()) {
- if(ProofManager::currentPM()->hasOp(n2.getOperator())) {
- return n1 == ProofManager::currentPM()->lookupOp(n2.getOperator());
- } else {
- return n1 == n2.getOperator();
- }
- }
- if(n2.getType().isFunction() && n1.hasOperator()) {
- if(ProofManager::currentPM()->hasOp(n1.getOperator())) {
- return n2 == ProofManager::currentPM()->lookupOp(n1.getOperator());
- } else {
- return n2 == n1.getOperator();
- }
- }
- if(n1.hasOperator() && n2.hasOperator() && n1.getOperator() != n2.getOperator()) {
- return false;
- }
- for(size_t i = 0; i < n1.getNumChildren() && i < n2.getNumChildren(); ++i) {
- if(n1[i] != n2[i]) {
- return false;
- }
- }
- return true;
-}
-
-void ProofArith::toStream(std::ostream& out) const
-{
- Trace("theory-proof-debug") << "; Print Arith proof..." << std::endl;
- //AJR : carry this further?
- ProofLetMap map;
- toStreamLFSC(out, ProofManager::getArithProof(), *d_proof, map);
-}
-
-void ProofArith::toStreamLFSC(std::ostream& out,
- TheoryProof* tp,
- const theory::eq::EqProof& pf,
- const ProofLetMap& map)
-{
- Debug("lfsc-arith") << "Printing arith proof in LFSC : " << std::endl;
- pf.debug_print("lfsc-arith");
- Debug("lfsc-arith") << std::endl;
- toStreamRecLFSC(out, tp, pf, 0, map);
-}
-
-Node ProofArith::toStreamRecLFSC(std::ostream& out,
- TheoryProof* tp,
- const theory::eq::EqProof& pf,
- unsigned tb,
- const ProofLetMap& map)
-{
- Debug("pf::arith") << std::endl
- << std::endl
- << "toStreamRecLFSC called. tb = " << tb
- << " . proof:" << std::endl;
- pf.debug_print("pf::arith");
- Debug("pf::arith") << std::endl;
-
- if(tb == 0) {
- Assert(pf.d_id == theory::eq::MERGED_THROUGH_TRANS);
- Assert(!pf.d_node.isNull());
- Assert(pf.d_children.size() >= 2);
-
- int neg = -1;
- std::shared_ptr<theory::eq::EqProof> subTrans =
- std::make_shared<theory::eq::EqProof>();
- subTrans->d_id = theory::eq::MERGED_THROUGH_TRANS;
- subTrans->d_node = pf.d_node;
-
- size_t i = 0;
- while (i < pf.d_children.size()) {
- // Look for the negative clause, with which we will form a contradiction.
- if(!pf.d_children[i]->d_node.isNull() && pf.d_children[i]->d_node.getKind() == kind::NOT) {
- Assert(neg < 0);
- neg = i;
- ++i;
- }
-
- // Handle congruence closures over equalities.
- else if (pf.d_children[i]->d_id==theory::eq::MERGED_THROUGH_CONGRUENCE && pf.d_children[i]->d_node.isNull()) {
- Debug("pf::arith") << "Handling congruence over equalities" << std::endl;
-
- // Gather the sequence of consecutive congruence closures.
- std::vector<std::shared_ptr<const theory::eq::EqProof>> congruenceClosures;
- unsigned count;
- Debug("pf::arith") << "Collecting congruence sequence" << std::endl;
- for (count = 0;
- i + count < pf.d_children.size() &&
- pf.d_children[i + count]->d_id==theory::eq::MERGED_THROUGH_CONGRUENCE &&
- pf.d_children[i + count]->d_node.isNull();
- ++count) {
- Debug("pf::arith") << "Found a congruence: " << std::endl;
- pf.d_children[i+count]->debug_print("pf::arith");
- congruenceClosures.push_back(pf.d_children[i+count]);
- }
-
- Debug("pf::arith") << "Total number of congruences found: " << congruenceClosures.size() << std::endl;
-
- // Determine if the "target" of the congruence sequence appears right before or right after the sequence.
- bool targetAppearsBefore = true;
- bool targetAppearsAfter = true;
-
- if ((i == 0) || (i == 1 && neg == 0)) {
- Debug("pf::arith") << "Target does not appear before" << std::endl;
- targetAppearsBefore = false;
- }
-
- if ((i + count >= pf.d_children.size()) ||
- (!pf.d_children[i + count]->d_node.isNull() &&
- pf.d_children[i + count]->d_node.getKind() == kind::NOT)) {
- Debug("pf::arith") << "Target does not appear after" << std::endl;
- targetAppearsAfter = false;
- }
-
- // Assert that we have precisely one target clause.
- Assert(targetAppearsBefore != targetAppearsAfter);
-
- // Begin breaking up the congruences and ordering the equalities correctly.
- std::vector<std::shared_ptr<theory::eq::EqProof>> orderedEqualities;
-
-
- // Insert target clause first.
- if (targetAppearsBefore) {
- orderedEqualities.push_back(pf.d_children[i - 1]);
- // The target has already been added to subTrans; remove it.
- subTrans->d_children.pop_back();
- } else {
- orderedEqualities.push_back(pf.d_children[i + count]);
- }
-
- // Start with the congruence closure closest to the target clause, and work our way back/forward.
- if (targetAppearsBefore) {
- for (unsigned j = 0; j < count; ++j) {
- if (pf.d_children[i + j]->d_children[0]->d_id != theory::eq::MERGED_THROUGH_REFLEXIVITY)
- orderedEqualities.insert(orderedEqualities.begin(), pf.d_children[i + j]->d_children[0]);
- if (pf.d_children[i + j]->d_children[1]->d_id != theory::eq::MERGED_THROUGH_REFLEXIVITY)
- orderedEqualities.insert(orderedEqualities.end(), pf.d_children[i + j]->d_children[1]);
- }
- } else {
- for (unsigned j = 0; j < count; ++j) {
- if (pf.d_children[i + count - 1 - j]->d_children[0]->d_id != theory::eq::MERGED_THROUGH_REFLEXIVITY)
- orderedEqualities.insert(orderedEqualities.begin(), pf.d_children[i + count - 1 - j]->d_children[0]);
- if (pf.d_children[i + count - 1 - j]->d_children[1]->d_id != theory::eq::MERGED_THROUGH_REFLEXIVITY)
- orderedEqualities.insert(orderedEqualities.end(), pf.d_children[i + count - 1 - j]->d_children[1]);
- }
- }
-
- // Copy the result into the main transitivity proof.
- subTrans->d_children.insert(subTrans->d_children.end(), orderedEqualities.begin(), orderedEqualities.end());
-
- // Increase i to skip over the children that have been processed.
- i += count;
- if (targetAppearsAfter) {
- ++i;
- }
- }
-
- // Else, just copy the child proof as is
- else {
- subTrans->d_children.push_back(pf.d_children[i]);
- ++i;
- }
- }
- Assert(neg >= 0);
-
- Node n1;
- std::stringstream ss;
- //Assert(subTrans->d_children.size() == pf.d_children.size() - 1);
- Debug("pf::arith") << "\nsubtrans has " << subTrans->d_children.size() << " children\n";
- if(pf.d_children.size() > 2) {
- n1 = toStreamRecLFSC(ss, tp, *subTrans, 1, map);
- } else {
- n1 = toStreamRecLFSC(ss, tp, *(subTrans->d_children[0]), 1, map);
- Debug("pf::arith") << "\nsubTrans unique child " << subTrans->d_children[0]->d_id << " was proven\ngot: " << n1 << std::endl;
- }
-
- Node n2 = pf.d_children[neg]->d_node;
- Assert(n2.getKind() == kind::NOT);
- out << "(clausify_false (contra _ ";
- Debug("pf::arith") << "\nhave proven: " << n1 << std::endl;
- Debug("pf::arith") << "n2 is " << n2[0] << std::endl;
-
- if (n2[0].getNumChildren() > 0) { Debug("pf::arith") << "\nn2[0]: " << n2[0][0] << std::endl; }
- if (n1.getNumChildren() > 1) { Debug("pf::arith") << "n1[1]: " << n1[1] << std::endl; }
-
- if(n2[0].getKind() == kind::APPLY_UF) {
- out << "(trans _ _ _ _ ";
- out << "(symm _ _ _ ";
- out << ss.str();
- out << ") (pred_eq_f _ " << ProofManager::getLitName(n2[0]) << ")) t_t_neq_f))" << std::endl;
- } else {
- Assert((n1[0] == n2[0][0] && n1[1] == n2[0][1])
- || (n1[1] == n2[0][0] && n1[0] == n2[0][1]));
- if(n1[1] == n2[0][0]) {
- out << "(symm _ _ _ " << ss.str() << ")";
- } else {
- out << ss.str();
- }
- out << " " << ProofManager::getLitName(n2[0]) << "))" << std::endl;
- }
- return Node();
- }
-
- switch(pf.d_id) {
- case theory::eq::MERGED_THROUGH_CONGRUENCE: {
- Debug("pf::arith") << "\nok, looking at congruence:\n";
- pf.debug_print("pf::arith");
- std::stack<const theory::eq::EqProof*> stk;
- for (const theory::eq::EqProof* pf2 = &pf;
- pf2->d_id == theory::eq::MERGED_THROUGH_CONGRUENCE;
- pf2 = pf2->d_children[0].get()) {
- Assert(!pf2->d_node.isNull());
- Assert(pf2->d_node.getKind() == kind::PARTIAL_APPLY_UF
- || pf2->d_node.getKind() == kind::BUILTIN
- || pf2->d_node.getKind() == kind::APPLY_UF
- || pf2->d_node.getKind() == kind::SELECT
- || pf2->d_node.getKind() == kind::STORE);
- Assert(pf2->d_children.size() == 2);
- out << "(cong _ _ _ _ _ _ ";
- stk.push(pf2);
- }
- Assert(stk.top()->d_children[0]->d_id
- != theory::eq::MERGED_THROUGH_CONGRUENCE);
- NodeBuilder<> b1(kind::PARTIAL_APPLY_UF), b2(kind::PARTIAL_APPLY_UF);
- const theory::eq::EqProof* pf2 = stk.top();
- stk.pop();
- Assert(pf2->d_id == theory::eq::MERGED_THROUGH_CONGRUENCE);
- Node n1 = toStreamRecLFSC(out, tp, *(pf2->d_children[0]), tb + 1, map);
- out << " ";
- std::stringstream ss;
- Node n2 = toStreamRecLFSC(ss, tp, *(pf2->d_children[1]), tb + 1, map);
- Debug("pf::arith") << "\nok, in FIRST cong[" << stk.size() << "]" << "\n";
- pf2->debug_print("pf::arith");
- Debug("pf::arith") << "looking at " << pf2->d_node << "\n";
- Debug("pf::arith") << " " << n1 << "\n";
- Debug("pf::arith") << " " << n2 << "\n";
- int side = 0;
- if(match(pf2->d_node, n1[0])) {
- //if(tb == 1) {
- Debug("pf::arith") << "SIDE IS 0\n";
- //}
- side = 0;
- } else {
- //if(tb == 1) {
- Debug("pf::arith") << "SIDE IS 1\n";
- //}
- if(!match(pf2->d_node, n1[1])) {
- Debug("pf::arith") << "IN BAD CASE, our first subproof is\n";
- pf2->d_children[0]->debug_print("pf::arith");
- }
- Assert(match(pf2->d_node, n1[1]));
- side = 1;
- }
- if(n1[side].getKind() == kind::APPLY_UF || n1[side].getKind() == kind::PARTIAL_APPLY_UF || n1[side].getKind() == kind::SELECT || n1[side].getKind() == kind::STORE) {
- if(n1[side].getKind() == kind::APPLY_UF || n1[side].getKind() == kind::PARTIAL_APPLY_UF) {
- b1 << n1[side].getOperator();
- } else {
- b1 << ProofManager::currentPM()->mkOp(n1[side].getOperator());
- }
- b1.append(n1[side].begin(), n1[side].end());
- } else {
- b1 << n1[side];
- }
- if(n1[1-side].getKind() == kind::PARTIAL_APPLY_UF || n1[1-side].getKind() == kind::APPLY_UF || n1[side].getKind() == kind::SELECT || n1[side].getKind() == kind::STORE) {
- if(n1[1-side].getKind() == kind::PARTIAL_APPLY_UF || n1[1-side].getKind() == kind::APPLY_UF) {
- b2 << n1[1-side].getOperator();
- } else {
- b2 << ProofManager::currentPM()->mkOp(n1[1-side].getOperator());
- }
- b2.append(n1[1-side].begin(), n1[1-side].end());
- } else {
- b2 << n1[1-side];
- }
- Debug("pf::arith") << "pf2->d_node " << pf2->d_node << std::endl;
- Debug("pf::arith") << "b1.getNumChildren() " << b1.getNumChildren() << std::endl;
- Debug("pf::arith") << "n1 " << n1 << std::endl;
- Debug("pf::arith") << "n2 " << n2 << std::endl;
- Debug("pf::arith") << "side " << side << std::endl;
- if(pf2->d_node[b1.getNumChildren() - (pf2->d_node.getMetaKind() == kind::metakind::PARAMETERIZED ? 0 : 1)] == n2[side]) {
- b1 << n2[side];
- b2 << n2[1-side];
- out << ss.str();
- } else {
- Assert(pf2->d_node[b1.getNumChildren()
- - (pf2->d_node.getMetaKind()
- == kind::metakind::PARAMETERIZED
- ? 0
- : 1)]
- == n2[1 - side]);
- b1 << n2[1-side];
- b2 << n2[side];
- out << "(symm _ _ _ " << ss.str() << ")";
- }
- out << ")";
- while(!stk.empty()) {
- if(tb == 1) {
- Debug("pf::arith") << "\nMORE TO DO\n";
- }
- pf2 = stk.top();
- stk.pop();
- Assert(pf2->d_id == theory::eq::MERGED_THROUGH_CONGRUENCE);
- out << " ";
- ss.str("");
- n2 = toStreamRecLFSC(ss, tp, *(pf2->d_children[1]), tb + 1, map);
- Debug("pf::arith") << "\nok, in cong[" << stk.size() << "]" << "\n";
- Debug("pf::arith") << "looking at " << pf2->d_node << "\n";
- Debug("pf::arith") << " " << n1 << "\n";
- Debug("pf::arith") << " " << n2 << "\n";
- Debug("pf::arith") << " " << b1 << "\n";
- Debug("pf::arith") << " " << b2 << "\n";
- if(pf2->d_node[b1.getNumChildren()] == n2[side]) {
- b1 << n2[side];
- b2 << n2[1-side];
- out << ss.str();
- } else {
- Assert(pf2->d_node[b1.getNumChildren()] == n2[1 - side]);
- b1 << n2[1-side];
- b2 << n2[side];
- out << "(symm _ _ _ " << ss.str() << ")";
- }
- out << ")";
- }
- n1 = b1;
- n2 = b2;
- Debug("pf::arith") << "at end assert, got " << pf2->d_node << " and " << n1 << std::endl;
- if(pf2->d_node.getKind() == kind::PARTIAL_APPLY_UF) {
- Assert(n1 == pf2->d_node);
- }
- if(n1.getOperator().getType().getNumChildren() == n1.getNumChildren() + 1) {
- if(ProofManager::currentPM()->hasOp(n1.getOperator())) {
- b1.clear(ProofManager::currentPM()->lookupOp(n2.getOperator()).getConst<Kind>());
- } else {
- b1.clear(kind::APPLY_UF);
- b1 << n1.getOperator();
- }
- b1.append(n1.begin(), n1.end());
- n1 = b1;
- Debug("pf::arith") << "at[2] end assert, got " << pf2->d_node << " and " << n1 << std::endl;
- if(pf2->d_node.getKind() == kind::APPLY_UF) {
- Assert(n1 == pf2->d_node);
- }
- }
- if(n2.getOperator().getType().getNumChildren() == n2.getNumChildren() + 1) {
- if(ProofManager::currentPM()->hasOp(n2.getOperator())) {
- b2.clear(ProofManager::currentPM()->lookupOp(n2.getOperator()).getConst<Kind>());
- } else {
- b2.clear(kind::APPLY_UF);
- b2 << n2.getOperator();
- }
- b2.append(n2.begin(), n2.end());
- n2 = b2;
- }
- Node n = (side == 0 ? eqNode(n1, n2) : eqNode(n2, n1));
- if(tb == 1) {
- Debug("pf::arith") << "\ncong proved: " << n << "\n";
- }
- return n;
- }
-
- case theory::eq::MERGED_THROUGH_REFLEXIVITY:
- Assert(!pf.d_node.isNull());
- Assert(pf.d_children.empty());
- out << "(refl _ ";
- tp->printTerm(NodeManager::currentNM()->toExpr(pf.d_node), out, map);
- out << ")";
- return eqNode(pf.d_node, pf.d_node);
-
- case theory::eq::MERGED_THROUGH_EQUALITY:
- Assert(!pf.d_node.isNull());
- Assert(pf.d_children.empty());
- out << ProofManager::getLitName(pf.d_node.negate());
- return pf.d_node;
-
- case theory::eq::MERGED_THROUGH_TRANS: {
- Assert(!pf.d_node.isNull());
- Assert(pf.d_children.size() >= 2);
- std::stringstream ss;
- Debug("pf::arith") << "\ndoing trans proof[[\n";
- pf.debug_print("pf::arith");
- Debug("pf::arith") << "\n";
- Node n1 = toStreamRecLFSC(ss, tp, *(pf.d_children[0]), tb + 1, map);
- Debug("pf::arith") << "\ndoing trans proof, got n1 " << n1 << "\n";
- if(tb == 1) {
- Debug("pf::arith") << "\ntrans proof[0], got n1 " << n1 << "\n";
- }
-
- bool identicalEqualities = false;
- bool evenLengthSequence;
- Node nodeAfterEqualitySequence;
-
- std::map<size_t, Node> childToStream;
-
- for(size_t i = 1; i < pf.d_children.size(); ++i) {
- std::stringstream ss1(ss.str()), ss2;
- ss.str("");
-
- // It is possible that we've already converted the i'th child to stream. If so,
- // use previously stored result. Otherwise, convert and store.
- Node n2;
- if (childToStream.find(i) != childToStream.end())
- n2 = childToStream[i];
- else {
- n2 = toStreamRecLFSC(ss2, tp, *(pf.d_children[i]), tb + 1, map);
- childToStream[i] = n2;
- }
-
- // The following branch is dedicated to handling sequences of identical equalities,
- // i.e. trans[ a=b, a=b, a=b ].
- //
- // There are two cases:
- // 1. The number of equalities is odd. Then, the sequence can be collapsed to just one equality,
- // i.e. a=b.
- // 2. The number of equalities is even. Now, we have two options: a=a or b=b. To determine this,
- // we look at the node after the equality sequence. If it needs a, we go for a=a; and if it needs
- // b, we go for b=b. If there is no following node, we look at the goal of the transitivity proof,
- // and use it to determine which option we need.
- if(n2.getKind() == kind::EQUAL) {
- if (((n1[0] == n2[0]) && (n1[1] == n2[1])) || ((n1[0] == n2[1]) && (n1[1] == n2[0]))) {
- // We are in a sequence of identical equalities
-
- Debug("pf::arith") << "Detected identical equalities: " << std::endl << "\t" << n1 << std::endl;
-
- if (!identicalEqualities) {
- // The sequence of identical equalities has started just now
- identicalEqualities = true;
-
- Debug("pf::arith") << "The sequence is just beginning. Determining length..." << std::endl;
-
- // Determine whether the length of this sequence is odd or even.
- evenLengthSequence = true;
- bool sequenceOver = false;
- size_t j = i + 1;
-
- while (j < pf.d_children.size() && !sequenceOver) {
- std::stringstream dontCare;
- nodeAfterEqualitySequence = toStreamRecLFSC(
- dontCare, tp, *(pf.d_children[j]), tb + 1, map);
-
- if (((nodeAfterEqualitySequence[0] == n1[0]) && (nodeAfterEqualitySequence[1] == n1[1])) ||
- ((nodeAfterEqualitySequence[0] == n1[1]) && (nodeAfterEqualitySequence[1] == n1[0]))) {
- evenLengthSequence = !evenLengthSequence;
- } else {
- sequenceOver = true;
- }
-
- ++j;
- }
-
- if (evenLengthSequence) {
- // If the length is even, we need to apply transitivity for the "correct" hand of the equality.
-
- Debug("pf::arith") << "Equality sequence of even length" << std::endl;
- Debug("pf::arith") << "n1 is: " << n1 << std::endl;
- Debug("pf::arith") << "n2 is: " << n2 << std::endl;
- Debug("pf::arith") << "pf-d_node is: " << pf.d_node << std::endl;
- Debug("pf::arith") << "Next node is: " << nodeAfterEqualitySequence << std::endl;
-
- ss << "(trans _ _ _ _ ";
-
- // If the sequence is at the very end of the transitivity proof, use pf.d_node to guide us.
- if (!sequenceOver) {
- if (match(n1[0], pf.d_node[0])) {
- n1 = eqNode(n1[0], n1[0]);
- ss << ss1.str() << " (symm _ _ _ " << ss1.str() << ")";
- } else if (match(n1[1], pf.d_node[1])) {
- n1 = eqNode(n1[1], n1[1]);
- ss << " (symm _ _ _ " << ss1.str() << ")" << ss1.str();
- } else {
- Debug("pf::arith") << "Error: identical equalities over, but hands don't match what we're proving."
- << std::endl;
- Assert(false);
- }
- } else {
- // We have a "next node". Use it to guide us.
-
- Assert(nodeAfterEqualitySequence.getKind() == kind::EQUAL);
-
- if ((n1[0] == nodeAfterEqualitySequence[0]) || (n1[0] == nodeAfterEqualitySequence[1])) {
-
- // Eliminate n1[1]
- ss << ss1.str() << " (symm _ _ _ " << ss1.str() << ")";
- n1 = eqNode(n1[0], n1[0]);
-
- } else if ((n1[1] == nodeAfterEqualitySequence[0]) || (n1[1] == nodeAfterEqualitySequence[1])) {
-
- // Eliminate n1[0]
- ss << " (symm _ _ _ " << ss1.str() << ")" << ss1.str();
- n1 = eqNode(n1[1], n1[1]);
-
- } else {
- Debug("pf::arith") << "Error: even length sequence, but I don't know which hand to keep!" << std::endl;
- Assert(false);
- }
- }
-
- ss << ")";
-
- } else {
- Debug("pf::arith") << "Equality sequence length is odd!" << std::endl;
- ss.str(ss1.str());
- }
-
- Debug("pf::arith") << "Have proven: " << n1 << std::endl;
- } else {
- ss.str(ss1.str());
- }
-
- // Ignore the redundancy.
- continue;
- }
- }
-
- if (identicalEqualities) {
- // We were in a sequence of identical equalities, but it has now ended. Resume normal operation.
- identicalEqualities = false;
- }
-
- Debug("pf::arith") << "\ndoing trans proof, got n2 " << n2 << "\n";
- if(tb == 1) {
- Debug("pf::arith") << "\ntrans proof[" << i << "], got n2 " << n2 << "\n";
- Debug("pf::arith") << (n2.getKind() == kind::EQUAL) << "\n";
-
- if ((n1.getNumChildren() >= 2) && (n2.getNumChildren() >= 2)) {
- Debug("pf::arith") << n1[0].getId() << " " << n1[1].getId() << " / " << n2[0].getId() << " " << n2[1].getId() << "\n";
- Debug("pf::arith") << n1[0].getId() << " " << n1[0] << "\n";
- Debug("pf::arith") << n1[1].getId() << " " << n1[1] << "\n";
- Debug("pf::arith") << n2[0].getId() << " " << n2[0] << "\n";
- Debug("pf::arith") << n2[1].getId() << " " << n2[1] << "\n";
- Debug("pf::arith") << (n1[0] == n2[0]) << "\n";
- Debug("pf::arith") << (n1[1] == n2[1]) << "\n";
- Debug("pf::arith") << (n1[0] == n2[1]) << "\n";
- Debug("pf::arith") << (n1[1] == n2[0]) << "\n";
- }
- }
- ss << "(trans _ _ _ _ ";
-
- if((n2.getKind() == kind::EQUAL) && (n1.getKind() == kind::EQUAL))
- // Both elements of the transitivity rule are equalities/iffs
- {
- if(n1[0] == n2[0]) {
- if(tb == 1) { Debug("pf::arith") << "case 1\n"; }
- n1 = eqNode(n1[1], n2[1]);
- ss << "(symm _ _ _ " << ss1.str() << ") " << ss2.str();
- } else if(n1[1] == n2[1]) {
- if(tb == 1) { Debug("pf::arith") << "case 2\n"; }
- n1 = eqNode(n1[0], n2[0]);
- ss << ss1.str() << " (symm _ _ _ " << ss2.str() << ")";
- } else if(n1[0] == n2[1]) {
- if(tb == 1) { Debug("pf::arith") << "case 3\n"; }
- n1 = eqNode(n2[0], n1[1]);
- ss << ss2.str() << " " << ss1.str();
- if(tb == 1) { Debug("pf::arith") << "++ proved " << n1 << "\n"; }
- } else if(n1[1] == n2[0]) {
- if(tb == 1) { Debug("pf::arith") << "case 4\n"; }
- n1 = eqNode(n1[0], n2[1]);
- ss << ss1.str() << " " << ss2.str();
- } else {
- Warning() << "\n\ntrans proof failure at step " << i << "\n\n";
- Warning() << "0 proves " << n1 << "\n";
- Warning() << "1 proves " << n2 << "\n\n";
- pf.debug_print("pf::arith",0);
- //toStreamRec(Warning.getStream(), pf, 0);
- Warning() << "\n\n";
- Unreachable();
- }
- Debug("pf::arith") << "++ trans proof[" << i << "], now have " << n1 << std::endl;
- } else if(n1.getKind() == kind::EQUAL) {
- // n1 is an equality/iff, but n2 is a predicate
- if(n1[0] == n2) {
- n1 = n1[1];
- ss << "(symm _ _ _ " << ss1.str() << ") (pred_eq_t _ " << ss2.str() << ")";
- } else if(n1[1] == n2) {
- n1 = n1[0];
- ss << ss1.str() << " (pred_eq_t _ " << ss2.str() << ")";
- } else {
- Unreachable();
- }
- } else if(n2.getKind() == kind::EQUAL) {
- // n2 is an equality/iff, but n1 is a predicate
- if(n2[0] == n1) {
- n1 = n2[1];
- ss << "(symm _ _ _ " << ss2.str() << ") (pred_eq_t _ " << ss1.str() << ")";
- } else if(n2[1] == n1) {
- n1 = n2[0];
- ss << ss2.str() << " (pred_eq_t _ " << ss1.str() << ")";
- } else {
- Unreachable();
- }
- } else {
- // Both n1 and n2 are prediacates. Don't know what to do...
- Unreachable();
- }
-
- ss << ")";
- }
- out << ss.str();
- Debug("pf::arith") << "\n++ trans proof done, have proven " << n1 << std::endl;
- return n1;
- }
-
- default:
- Assert(!pf.d_node.isNull());
- Assert(pf.d_children.empty());
- Debug("pf::arith") << "theory proof: " << pf.d_node << " by rule " << int(pf.d_id) << std::endl;
- AlwaysAssert(false);
- return pf.d_node;
- }
-}
-
-ArithProof::ArithProof(theory::arith::TheoryArith* arith, TheoryProofEngine* pe)
- : TheoryProof(arith, pe), d_recorder()
-{
- arith->setProofRecorder(&d_recorder);
-}
-
-theory::TheoryId ArithProof::getTheoryId() { return theory::THEORY_ARITH; }
-void ArithProof::registerTerm(Expr term) {
- Debug("pf::arith") << "Arith register term: " << term << ". Kind: " << term.getKind()
- << ". Type: " << term.getType() << std::endl;
-
- if (term.getType().isReal() && !term.getType().isInteger()) {
- Debug("pf::arith") << "Entering real mode" << std::endl;
- }
-
- if (term.isVariable() && !ProofManager::getSkolemizationManager()->isSkolem(term)) {
- d_declarations.insert(term);
- }
-
- // recursively declare all other terms
- for (unsigned i = 0; i < term.getNumChildren(); ++i) {
- // could belong to other theories
- d_proofEngine->registerTerm(term[i]);
- }
-}
-
-void LFSCArithProof::printOwnedTermAsType(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType)
-{
- Debug("pf::arith") << "Arith print term: " << term << ". Kind: " << term.getKind()
- << ". Type: " << term.getType()
- << ". Number of children: " << term.getNumChildren() << std::endl;
-
- // !d_realMode <--> term.getType().isInteger()
-
- Assert (theory::Theory::theoryOf(term) == theory::THEORY_ARITH);
- std::ostringstream closing;
- if (!expectedType.isNull() && !expectedType.isInteger() && term.getType().isInteger()) {
- os << "(term_int_to_real ";
- closing << ")";
- }
- switch (term.getKind())
- {
- case kind::CONST_RATIONAL:
- {
- Assert(term.getNumChildren() == 0);
- Assert(term.getType().isInteger() || term.getType().isReal());
-
- const Rational& r = term.getConst<Rational>();
- bool neg = (r < 0);
-
- os << (term.getType().isInteger() ? "(a_int " : "(a_real ");
- closing << ") ";
-
- if (neg)
- {
- os << "(~ ";
- closing << ")";
- }
-
- if (term.getType().isInteger())
- {
- os << r.abs();
- }
- else
- {
- printRational(os, r.abs());
- }
-
- break;
- }
-
- case kind::PLUS:
- case kind::MINUS:
- case kind::MULT:
- case kind::DIVISION:
- case kind::DIVISION_TOTAL:
- {
- Assert(term.getNumChildren() >= 1);
- TypeNode ty = Node::fromExpr(term).getType();
-
- std::string lfscFunction = getLfscFunction(term);
- for (unsigned i = 0; i < term.getNumChildren() - 1; ++i)
- {
- os << "(" << lfscFunction << " ";
- closing << ")";
- d_proofEngine->printBoundTerm(term[i], os, map, ty);
- os << " ";
- }
-
- d_proofEngine->printBoundTerm(term[term.getNumChildren() - 1], os, map, ty);
- break;
- }
-
- case kind::UMINUS:
- {
- Assert(term.getNumChildren() == 1);
- os << "(" << getLfscFunction(term) << " ";
- closing << ")";
- d_proofEngine->printBoundTerm(term[0], os, map, Node::fromExpr(term).getType());
- break;
- }
-
- case kind::GT:
- case kind::GEQ:
- case kind::LT:
- case kind::LEQ:
- {
- Assert(term.getNumChildren() == 2);
- Assert(term.getType().isBoolean());
-
- std::string lfscFunction = getLfscFunction(term);
- TypeNode realType = NodeManager::currentNM()->realType();
-
- os << "(" << lfscFunction << " ";
- closing << ")";
-
- d_proofEngine->printBoundTerm(term[0], os, map);
- os << " ";
- d_proofEngine->printBoundTerm(term[1], os, map, realType);
- break;
- }
- case kind::EQUAL:
- {
- Assert(term.getType().isBoolean());
- Assert(term.getNumChildren() == 2);
-
- TypeNode eqType = equalityType(term[0], term[1]);
-
- os << "(= " << eqType << " ";
- closing << ")";
-
- d_proofEngine->printBoundTerm(term[0], os, map, eqType);
- d_proofEngine->printBoundTerm(term[1], os, map, eqType);
- break;
- }
-
- case kind::VARIABLE:
- case kind::SKOLEM:
- os << CVC4_ARITH_VAR_TERM_PREFIX << ProofManager::sanitize(term);
- break;
-
- default:
- Debug("pf::arith") << "Default printing of term: " << term << std::endl;
- os << term;
- break;
- }
- os << closing.str();
-}
-
-void LFSCArithProof::printOwnedSort(Type type, std::ostream& os) {
- Debug("pf::arith") << "Arith print sort: " << type << std::endl;
- os << type;
-}
-
-std::string LFSCArithProof::getLfscFunction(const Node & n) {
- Assert(n.getType().isInteger() || n.getType().isReal() || n.getType().isBoolean());
- std::string opString;
- switch (n.getKind()) {
- case kind::UMINUS:
- opString = "u-_";
- break;
- case kind::PLUS:
- opString = "+_";
- break;
- case kind::MINUS:
- opString = "-_";
- break;
- case kind::MULT:
- opString = "*_";
- break;
- case kind::DIVISION:
- case kind::DIVISION_TOTAL:
- opString = "/_";
- break;
- case kind::GT:
- opString = ">_";
- break;
- case kind::GEQ:
- opString = ">=_";
- break;
- case kind::LT:
- opString = "<_";
- break;
- case kind::LEQ:
- opString = "<=_";
- break;
- default:
- Unreachable() << "Tried to get the operator for a non-operator kind: " << n.getKind();
- }
- std::string typeString;
- if (n.getType().isInteger()) {
- typeString = "Int";
- } else if (n.getType().isReal()) {
- typeString = "Real";
- } else { // Boolean
- if (n[0].getType().isInteger()) {
- typeString = "IntReal";
- } else {
- typeString = "Real";
- }
- }
- return opString + typeString;
-}
-
-void LFSCArithProof::printRational(std::ostream& o, const Rational& r)
-{
- if (r.sgn() < 0)
- {
- o << "(~ " << r.getNumerator().abs() << "/" << r.getDenominator().abs()
- << ")";
- }
- else
- {
- o << r.getNumerator() << "/" << r.getDenominator();
- }
-}
-
-void LFSCArithProof::printInteger(std::ostream& o, const Integer& i)
-{
- if (i.sgn() < 0)
- {
- o << "(~ " << i.abs() << ")";
- }
- else
- {
- o << i;
- }
-}
-
-void LFSCArithProof::printLinearPolynomialNormalizer(std::ostream& o,
- const Node& n)
-{
- switch (n.getKind())
- {
- case kind::PLUS:
- {
- // Since our axioms are binary, but n may be n-ary, we rig up
- // a right-associative tree.
- size_t nchildren = n.getNumChildren();
- for (size_t i = 0; i < nchildren; ++i)
- {
- if (i < nchildren - 1)
- {
- o << "\n (is_aff_+ _ _ _ _ _ ";
- }
- printLinearMonomialNormalizer(o, n[i]);
- }
- std::fill_n(std::ostream_iterator<char>(o), nchildren - 1, ')');
- break;
- }
- case kind::MULT:
- case kind::VARIABLE:
- case kind::CONST_RATIONAL:
- case kind::SKOLEM:
- {
- printLinearMonomialNormalizer(o, n);
- break;
- }
- default:
- Unreachable() << "Invalid operation " << n.getKind()
- << " in linear polynomial";
- break;
- }
-}
-
-void LFSCArithProof::printLinearMonomialNormalizer(std::ostream& o,
- const Node& n)
-{
- switch (n.getKind())
- {
- case kind::MULT: {
- Assert((n[0].getKind() == kind::CONST_RATIONAL
- && (n[1].getKind() == kind::VARIABLE
- || n[1].getKind() == kind::SKOLEM)))
- << "node " << n << " is not a linear monomial"
- << " " << n[0].getKind() << " " << n[1].getKind();
-
- o << "\n (is_aff_mul_c_L _ _ _ ";
- printConstRational(o, n[0]);
- o << " ";
- printVariableNormalizer(o, n[1]);
- o << ")";
- break;
- }
- case kind::CONST_RATIONAL:
- {
- o << "\n (is_aff_const ";
- printConstRational(o, n);
- o << ")";
- break;
- }
- case kind::VARIABLE:
- case kind::SKOLEM:
- {
- o << "\n ";
- printVariableNormalizer(o, n);
- break;
- }
- default:
- Unreachable() << "Invalid operation " << n.getKind()
- << " in linear monomial";
- break;
- }
-}
-
-void LFSCArithProof::printConstRational(std::ostream& o, const Node& n)
-{
- Assert(n.getKind() == kind::CONST_RATIONAL);
- const Rational value = n.getConst<Rational>();
- printRational(o, value);
-}
-
-void LFSCArithProof::printVariableNormalizer(std::ostream& o, const Node& n)
-{
- std::ostringstream msg;
- Assert(n.getKind() == kind::VARIABLE || n.getKind() == kind::SKOLEM)
- << "Invalid variable kind " << n.getKind() << " in linear monomial";
- if (n.getType().isInteger()) {
- o << "(is_aff_var_int ";
- } else if (n.getType().isReal()) {
- o << "(is_aff_var_real ";
- } else {
- Unreachable();
- }
- o << n << ")";
-}
-
-void LFSCArithProof::printLinearPolynomialPredicateNormalizer(std::ostream& o,
- const Node& n)
-{
- Assert(n.getKind() == kind::GEQ)
- << "can only print normalization witnesses for (>=) nodes";
- Assert(n[1].getKind() == kind::CONST_RATIONAL);
- o << "\n (is_aff_- _ _ _ _ _ ";
- printLinearPolynomialNormalizer(o, n[0]);
- o << "\n (is_aff_const ";
- printConstRational(o, n[1]);
- o << "))";
-}
-
-std::pair<Node, std::string> LFSCArithProof::printProofAndMaybeTighten(
- const Node& bound)
-{
- const Node & nonNegBound = bound.getKind() == kind::NOT ? bound[0] : bound;
- std::ostringstream pfOfPossiblyTightenedPredicate;
- if (nonNegBound[0].getType().isInteger()) {
- switch(bound.getKind())
- {
- case kind::NOT:
- {
- // Tighten ~[i >= r] to [i < r] to [i <= {r}] to [-i >= -{r}]
- // where
- // * i is an integer
- // * r is a real
- // * {r} denotes the greatest int less than r
- // it is equivalent to (ceil(r) - 1)
- Assert(nonNegBound[1].getKind() == kind::CONST_RATIONAL);
- Rational oldBound = nonNegBound[1].getConst<Rational>();
- Integer newBound = -(oldBound.ceiling() - 1);
- // Since the arith theory rewrites bounds to be purely integral or
- // purely real, mixed bounds should not appear in proofs
- AlwaysAssert(oldBound.isIntegral()) << "Mixed int/real bound in arith proof";
- pfOfPossiblyTightenedPredicate
- << "(tighten_not_>=_IntInt"
- << " _ _ _ _ ("
- << "check_neg_of_greatest_integer_below_int ";
- printInteger(pfOfPossiblyTightenedPredicate, newBound);
- pfOfPossiblyTightenedPredicate << " ";
- printInteger(pfOfPossiblyTightenedPredicate, oldBound.ceiling());
- pfOfPossiblyTightenedPredicate << ") " << ProofManager::getLitName(bound.negate(), "") << ")";
- Node newLeft = (theory::arith::Polynomial::parsePolynomial(nonNegBound[0]) * -1).getNode();
- Node newRight = NodeManager::currentNM()->mkConst(Rational(newBound));
- Node newTerm = NodeManager::currentNM()->mkNode(kind::GEQ, newLeft, newRight);
- return std::make_pair(newTerm, pfOfPossiblyTightenedPredicate.str());
- }
- case kind::GEQ:
- {
- // Tighten [i >= r] to [i >= ceil(r)]
- // where
- // * i is an integer
- // * r is a real
- Assert(nonNegBound[1].getKind() == kind::CONST_RATIONAL);
-
- Rational oldBound = nonNegBound[1].getConst<Rational>();
- // Since the arith theory rewrites bounds to be purely integral or
- // purely real, mixed bounds should not appear in proofs
- AlwaysAssert(oldBound.isIntegral()) << "Mixed int/real bound in arith proof";
- pfOfPossiblyTightenedPredicate << ProofManager::getLitName(bound.negate(), "");
- return std::make_pair(bound, pfOfPossiblyTightenedPredicate.str());
- }
- default: Unreachable();
- }
- } else {
- return std::make_pair(bound, ProofManager::getLitName(bound.negate(), ""));
- }
- // Silence compiler warnings about missing a return.
- Unreachable();
-}
-
-void LFSCArithProof::printTheoryLemmaProof(std::vector<Expr>& lemma,
- std::ostream& os,
- std::ostream& paren,
- const ProofLetMap& map)
-{
- Debug("pf::arith") << "Printing proof for lemma " << lemma << std::endl;
- if (Debug.isOn("pf::arith::printTheoryLemmaProof")) {
- Debug("pf::arith::printTheoryLemmaProof") << "Printing proof for lemma:" << std::endl;
- for (const auto & conjunct : lemma) {
- Debug("pf::arith::printTheoryLemmaProof") << " " << conjunct << std::endl;
- }
- }
- // Prefixes for the names of linearity witnesses
- const char* linearizedProofPrefix = "pf_aff";
- std::ostringstream lemmaParen;
-
- // Construct the set of conflicting literals
- std::set<Node> conflictSet;
- std::transform(lemma.begin(),
- lemma.end(),
- std::inserter(conflictSet, conflictSet.begin()),
- [](const Expr& e) {
- return NodeManager::currentNM()->fromExpr(e).negate();
- });
-
- // If we have Farkas coefficients stored for this lemma, use them to write a
- // proof. Otherwise, just `trust` the lemma.
- if (d_recorder.hasFarkasCoefficients(conflictSet))
- {
- // Get farkas coefficients & literal order
- const auto& farkasInfo = d_recorder.getFarkasCoefficients(conflictSet);
- const Node& conflict = farkasInfo.first;
- theory::arith::RationalVectorCP farkasCoefficients = farkasInfo.second;
- Assert(farkasCoefficients != theory::arith::RationalVectorCPSentinel);
- Assert(conflict.getNumChildren() == farkasCoefficients->size());
- const size_t nAntecedents = conflict.getNumChildren();
-
- // Print proof
- if (Debug.isOn("pf::arith::printTheoryLemmaProof")) {
- os << "Farkas:" << std::endl;
- for (const auto & n : *farkasCoefficients) {
- os << " " << n << std::endl;
- }
- }
-
- // Prove affine function bounds from term bounds
- os << "\n;; Farkas Proof ;;" << std::endl;
- os << "\n; Linear Polynomial Proof Conversions";
- for (size_t i = 0; i != nAntecedents; ++i)
- {
- const Node& antecedent = conflict[i];
- os << "\n (@ "
- << ProofManager::getLitName(antecedent.negate(), linearizedProofPrefix)
- << " ";
- lemmaParen << ")";
- const std::pair<Node, std::string> tightened = printProofAndMaybeTighten(antecedent);
- switch (tightened.first.getKind())
- {
- case kind::NOT:
- {
- Assert(conflict[i][0].getKind() == kind::GEQ);
- os << "(aff_>_from_term _ _ _ _ ";
- break;
- }
- case kind::GEQ:
- {
- os << "(aff_>=_from_term _ _ _ ";
- break;
- }
- default: Unreachable();
- }
- const Node& nonNegTightened = tightened.first.getKind() == kind::NOT ? tightened.first[0] : tightened.first;
- printLinearPolynomialPredicateNormalizer(os, nonNegTightened);
- os << " (pf_reified_arith_pred _ _ " << tightened.second << "))";
- }
-
- // Now, print the proof of bottom, from affine function bounds
- os << "\n; Farkas Combination";
- os << "\n (clausify_false (bounded_aff_contra _ _";
- lemmaParen << "))";
- for (size_t i = 0; i != nAntecedents; ++i)
- {
- const Node& lit = conflict[i];
- os << "\n (bounded_aff_add _ _ _ _ _";
- os << "\n (bounded_aff_mul_c _ _ _ ";
- printRational(os, (*farkasCoefficients)[i].abs());
- os << " " << ProofManager::getLitName(lit.negate(), linearizedProofPrefix)
- << ")"
- << " ; " << lit;
- lemmaParen << ")";
- }
-
- os << "\n bounded_aff_ax_0_>=_0";
- os << lemmaParen.str(); // Close lemma proof
- }
- else
- {
- os << "\n; Arithmetic proofs which use reasoning more complex than Farkas "
- "proofs and bound tightening are currently unsupported\n"
- "(clausify_false trust)\n";
- }
-}
-
-void LFSCArithProof::printSortDeclarations(std::ostream& os, std::ostream& paren) {
- // Nothing to do here at this point.
-}
-
-void LFSCArithProof::printTermDeclarations(std::ostream& os, std::ostream& paren) {
- for (ExprSet::const_iterator it = d_declarations.begin();
- it != d_declarations.end();
- ++it)
- {
- Expr term = *it;
- Assert(term.isVariable());
- bool isInt = term.getType().isInteger();
- const char * var_type = isInt ? "int_var" : "real_var";
- os << "(% " << ProofManager::sanitize(term) << " " << var_type << "\n";
- os << "(@ " << CVC4_ARITH_VAR_TERM_PREFIX << ProofManager::sanitize(term)
- << " ";
- os << "(term_" << var_type << " " << ProofManager::sanitize(term) << ")\n";
- paren << ")";
- paren << ")";
- }
-}
-
-void LFSCArithProof::printDeferredDeclarations(std::ostream& os, std::ostream& paren) {
- // Nothing to do here at this point.
-}
-
-void LFSCArithProof::printAliasingDeclarations(std::ostream& os, std::ostream& paren, const ProofLetMap &globalLetMap) {
- // Nothing to do here at this point.
-}
-
-bool LFSCArithProof::printsAsBool(const Node& n)
-{
- // Our boolean variables and constants print as sort Bool.
- // All complex booleans print as formulas.
- return n.getType().isBoolean() and (n.isVar() or n.isConst());
-}
-
-TypeNode LFSCArithProof::equalityType(const Expr& left, const Expr& right)
-{
- return TypeNode::fromType(!left.getType().isInteger() ? left.getType() : right.getType());
-}
-
-} /* CVC4 namespace */
diff --git a/src/proof/arith_proof.h b/src/proof/arith_proof.h
deleted file mode 100644
index 832afcae0..000000000
--- a/src/proof/arith_proof.h
+++ /dev/null
@@ -1,217 +0,0 @@
-/********************* */
-/*! \file arith_proof.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir, Guy Katz, Mathias Preiner
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief Arith proof
- **
- ** Arith proof
- **/
-
-#include "cvc4_private.h"
-
-#ifndef CVC4__ARITH__PROOF_H
-#define CVC4__ARITH__PROOF_H
-
-#include <memory>
-#include <unordered_set>
-
-#include "expr/expr.h"
-#include "proof/arith_proof_recorder.h"
-#include "proof/proof_manager.h"
-#include "proof/theory_proof.h"
-#include "theory/uf/equality_engine.h"
-
-namespace CVC4 {
-
-//proof object outputted by TheoryArith
-class ProofArith : public Proof {
- public:
- ProofArith(std::shared_ptr<theory::eq::EqProof> pf) : d_proof(pf) {}
- void toStream(std::ostream& out) const override;
-
- private:
- static void toStreamLFSC(std::ostream& out, TheoryProof* tp,
- const theory::eq::EqProof& pf,
- const ProofLetMap& map);
- static Node toStreamRecLFSC(std::ostream& out, TheoryProof* tp,
- const theory::eq::EqProof& pf,
- unsigned tb, const ProofLetMap& map);
- // it is simply an equality engine proof
- std::shared_ptr<theory::eq::EqProof> d_proof;
-};
-
-namespace theory {
-namespace arith {
-class TheoryArith;
-}
-}
-
-typedef std::unordered_set<Type, TypeHashFunction > TypeSet;
-
-
-class ArithProof : public TheoryProof {
-protected:
- // std::map<Expr, std::string> d_constRationalString; // all the variable/function declarations
-
- // TypeSet d_sorts; // all the uninterpreted sorts in this theory
- ExprSet d_declarations; // all the variable/function declarations
-
- /**
- * Where farkas proofs of lemmas are stored.
- */
- proof::ArithProofRecorder d_recorder;
-
- theory::TheoryId getTheoryId() override;
-
- public:
- ArithProof(theory::arith::TheoryArith* arith, TheoryProofEngine* proofEngine);
-
- void registerTerm(Expr term) override;
-};
-
-class LFSCArithProof : public ArithProof {
-public:
- LFSCArithProof(theory::arith::TheoryArith* arith, TheoryProofEngine* proofEngine)
- : ArithProof(arith, proofEngine)
- {}
- void printOwnedTermAsType(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType) override;
- void printOwnedSort(Type type, std::ostream& os) override;
-
- /**
- * Returns the LFSC identifier for the operator of this node.
- *
- * e.g. "+_Real".
- *
- * Does not include any parens.
- *
- * Even if the operator is a comparison (e.g. >=) on integers, will not
- * return a purely `Int` predicate like ">=_Int". Instead this treats the
- * right hand side as a real.
- */
- static std::string getLfscFunction(const Node& n);
-
- /**
- * Print a rational number in LFSC format.
- * e.g. 5/8 or (~ 1/1)
- *
- * @param o ostream to print to.
- * @param r the rational to print
- */
- static void printRational(std::ostream& o, const Rational& r);
-
- /**
- * Print an integer in LFSC format.
- * e.g. 5 or (~ 1)
- *
- * @param o ostream to print to.
- * @param i the integer to print
- */
- static void printInteger(std::ostream& o, const Integer& i);
-
- /**
- * Print a value of type poly_formula_norm
- *
- * @param o ostream to print to
- * @param n node (asserted to be of the form [linear polynomial >= constant])
- */
- static void printLinearPolynomialPredicateNormalizer(std::ostream& o,
- const Node& n);
-
- /**
- * Print a value of type poly_norm
- *
- * @param o ostream to print to
- * @param n node (asserted to be a linear polynomial)
- */
- static void printLinearPolynomialNormalizer(std::ostream& o, const Node& n);
-
- /**
- * Print a value of type poly_norm
- *
- * @param o ostream to print to
- * @param n node (asserted to be a linear monomial)
- */
- static void printLinearMonomialNormalizer(std::ostream& o, const Node& n);
-
- /**
- * Print a LFSC rational
- *
- * @param o ostream to print to
- * @param n node (asserted to be a const rational)
- */
- static void printConstRational(std::ostream& o, const Node& n);
-
- /**
- * print the pn_var normalizer for n (type poly_norm)
- *
- * @param o the ostream to print to
- * @param n the node to print (asserted to be a variable)
- */
- static void printVariableNormalizer(std::ostream& o, const Node& n);
- /**
- * print a proof of the lemma
- *
- * First, we print linearity witnesses, i.e. witnesses that each literal has
- * the form:
- * [linear polynomial] >= 0 OR
- * [linear polynomial] > 0
- *
- * Then we use those witnesses to prove that the above linearized constraints
- * hold.
- *
- * Then we use the farkas coefficients to combine the literals into a
- * variable-free contradiction. The literals may be a mix of strict and
- * relaxed inequalities.
- *
- * @param lemma the set of literals disjoined in the lemma
- * @param os stream to print the proof to
- * @param paren global closing stream (unused)
- * @param map let map (unused)
- */
- void printTheoryLemmaProof(std::vector<Expr>& lemma,
- std::ostream& os,
- std::ostream& paren,
- const ProofLetMap& map) override;
- void printSortDeclarations(std::ostream& os, std::ostream& paren) override;
- void printTermDeclarations(std::ostream& os, std::ostream& paren) override;
- void printDeferredDeclarations(std::ostream& os,
- std::ostream& paren) override;
- void printAliasingDeclarations(std::ostream& os,
- std::ostream& paren,
- const ProofLetMap& globalLetMap) override;
-
- /**
- * Given a node that is an arith literal (an arith comparison or negation
- * thereof), prints a proof of that literal.
- *
- * If the node represents a tightenable bound (e.g. [Int] < 3) then it prints
- * a proof of the tightening instead. (e.g. [Int] <= 2).
- *
- * @return a pair comprising:
- * * the new node (after tightening) and
- * * a string proving it.
- */
- std::pair<Node, std::string> printProofAndMaybeTighten(const Node& bound);
-
- /**
- * Return whether this node, when serialized to LFSC, has sort `Bool`. Otherwise, the sort is `formula`.
- */
- bool printsAsBool(const Node& n) override;
-
- TypeNode equalityType(const Expr& left, const Expr& right) override;
-};
-
-
-}/* CVC4 namespace */
-
-#endif /* CVC4__ARITH__PROOF_H */
diff --git a/src/proof/arith_proof_recorder.cpp b/src/proof/arith_proof_recorder.cpp
deleted file mode 100644
index 01da402c9..000000000
--- a/src/proof/arith_proof_recorder.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-/********************* */
-/*! \file arith_proof_recorder.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief A class for recording the skeletons of arithmetic proofs at solve
- ** time so they can later be used during proof-production time.
- **/
-
-#include "proof/arith_proof_recorder.h"
-
-#include <algorithm>
-#include <vector>
-
-#include "base/map_util.h"
-
-namespace CVC4 {
-namespace proof {
-
-ArithProofRecorder::ArithProofRecorder() : d_lemmasToFarkasCoefficients()
-{
- // Nothing else
-}
-void ArithProofRecorder::saveFarkasCoefficients(
- Node conflict, theory::arith::RationalVectorCP farkasCoefficients)
-{
- // Verify that the conflict is a conjuction of (possibly negated) real bounds
- // Verify that the conflict is a conjunciton ...
- Assert(conflict.getKind() == kind::AND);
- Assert(conflict.getNumChildren() == farkasCoefficients->size());
- for (size_t i = 0, nchildren = conflict.getNumChildren(); i < nchildren; ++i)
- {
- const Node& child = conflict[i];
- // ... of possibly negated ...
- const Node& nonNegativeChild =
- child.getKind() == kind::NOT ? child[0] : child;
- // ... real bounds
- Assert(nonNegativeChild.getType().isBoolean()
- && nonNegativeChild[0].getType().isReal());
- }
- Debug("pf::arith") << "Saved Farkas Coefficients:" << std::endl;
- if (Debug.isOn("pf::arith"))
- {
- for (size_t i = 0, nchildren = conflict.getNumChildren(); i < nchildren;
- ++i)
- {
- const Node& child = conflict[i];
- const Rational& r = (*farkasCoefficients)[i];
- Debug("pf::arith") << " " << std::setw(8) << r;
- Debug("pf::arith") << " " << child << std::endl;
- }
- }
-
- std::set<Node> lits;
- std::copy(
- conflict.begin(), conflict.end(), std::inserter(lits, lits.begin()));
-
- d_lemmasToFarkasCoefficients[lits] =
- std::make_pair(std::move(conflict), *farkasCoefficients);
-}
-
-bool ArithProofRecorder::hasFarkasCoefficients(
- const std::set<Node>& conflict) const
-{
- return d_lemmasToFarkasCoefficients.find(conflict)
- != d_lemmasToFarkasCoefficients.end();
-}
-
-std::pair<Node, theory::arith::RationalVectorCP>
-ArithProofRecorder::getFarkasCoefficients(const std::set<Node>& conflict) const
-{
- if (auto *p = FindOrNull(d_lemmasToFarkasCoefficients, conflict))
- {
- return std::make_pair(p->first, &p->second);
- }
- else
- {
- return std::make_pair(Node(), theory::arith::RationalVectorCPSentinel);
- }
-}
-
-} // namespace proof
-} // namespace CVC4
diff --git a/src/proof/arith_proof_recorder.h b/src/proof/arith_proof_recorder.h
deleted file mode 100644
index 0669e5d16..000000000
--- a/src/proof/arith_proof_recorder.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/********************* */
-/*! \file arith_proof_recorder.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir, Mathias Preiner
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief A class for recording the skeletons of arithmetic proofs at solve
- ** time so they can later be used during proof-production time.
- **
- ** In particular, we're interested in proving bottom from a conjunction of
- ** theory literals.
- **
- ** For now, we assume that this can be done using a Farkas combination, and if
- ** that doesn't work for some reason, then we give up and "trust" the lemma.
- ** In the future we'll build support for more sophisticated reasoning.
- **
- ** Given this scope, our task is to...
- ** for each lemma (a set of literals)
- ** save the Farkas coefficients for those literals
- ** which requires we save an ordering of the literals
- ** and a parallel ordering of Farkas coefficients.
- **
- ** Farkas proofs have the following core structure:
- ** For a list of affine bounds: c[i] dot x >= b[i]
- ** (x is a vector of variables)
- ** (c[i] is a vector of coefficients)
- ** and a list of non-negative coefficients: f[i],
- ** compute
- **
- ** sum_i{ (c[i] dot x) * f[i] } and sum_i{b[i]*f[i]}
- **
- ** and then verify that the left is actually < the right, a contradiction
- **
- ** To be clear: this code does not check Farkas proofs, it just stores the
- ** information needed to write them.
- **/
-
-#include "cvc4_private.h"
-
-#ifndef CVC4__PROOF__ARITH_PROOF_RECORDER_H
-#define CVC4__PROOF__ARITH_PROOF_RECORDER_H
-
-#include <map>
-#include <set>
-
-#include "expr/node.h"
-#include "theory/arith/constraint_forward.h"
-
-namespace CVC4 {
-namespace proof {
-
-class ArithProofRecorder
-{
- public:
- ArithProofRecorder();
-
- /**
- * @brief For a set of incompatible literals, save the Farkas coefficients
- * demonstrating their incompatibility
- *
- * @param conflict a conjunction of conflicting literals
- * @param farkasCoefficients a list of rational coefficients which the literals
- * should be multiplied by (pairwise) to produce a contradiction.
- *
- * The orders of the two vectors must agree!
- */
- void saveFarkasCoefficients(
- Node conflict, theory::arith::RationalVectorCP farkasCoefficients);
-
- /**
- * @brief Determine whether some literals have a Farkas proof of their
- * incompatibility
- *
- * @param conflict a conjunction of (putatively) conflicting literals
- *
- * @return whether or not there is actually a proof for them.
- */
- bool hasFarkasCoefficients(const std::set<Node>& conflict) const;
-
- /**
- * @brief Get the Farkas Coefficients object
- *
- * @param conflict a conjunction of conflicting literals
- * @return theory::arith::RationalVectorCP -- the Farkas coefficients
- * Node -- a conjunction of the problem literals in coefficient order
- *
- * theory::arith::RationalVectorCPSentinel if there is no entry for
- * these lits
- */
- std::pair<Node, theory::arith::RationalVectorCP> getFarkasCoefficients(
- const std::set<Node>& conflict) const;
-
- protected:
- // For each lemma, save the Farkas coefficients of that lemma
- std::map<std::set<Node>, std::pair<Node, theory::arith::RationalVector>>
- d_lemmasToFarkasCoefficients;
-};
-
-} // namespace proof
-} // namespace CVC4
-
-#endif
diff --git a/src/proof/array_proof.cpp b/src/proof/array_proof.cpp
deleted file mode 100644
index 2d42a7489..000000000
--- a/src/proof/array_proof.cpp
+++ /dev/null
@@ -1,1350 +0,0 @@
-/********************* */
-/*! \file array_proof.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Guy Katz, Yoni Zohar, Liana Hadarean
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** [[ Add lengthier description here ]]
-
- ** \todo document this file
-
-**/
-
-#include "proof/array_proof.h"
-
-#include <stack>
-
-#include "proof/proof_manager.h"
-#include "proof/simplify_boolean_node.h"
-#include "proof/theory_proof.h"
-#include "theory/arrays/theory_arrays.h"
-
-namespace CVC4 {
-
-namespace {
-
-class ArrayProofPrinter : public theory::eq::EqProof::PrettyPrinter {
- public:
- ArrayProofPrinter(unsigned row, unsigned row1, unsigned ext)
- : d_row(row), d_row1(row1), d_ext(ext) {}
-
- std::string printTag(unsigned tag) override;
-
- private:
- const unsigned d_row;
- const unsigned d_row1;
- const unsigned d_ext;
-}; // class ArrayProofPrinter
-
-std::string ArrayProofPrinter::printTag(unsigned tag) {
- if (tag == theory::eq::MERGED_THROUGH_CONGRUENCE) return "Congruence";
- if (tag == theory::eq::MERGED_THROUGH_EQUALITY) return "Pure Equality";
- if (tag == theory::eq::MERGED_THROUGH_REFLEXIVITY) return "Reflexivity";
- if (tag == theory::eq::MERGED_THROUGH_CONSTANTS) return "Constants";
- if (tag == theory::eq::MERGED_THROUGH_TRANS) return "Transitivity";
-
- if (tag == d_row) return "Read Over Write";
- if (tag == d_row1) return "Read Over Write (1)";
- if (tag == d_ext) return "Extensionality";
-
- std::ostringstream result;
- result << tag;
- return result.str();
-}
-
-} // namespace
-
-
-
-ProofArray::ProofArray(std::shared_ptr<theory::eq::EqProof> pf,
- unsigned row,
- unsigned row1,
- unsigned ext)
- : d_proof(pf), d_reasonRow(row), d_reasonRow1(row1), d_reasonExt(ext)
-{
-}
-
-void ProofArray::toStream(std::ostream& out) const
-{
- ProofLetMap map;
- toStream(out, map);
-}
-
-void ProofArray::toStream(std::ostream& out, const ProofLetMap& map) const
-{
- Trace("pf::array") << "; Print Array proof..." << std::endl;
- toStreamLFSC(out, ProofManager::getArrayProof(), *d_proof, map);
- Debug("pf::array") << "; Print Array proof done!" << std::endl;
-}
-
-void ProofArray::toStreamLFSC(std::ostream& out,
- TheoryProof* tp,
- const theory::eq::EqProof& pf,
- const ProofLetMap& map) const
-{
- Debug("pf::array") << "Printing array proof in LFSC : " << std::endl;
- ArrayProofPrinter proofPrinter(d_reasonRow, d_reasonRow1, d_reasonExt);
- pf.debug_print("pf::array", 0, &proofPrinter);
- Debug("pf::array") << std::endl;
- toStreamRecLFSC(out, tp, pf, 0, map);
- Debug("pf::array") << "Printing array proof in LFSC DONE" << std::endl;
-}
-
-Node ProofArray::toStreamRecLFSC(std::ostream& out,
- TheoryProof* tp,
- const theory::eq::EqProof& pf,
- unsigned tb,
- const ProofLetMap& map) const
-{
- Debug("pf::array") << std::endl
- << std::endl
- << "toStreamRecLFSC called. tb = " << tb
- << " . proof:" << std::endl;
- ArrayProofPrinter proofPrinter(d_reasonRow, d_reasonRow1, d_reasonExt);
- if(tb == 0) {
- std::shared_ptr<theory::eq::EqProof> subTrans =
- std::make_shared<theory::eq::EqProof>();
-
- int neg = tp->assertAndPrint(pf, map, subTrans, &proofPrinter);
-
- Node n1;
- std::stringstream ss, ss2;
- Debug("mgdx") << "\nsubtrans has " << subTrans->d_children.size() << " children\n";
- bool disequalityFound = (neg >= 0);
-
- if (!disequalityFound || pf.d_children.size() > 2)
- {
- n1 = toStreamRecLFSC(ss, tp, *subTrans, 1, map);
- } else {
- n1 = toStreamRecLFSC(ss, tp, *(subTrans->d_children[0]), 1, map);
- Debug("mgdx") << "\nsubTrans unique child "
- << subTrans->d_children[0]->d_id
- << " was proven\ngot: " << n1 << std::endl;
- }
-
- out << "(clausify_false (contra _ ";
- if (disequalityFound) {
- Node n2 = pf.d_children[neg]->d_node;
- Assert(n2.getKind() == kind::NOT);
- Debug("mgdx") << "\nhave proven: " << n1 << std::endl;
- Debug("mgdx") << "n2 is " << n2 << std::endl;
- Debug("mgdx") << "n2->d_id is " << pf.d_children[neg]->d_id << std::endl;
- Debug("mgdx") << "n2[0] is " << n2[0] << std::endl;
-
- if (n2[0].getNumChildren() > 0) { Debug("mgdx") << "\nn2[0]: " << n2[0][0] << std::endl; }
- if (n1.getNumChildren() > 1) { Debug("mgdx") << "n1[1]: " << n1[1] << std::endl; }
-
- if ((pf.d_children[neg]->d_id == d_reasonExt) ||
- (pf.d_children[neg]->d_id == theory::eq::MERGED_THROUGH_TRANS)) {
- // Ext case: The negative node was created by an EXT rule; e.g. it is a[k]!=b[k], due to a!=b.
- out << ss.str();
- out << " ";
- toStreamRecLFSC(ss2, tp, *pf.d_children[neg], 1, map);
- out << ss2.str();
- } else if (n2[0].getKind() == kind::APPLY_UF) {
- out << "(trans _ _ _ _ ";
- out << "(symm _ _ _ ";
- out << ss.str();
- out << ") (pred_eq_f _ " << ProofManager::getLitName(n2[0]) << ")) t_t_neq_f))" << std::endl;
- } else {
- Assert((n1[0] == n2[0][0] && n1[1] == n2[0][1])
- || (n1[1] == n2[0][0] && n1[0] == n2[0][1]));
- if(n1[1] == n2[0][0]) {
- out << "(symm _ _ _ " << ss.str() << ")";
- } else {
- out << ss.str();
- }
- Debug("pf::array") << "ArrayProof::toStream: getLitName( " << n2[0] << " ) = " <<
- ProofManager::getLitName(n2[0]) << std::endl;
-
- out << " " << ProofManager::getLitName(n2[0]);
- }
- } else {
- Node n2 = pf.d_node;
- Assert(n2.getKind() == kind::EQUAL);
- Assert((n1[0] == n2[0] && n1[1] == n2[1])
- || (n1[1] == n2[0] && n1[0] == n2[1]));
-
- out << ss.str();
- out << " ";
- ProofManager::getTheoryProofEngine()->printConstantDisequalityProof(out,
- n1[0].toExpr(),
- n1[1].toExpr(),
- map);
- }
-
- out << "))" << std::endl;
- return Node();
- }
-
- switch (pf.d_id)
- {
- case theory::eq::MERGED_THROUGH_CONGRUENCE:
- {
- Debug("mgd") << "\nok, looking at congruence:\n";
- pf.debug_print("mgd", 0, &proofPrinter);
- std::stack<const theory::eq::EqProof*> stk;
- for (const theory::eq::EqProof* pf2 = &pf;
- pf2->d_id == theory::eq::MERGED_THROUGH_CONGRUENCE;
- pf2 = pf2->d_children[0].get())
- {
- Debug("mgd") << "Looking at pf2 with d_node: " << pf2->d_node
- << std::endl;
- Assert(!pf2->d_node.isNull());
- Assert(pf2->d_node.getKind() == kind::PARTIAL_APPLY_UF
- || pf2->d_node.getKind() == kind::BUILTIN
- || pf2->d_node.getKind() == kind::APPLY_UF
- || pf2->d_node.getKind() == kind::SELECT
- || pf2->d_node.getKind() == kind::PARTIAL_SELECT_0
- || pf2->d_node.getKind() == kind::PARTIAL_SELECT_1
- || pf2->d_node.getKind() == kind::STORE);
-
- Assert(pf2->d_children.size() == 2);
- out << "(cong _ _ _ _ _ _ ";
- stk.push(pf2);
- }
- Assert(stk.top()->d_children[0]->d_id
- != theory::eq::MERGED_THROUGH_CONGRUENCE);
- // NodeBuilder<> b1(kind::PARTIAL_APPLY_UF),
- // b2(kind::PARTIAL_APPLY_UF);
- NodeBuilder<> b1, b2;
-
- const theory::eq::EqProof* pf2 = stk.top();
- stk.pop();
- Assert(pf2->d_id == theory::eq::MERGED_THROUGH_CONGRUENCE);
- Node n1 = toStreamRecLFSC(out, tp, *(pf2->d_children[0]), tb + 1, map);
- out << " ";
- std::stringstream ss;
- Node n2 = toStreamRecLFSC(ss, tp, *(pf2->d_children[1]), tb + 1, map);
-
- Debug("mgd") << "\nok, in FIRST cong[" << stk.size() << "]"
- << "\n";
- pf2->debug_print("mgd", 0, &proofPrinter);
- // Temp
- Debug("mgd") << "n1 is a proof for: " << pf2->d_children[0]->d_node
- << ". It is: " << n1 << std::endl;
- Debug("mgd") << "n2 is a proof for: " << pf2->d_children[1]->d_node
- << ". It is: " << n2 << std::endl;
- //
- Debug("mgd") << "looking at " << pf2->d_node << "\n";
- Debug("mgd") << " " << n1 << "\n";
- Debug("mgd") << " " << n2 << "\n";
-
- int side = 0;
- if (tp->match(pf2->d_node, n1[0]))
- {
- Debug("mgd") << "SIDE IS 0\n";
- side = 0;
- }
- else
- {
- Debug("mgd") << "SIDE IS 1\n";
- if (!tp->match(pf2->d_node, n1[1]))
- {
- Debug("mgd") << "IN BAD CASE, our first subproof is\n";
- pf2->d_children[0]->debug_print("mgd", 0, &proofPrinter);
- }
- Assert(tp->match(pf2->d_node, n1[1]));
- side = 1;
- }
-
- if (n1[side].getKind() == kind::APPLY_UF
- || n1[side].getKind() == kind::PARTIAL_APPLY_UF
- || n1[side].getKind() == kind::SELECT
- || n1[side].getKind() == kind::PARTIAL_SELECT_1
- || n1[side].getKind() == kind::STORE)
- {
- if (n1[side].getKind() == kind::APPLY_UF
- || n1[side].getKind() == kind::PARTIAL_APPLY_UF)
- {
- b1 << kind::PARTIAL_APPLY_UF;
- b1 << n1[side].getOperator();
- }
- else if (n1[side].getKind() == kind::SELECT
- || n1[side].getKind() == kind::PARTIAL_SELECT_1)
- {
- // b1 << n1[side].getKind();
- b1 << kind::SELECT;
- } else {
- b1 << kind::PARTIAL_APPLY_UF;
- b1 << ProofManager::currentPM()->mkOp(n1[side].getOperator());
- }
- b1.append(n1[side].begin(), n1[side].end());
- }
- else if (n1[side].getKind() == kind::PARTIAL_SELECT_0) {
- b1 << kind::PARTIAL_SELECT_1;
- } else {
- b1 << n1[side];
- }
-
- if(n1[1-side].getKind() == kind::PARTIAL_APPLY_UF ||
- n1[1-side].getKind() == kind::APPLY_UF ||
- n1[1-side].getKind() == kind::SELECT ||
- n1[1-side].getKind() == kind::PARTIAL_SELECT_1 ||
- n1[1-side].getKind() == kind::STORE) {
- if(n1[1-side].getKind() == kind::APPLY_UF ||
- n1[1-side].getKind() == kind::PARTIAL_APPLY_UF) {
- b2 << kind::PARTIAL_APPLY_UF;
- b2 << n1[1-side].getOperator();
- } else if (n1[1-side].getKind() == kind::SELECT || n1[1-side].getKind() == kind::PARTIAL_SELECT_1) {
- // b2 << n1[1-side].getKind();
- b2 << kind::SELECT;
- } else {
- b2 << kind::PARTIAL_APPLY_UF;
- b2 << ProofManager::currentPM()->mkOp(n1[1-side].getOperator());
- }
- b2.append(n1[1-side].begin(), n1[1-side].end());
- } else if (n1[1-side].getKind() == kind::PARTIAL_SELECT_0) {
- b2 << kind::PARTIAL_SELECT_1;
- } else {
- b2 << n1[1-side];
- }
- Debug("mgd") << "pf2->d_node " << pf2->d_node << std::endl;
- Debug("mgd") << "b1.getNumChildren() " << b1.getNumChildren() << std::endl;
- Debug("mgd") << "n1 " << n1 << std::endl;
- Debug("mgd") << "n2 " << n2 << std::endl;
- // These debug prints can cause a problem if we're constructing a SELECT node and it doesn't have enough
- // children yet.
- // Debug("mgd") << "b1 " << b1 << std::endl;
- // Debug("mgd") << "b2 " << b2 << std::endl;
- Debug("mgd") << "side " << side << std::endl;
- Debug("mgd") << "pf2->d_node's number of children: " << pf2->d_node.getNumChildren() << std::endl;
- Debug("mgd") << "pf2->d_node's meta kind: " << pf2->d_node.getMetaKind() << std::endl;
- Debug("mgd") << "Is this meta kind considered parameterized? " << (pf2->d_node.getMetaKind() == kind::metakind::PARAMETERIZED) << std::endl;
-
- if(pf2->d_node[b1.getNumChildren() +
- (n1[side].getKind() == kind::PARTIAL_SELECT_0 ? 1 : 0) +
- (n1[side].getKind() == kind::PARTIAL_SELECT_1 ? 1 : 0) -
- (pf2->d_node.getMetaKind() == kind::metakind::PARAMETERIZED ? 0 : 1)] == n2[side]) {
- b1 << n2[side];
- b2 << n2[1-side];
- out << ss.str();
- } else {
- Assert(
- pf2->d_node[b1.getNumChildren()
- + (n1[side].getKind() == kind::PARTIAL_SELECT_0 ? 1 : 0)
- + (n1[side].getKind() == kind::PARTIAL_SELECT_1 ? 1 : 0)
- - (pf2->d_node.getMetaKind()
- == kind::metakind::PARAMETERIZED
- ? 0
- : 1)]
- == n2[1 - side]);
- b1 << n2[1-side];
- b2 << n2[side];
- out << "(symm _ _ _ " << ss.str() << ")";
- }
-
- Debug("mgd") << "After first insertion:" << std::endl;
- Debug("mgd") << "b1 " << b1 << std::endl;
- Debug("mgd") << "b2 " << b2 << std::endl;
-
- out << ")";
- while(!stk.empty()) {
-
- Debug("mgd") << "\nMORE TO DO\n";
-
- pf2 = stk.top();
- stk.pop();
- Assert(pf2->d_id == theory::eq::MERGED_THROUGH_CONGRUENCE);
- out << " ";
- ss.str("");
- n2 = toStreamRecLFSC(ss, tp, *(pf2->d_children[1]), tb + 1, map);
-
- Debug("mgd") << "\nok, in cong[" << stk.size() << "]" << "\n";
- Debug("mgd") << "looking at " << pf2->d_node << "\n";
- Debug("mgd") << " " << n1 << "\n";
- Debug("mgd") << " " << n2 << "\n";
- Debug("mgd") << " " << b1 << "\n";
- Debug("mgd") << " " << b2 << "\n";
- if(pf2->d_node[b1.getNumChildren()] == n2[side]) {
- b1 << n2[side];
- b2 << n2[1-side];
- out << ss.str();
- } else {
- Assert(pf2->d_node[b1.getNumChildren()] == n2[1 - side]);
- b1 << n2[1-side];
- b2 << n2[side];
- out << "(symm _ _ _ " << ss.str() << ")";
- }
- out << ")";
- }
- n1 = b1;
- n2 = b2;
-
- Debug("mgd") << "at end assert!" << std::endl
- << "pf2->d_node = " << pf2->d_node << std::endl
- << "n1 (assigned from b1) = " << n1 << std::endl
- << "n2 (assigned from b2) = " << n2 << std::endl;
-
- if(pf2->d_node.getKind() == kind::PARTIAL_APPLY_UF) {
- Assert(n1 == pf2->d_node);
- }
-
- Debug("mgd") << "n1.getOperator().getType().getNumChildren() = "
- << n1.getOperator().getType().getNumChildren() << std::endl;
- Debug("mgd") << "n1.getNumChildren() + 1 = "
- << n1.getNumChildren() + 1 << std::endl;
-
- Assert(!(
- (n1.getKind() == kind::PARTIAL_SELECT_0 && n1.getNumChildren() == 2)));
- if (n1.getKind() == kind::PARTIAL_SELECT_1 && n1.getNumChildren() == 2) {
- Debug("mgd") << "Finished a SELECT. Updating.." << std::endl;
- b1.clear(kind::SELECT);
- b1.append(n1.begin(), n1.end());
- n1 = b1;
- Debug("mgd") << "New n1: " << n1 << std::endl;
- } else if(n1.getOperator().getType().getNumChildren() == n1.getNumChildren() + 1) {
- if(ProofManager::currentPM()->hasOp(n1.getOperator())) {
- b1.clear(ProofManager::currentPM()->lookupOp(n2.getOperator()).getConst<Kind>());
- } else {
- b1.clear(kind::APPLY_UF);
- b1 << n1.getOperator();
- }
- b1.append(n1.begin(), n1.end());
- n1 = b1;
- Debug("mgd") << "at[2] end assert, got " << pf2->d_node << " and " << n1 << std::endl;
- if(pf2->d_node.getKind() == kind::APPLY_UF) {
- Assert(n1 == pf2->d_node);
- }
- }
-
- Debug("mgd") << "n2.getOperator().getType().getNumChildren() = "
- << n2.getOperator().getType().getNumChildren() << std::endl;
- Debug("mgd") << "n2.getNumChildren() + 1 = "
- << n2.getNumChildren() + 1 << std::endl;
-
- Assert(!(
- (n2.getKind() == kind::PARTIAL_SELECT_0 && n2.getNumChildren() == 2)));
- if (n2.getKind() == kind::PARTIAL_SELECT_1 && n2.getNumChildren() == 2) {
- Debug("mgd") << "Finished a SELECT. Updating.." << std::endl;
- b2.clear(kind::SELECT);
- b2.append(n2.begin(), n2.end());
- n2 = b2;
- Debug("mgd") << "New n2: " << n2 << std::endl;
- } else if(n2.getOperator().getType().getNumChildren() == n2.getNumChildren() + 1) {
- if(ProofManager::currentPM()->hasOp(n2.getOperator())) {
- b2.clear(ProofManager::currentPM()->lookupOp(n2.getOperator()).getConst<Kind>());
- } else {
- b2.clear(kind::APPLY_UF);
- b2 << n2.getOperator();
- }
- b2.append(n2.begin(), n2.end());
- n2 = b2;
- }
- Node n = (side == 0 ? n1.eqNode(n2) : n2.eqNode(n1));
-
- Debug("mgdx") << "\ncong proved: " << n << "\n";
- return n;
- }
- case theory::eq::MERGED_THROUGH_REFLEXIVITY:
- {
- Assert(!pf.d_node.isNull());
- Assert(pf.d_children.empty());
- out << "(refl _ ";
- tp->printTerm(NodeManager::currentNM()->toExpr(pf.d_node), out, map);
- out << ")";
- return pf.d_node.eqNode(pf.d_node);
- }
- case theory::eq::MERGED_THROUGH_EQUALITY:
- {
- Assert(!pf.d_node.isNull());
- Assert(pf.d_children.empty());
- Debug("pf::array") << "ArrayProof::toStream: getLitName( " << pf.d_node.negate() << " ) = " <<
- ProofManager::getLitName(pf.d_node.negate()) << std::endl;
- out << ProofManager::getLitName(pf.d_node.negate());
- return pf.d_node;
- }
-
- case theory::eq::MERGED_THROUGH_TRANS:
- {
- bool firstNeg = false;
- bool secondNeg = false;
-
- Assert(!pf.d_node.isNull());
- Assert(pf.d_children.size() >= 2);
- std::stringstream ss;
- Debug("mgd") << "\ndoing trans proof[[\n";
- pf.debug_print("mgd", 0, &proofPrinter);
- Debug("mgd") << "\n";
-
- pf.d_children[0]->d_node = simplifyBooleanNode(pf.d_children[0]->d_node);
-
- Node n1 = toStreamRecLFSC(ss, tp, *(pf.d_children[0]), tb + 1, map);
- Debug("mgd") << "\ndoing trans proof, got n1 " << n1 << "\n";
- if(tb == 1) {
- Debug("mgdx") << "\ntrans proof[0], got n1 " << n1 << "\n";
- }
-
- bool identicalEqualities = false;
- bool evenLengthSequence;
- std::stringstream dontCare;
- Node nodeAfterEqualitySequence =
- toStreamRecLFSC(dontCare, tp, *(pf.d_children[0]), tb + 1, map);
-
- std::map<size_t, Node> childToStream;
-
- std::pair<Node, Node> nodePair;
- for (size_t i = 1; i < pf.d_children.size(); ++i)
- {
- std::stringstream ss1(ss.str()), ss2;
- ss.str("");
-
- // In congruences, we can have something like a[x] - it's important to
- // keep these,
- // and not turn them into (a[x]=true), because that will mess up the
- // congruence application
- // later.
-
- if (pf.d_children[i]->d_id != theory::eq::MERGED_THROUGH_CONGRUENCE)
- pf.d_children[i]->d_node =
- simplifyBooleanNode(pf.d_children[i]->d_node);
-
- // It is possible that we've already converted the i'th child to stream.
- // If so,
- // use previously stored result. Otherwise, convert and store.
- Node n2;
- if (childToStream.find(i) != childToStream.end())
- n2 = childToStream[i];
- else
- {
- n2 = toStreamRecLFSC(ss2, tp, *(pf.d_children[i]), tb + 1, map);
- childToStream[i] = n2;
- }
-
- Debug("mgd") << "\ndoing trans proof, got (first) n2 " << n2 << "\n";
-
- // The following branch is dedicated to handling sequences of identical
- // equalities,
- // i.e. trans[ a=b, a=b, a=b ].
- //
- // There are two cases:
- // 1. The number of equalities is odd. Then, the sequence can be
- // collapsed to just one equality,
- // i.e. a=b.
- // 2. The number of equalities is even. Now, we have two options: a=a
- // or b=b. To determine this,
- // we look at the node after the equality sequence. If it needs a,
- // we go for a=a; and if it needs
- // b, we go for b=b. If there is no following node, we look at the
- // goal of the transitivity proof,
- // and use it to determine which option we need.
-
- if (n2.getKind() == kind::EQUAL)
- {
- if (((n1[0] == n2[0]) && (n1[1] == n2[1]))
- || ((n1[0] == n2[1]) && (n1[1] == n2[0])))
- {
- // We are in a sequence of identical equalities
-
- Debug("pf::array") << "Detected identical equalities: " << std::endl
- << "\t" << n1 << std::endl;
-
- if (!identicalEqualities)
- {
- // The sequence of identical equalities has started just now
- identicalEqualities = true;
-
- Debug("pf::array")
- << "The sequence is just beginning. Determining length..."
- << std::endl;
-
- // Determine whether the length of this sequence is odd or even.
- evenLengthSequence = true;
- bool sequenceOver = false;
- size_t j = i + 1;
-
- while (j < pf.d_children.size() && !sequenceOver)
- {
- std::stringstream ignore;
- nodeAfterEqualitySequence =
- toStreamRecLFSC(ignore, tp, *(pf.d_children[j]), tb + 1, map);
- if (((nodeAfterEqualitySequence[0] == n1[0])
- && (nodeAfterEqualitySequence[1] == n1[1]))
- || ((nodeAfterEqualitySequence[0] == n1[1])
- && (nodeAfterEqualitySequence[1] == n1[0])))
- {
- evenLengthSequence = !evenLengthSequence;
- }
- else
- {
- sequenceOver = true;
- }
-
- ++j;
- }
-
- nodePair =
- tp->identicalEqualitiesPrinterHelper(evenLengthSequence,
- sequenceOver,
- pf,
- map,
- ss1.str(),
- &ss,
- n1,
- nodeAfterEqualitySequence);
- n1 = nodePair.first;
- nodeAfterEqualitySequence = nodePair.second;
- }
- else
- {
- ss.str(ss1.str());
- }
-
- // Ignore the redundancy.
- continue;
- }
- }
-
- if (identicalEqualities)
- {
- // We were in a sequence of identical equalities, but it has now ended.
- // Resume normal operation.
- identicalEqualities = false;
- }
-
- Debug("mgd") << "\ndoing trans proof, got n2 " << n2 << "\n";
- if (tb == 1)
- {
- Debug("mgdx") << "\ntrans proof[" << i << "], got n2 " << n2 << "\n";
- Debug("mgdx") << (n2.getKind() == kind::EQUAL) << "\n";
-
- if ((n1.getNumChildren() >= 2) && (n2.getNumChildren() >= 2))
- {
- Debug("mgdx") << n1[0].getId() << " " << n1[1].getId() << " / "
- << n2[0].getId() << " " << n2[1].getId() << "\n";
- Debug("mgdx") << n1[0].getId() << " " << n1[0] << "\n";
- Debug("mgdx") << n1[1].getId() << " " << n1[1] << "\n";
- Debug("mgdx") << n2[0].getId() << " " << n2[0] << "\n";
- Debug("mgdx") << n2[1].getId() << " " << n2[1] << "\n";
- Debug("mgdx") << (n1[0] == n2[0]) << "\n";
- Debug("mgdx") << (n1[1] == n2[1]) << "\n";
- Debug("mgdx") << (n1[0] == n2[1]) << "\n";
- Debug("mgdx") << (n1[1] == n2[0]) << "\n";
- }
- }
-
- // We can hadnle one of the equalities being negative, but not both
- Assert((n1.getKind() != kind::NOT) || (n2.getKind() != kind::NOT));
-
- firstNeg = false;
- secondNeg = false;
-
- if (n1.getKind() == kind::NOT) {
- Debug("mgdx") << "n1 is negative" << std::endl;
- Debug("pf::array") << "n1 = " << n1 << ", n2 = " << n2 << std::endl;
- firstNeg = true;
- ss << "(negtrans1 _ _ _ _ ";
- n1 = n1[0];
- } else if (n2.getKind() == kind::NOT) {
- Debug("mgdx") << "n2 is negative" << std::endl;
- Debug("pf::array") << "n1 = " << n1 << ", n2 = " << n2 << std::endl;
- secondNeg = true;
- ss << "(negtrans2 _ _ _ _ ";
- n2 = n2[0];
- } else {
- ss << "(trans _ _ _ _ ";
- }
-
- if((n2.getKind() == kind::EQUAL) && (n1.getKind() == kind::EQUAL))
- // Both elements of the transitivity rule are equalities/iffs
- {
- if(n1[0] == n2[0]) {
- if(tb == 1) { Debug("mgdx") << "case 1\n"; }
- n1 = n1[1].eqNode(n2[1]);
- ss << (firstNeg ? "(negsymm _ _ _ " : "(symm _ _ _ ") << ss1.str() << ") " << ss2.str();
- } else if(n1[1] == n2[1]) {
- if(tb == 1) { Debug("mgdx") << "case 2\n"; }
- n1 = n1[0].eqNode(n2[0]);
- ss << ss1.str() << (secondNeg ? " (negsymm _ _ _ " : " (symm _ _ _ " ) << ss2.str() << ")";
- } else if(n1[0] == n2[1]) {
- if(tb == 1) { Debug("mgdx") << "case 3\n"; }
- if(!firstNeg && !secondNeg) {
- n1 = n2[0].eqNode(n1[1]);
- ss << ss2.str() << " " << ss1.str();
- } else if (firstNeg) {
- n1 = n1[1].eqNode(n2[0]);
- ss << " (negsymm _ _ _ " << ss1.str() << ") (symm _ _ _ " << ss2.str() << ")";
- } else {
- Assert(secondNeg);
- n1 = n1[1].eqNode(n2[0]);
- ss << " (symm _ _ _ " << ss1.str() << ") (negsymm _ _ _ " << ss2.str() << ")";
- }
- if(tb == 1) { Debug("mgdx") << "++ proved " << n1 << "\n"; }
- } else if(n1[1] == n2[0]) {
- if(tb == 1) { Debug("mgdx") << "case 4\n"; }
- n1 = n1[0].eqNode(n2[1]);
- ss << ss1.str() << " " << ss2.str();
- } else {
- Warning() << "\n\ntrans proof failure at step " << i << "\n\n";
- Warning() << "0 proves " << n1 << "\n";
- Warning() << "1 proves " << n2 << "\n\n";
- pf.debug_print("mgdx", 0, &proofPrinter);
- //toStreamRec(Warning.getStream(), pf, 0);
- Warning() << "\n\n";
- Unreachable();
- }
- Debug("mgd") << "++ trans proof[" << i << "], now have " << n1 << std::endl;
- } else if(n1.getKind() == kind::EQUAL) {
- // n1 is an equality/iff, but n2 is a predicate
- if(n1[0] == n2) {
- n1 = n1[1];
- ss << (firstNeg ? "(negsymm _ _ _ " : "(symm _ _ _ ")
- << ss1.str() << ") (pred_eq_t _ " << ss2.str() << ")";
- } else if(n1[1] == n2) {
- n1 = n1[0];
- ss << ss1.str() << " (pred_eq_t _ " << ss2.str() << ")";
- } else {
- Unreachable();
- }
- } else if(n2.getKind() == kind::EQUAL) {
- // n2 is an equality/iff, but n1 is a predicate
- if(n2[0] == n1) {
- n1 = n2[1];
- ss << (secondNeg ? "(negsymm _ _ _ " : "(symm _ _ _ ")
- << ss2.str() << ") (pred_eq_t _ " << ss1.str() << ")";
- } else if(n2[1] == n1) {
- n1 = n2[0];
- ss << ss2.str() << " (pred_eq_t _ " << ss1.str() << ")";
- } else {
- Unreachable();
- }
- } else {
- // Both n1 and n2 are prediacates. Don't know what to do...
- Unreachable();
- }
-
- ss << ")";
-
- if (firstNeg || secondNeg) {
- n1 = (n1.getKind() == kind::NOT) ? n1[0] : n1.notNode();
- }
- }
-
- out << ss.str();
- Debug("mgd") << "\n++ trans proof done, have proven " << n1 << std::endl;
- //return (firstNeg || secondNeg) ? n1.notNode() : n1;
- return n1;
- }
-
- case theory::eq::MERGED_THROUGH_CONSTANTS:
- {
- Debug("pf::array") << "Proof for: " << pf.d_node << std::endl;
- Assert(pf.d_node.getKind() == kind::NOT);
- Node n = pf.d_node[0];
- Assert(n.getKind() == kind::EQUAL);
- Assert(n.getNumChildren() == 2);
- Assert(n[0].isConst() && n[1].isConst());
-
- ProofManager::getTheoryProofEngine()->printConstantDisequalityProof(
- out, n[0].toExpr(), n[1].toExpr(), map);
- return pf.d_node;
- }
-
- default:
- {
- if (pf.d_id == d_reasonRow)
- {
- Debug("mgd") << "row lemma: " << pf.d_node << std::endl;
- Assert(pf.d_node.getKind() == kind::EQUAL);
-
- if (pf.d_node[1].getKind() == kind::SELECT)
- {
- // This is the case where ((a[i]:=t)[k] == a[k]), and the sub-proof
- // explains why (i != k).
- TNode t1, t2, t3, t4;
- Node ret;
- if (pf.d_node[1].getKind() == kind::SELECT
- && pf.d_node[1][0].getKind() == kind::STORE
- && pf.d_node[0].getKind() == kind::SELECT
- && pf.d_node[0][0] == pf.d_node[1][0][0]
- && pf.d_node[0][1] == pf.d_node[1][1])
- {
- t2 = pf.d_node[1][0][1];
- t3 = pf.d_node[1][1];
- t1 = pf.d_node[0][0];
- t4 = pf.d_node[1][0][2];
- ret = pf.d_node[1].eqNode(pf.d_node[0]);
- Debug("mgd") << "t1 " << t1 << "\nt2 " << t2 << "\nt3 " << t3
- << "\nt4 " << t4 << "\n";
- }
- else
- {
- Assert(pf.d_node[0].getKind() == kind::SELECT
- && pf.d_node[0][0].getKind() == kind::STORE
- && pf.d_node[1].getKind() == kind::SELECT
- && pf.d_node[1][0] == pf.d_node[0][0][0]
- && pf.d_node[1][1] == pf.d_node[0][1]);
- t2 = pf.d_node[0][0][1];
- t3 = pf.d_node[0][1];
- t1 = pf.d_node[1][0];
- t4 = pf.d_node[0][0][2];
- ret = pf.d_node;
- Debug("mgd") << "t1 " << t1 << "\nt2 " << t2 << "\nt3 " << t3
- << "\nt4 " << t4 << "\n";
- }
-
- // inner index != outer index
- // t3 is the outer index
-
- Assert(pf.d_children.size() == 1);
- std::stringstream ss;
- Node subproof =
- toStreamRecLFSC(ss, tp, *(pf.d_children[0]), tb + 1, map);
-
- out << "(row _ _ ";
- tp->printTerm(t2.toExpr(), out, map);
- out << " ";
- tp->printTerm(t3.toExpr(), out, map);
- out << " ";
- tp->printTerm(t1.toExpr(), out, map);
- out << " ";
- tp->printTerm(t4.toExpr(), out, map);
- out << " ";
-
- Debug("pf::array") << "pf.d_children[0]->d_node is: "
- << pf.d_children[0]->d_node << ". t3 is: " << t3
- << std::endl
- << "subproof is: " << subproof << std::endl;
-
- Debug("pf::array") << "Subproof is: " << ss.str() << std::endl;
-
- // The subproof needs to show that t2 != t3. This can either be a direct
- // disequality,
- // or, if (wlog) t2 is constant, it can show that t3 is equal to another
- // constant.
- if (subproof.getKind() == kind::NOT)
- {
- // The subproof is for t2 != t3 (or t3 != t2)
- if (subproof[0][1] == t3)
- {
- Debug("pf::array") << "Dont need symmetry!" << std::endl;
- out << ss.str();
- }
- else
- {
- Debug("pf::array") << "Need symmetry!" << std::endl;
- out << "(negsymm _ _ _ " << ss.str() << ")";
- }
- }
- else
- {
- // Either t2 or t3 is a constant.
- Assert(subproof.getKind() == kind::EQUAL);
- Assert(subproof[0].isConst() || subproof[1].isConst());
- Assert(t2.isConst() || t3.isConst());
- Assert(!(t2.isConst() && t3.isConst()));
-
- bool t2IsConst = t2.isConst();
- if (subproof[0].isConst())
- {
- if (t2IsConst)
- {
- // (t3 == subproof[1]) == subproof[0] != t2
- // goal is t2 != t3
- // subproof already shows constant = t3
- Assert(t3 == subproof[1]);
- out << "(negtrans _ _ _ _ ";
- tp->printConstantDisequalityProof(
- out, t2.toExpr(), subproof[0].toExpr(), map);
- out << " ";
- out << ss.str();
- out << ")";
- }
- else
- {
- Assert(t2 == subproof[1]);
- out << "(negsymm _ _ _ ";
- out << "(negtrans _ _ _ _ ";
- tp->printConstantDisequalityProof(
- out, t3.toExpr(), subproof[0].toExpr(), map);
- out << " ";
- out << ss.str();
- out << "))";
- }
- }
- else
- {
- if (t2IsConst)
- {
- // (t3 == subproof[0]) == subproof[1] != t2
- // goal is t2 != t3
- // subproof already shows constant = t3
- Assert(t3 == subproof[0]);
- out << "(negtrans _ _ _ _ ";
- tp->printConstantDisequalityProof(
- out, t2.toExpr(), subproof[1].toExpr(), map);
- out << " ";
- out << "(symm _ _ _ " << ss.str() << ")";
- out << ")";
- }
- else
- {
- Assert(t2 == subproof[0]);
- out << "(negsymm _ _ _ ";
- out << "(negtrans _ _ _ _ ";
- tp->printConstantDisequalityProof(
- out, t3.toExpr(), subproof[1].toExpr(), map);
- out << " ";
- out << "(symm _ _ _ " << ss.str() << ")";
- out << "))";
- }
- }
- }
-
- out << ")";
- return ret;
- }
- else
- {
- Debug("pf::array") << "In the case of NEGATIVE ROW" << std::endl;
-
- Debug("pf::array") << "pf.d_children[0]->d_node is: "
- << pf.d_children[0]->d_node << std::endl;
-
- // This is the case where (i == k), and the sub-proof explains why
- // ((a[i]:=t)[k] != a[k])
-
- // If we wanted to remove the need for "negativerow", we would need to
- // prove i==k using a new satlem. We would:
- // 1. Create a new satlem.
- // 2. Assume that i != k
- // 3. Apply ROW to show that ((a[i]:=t)[k] == a[k])
- // 4. Contradict this with the fact that ((a[i]:=t)[k] != a[k]),
- // obtaining our contradiction
-
- TNode t1, t2, t3, t4;
- Node ret;
-
- // pf.d_node is an equality, i==k.
- t1 = pf.d_node[0];
- t2 = pf.d_node[1];
-
- // pf.d_children[0]->d_node will have the form: (not (= (select (store
- // a_565 i7 e_566) i1) (select a_565 i1))),
- // or its symmetrical version.
-
- unsigned side;
- if (pf.d_children[0]->d_node[0][0].getKind() == kind::SELECT
- && pf.d_children[0]->d_node[0][0][0].getKind() == kind::STORE)
- {
- side = 0;
- }
- else if (pf.d_children[0]->d_node[0][1].getKind() == kind::SELECT
- && pf.d_children[0]->d_node[0][1][0].getKind() == kind::STORE)
- {
- side = 1;
- }
- else
- {
- Unreachable();
- }
-
- Debug("pf::array") << "Side is: " << side << std::endl;
-
- // The array's index and element types will come from the subproof...
- t3 = pf.d_children[0]->d_node[0][side][0][0];
- t4 = pf.d_children[0]->d_node[0][side][0][2];
- ret = pf.d_node;
-
- // The order of indices needs to match; we might have to swap t1 and t2
- // and then apply symmetry.
- bool swap = (t2 == pf.d_children[0]->d_node[0][side][0][1]);
-
- Debug("mgd") << "t1 " << t1 << "\nt2 " << t2 << "\nt3 " << t3 << "\nt4 "
- << t4 << "\n";
-
- Assert(pf.d_children.size() == 1);
- std::stringstream ss;
- Node subproof =
- toStreamRecLFSC(ss, tp, *(pf.d_children[0]), tb + 1, map);
-
- Debug("pf::array") << "Subproof is: " << ss.str() << std::endl;
-
- if (swap)
- {
- out << "(symm _ _ _ ";
- }
-
- out << "(negativerow _ _ ";
- tp->printTerm(swap ? t2.toExpr() : t1.toExpr(), out, map);
- out << " ";
- tp->printTerm(swap ? t1.toExpr() : t2.toExpr(), out, map);
- out << " ";
- tp->printTerm(t3.toExpr(), out, map);
- out << " ";
- tp->printTerm(t4.toExpr(), out, map);
- out << " ";
-
- if (side != 0)
- {
- out << "(negsymm _ _ _ " << ss.str() << ")";
- }
- else
- {
- out << ss.str();
- }
-
- out << ")";
-
- if (swap)
- {
- out << ") ";
- }
-
- return ret;
- }
- }
- else if (pf.d_id == d_reasonRow1)
- {
- Debug("mgd") << "row1 lemma: " << pf.d_node << std::endl;
- Assert(pf.d_node.getKind() == kind::EQUAL);
- TNode t1, t2, t3;
- Node ret;
- if (pf.d_node[1].getKind() == kind::SELECT
- && pf.d_node[1][0].getKind() == kind::STORE
- && pf.d_node[1][0][1] == pf.d_node[1][1]
- && pf.d_node[1][0][2] == pf.d_node[0])
- {
- t1 = pf.d_node[1][0][0];
- t2 = pf.d_node[1][0][1];
- t3 = pf.d_node[0];
- ret = pf.d_node[1].eqNode(pf.d_node[0]);
- Debug("mgd") << "t1 " << t1 << "\nt2 " << t2 << "\nt3 " << t3 << "\n";
- }
- else
- {
- Assert(pf.d_node[0].getKind() == kind::SELECT
- && pf.d_node[0][0].getKind() == kind::STORE
- && pf.d_node[0][0][1] == pf.d_node[0][1]
- && pf.d_node[0][0][2] == pf.d_node[1]);
- t1 = pf.d_node[0][0][0];
- t2 = pf.d_node[0][0][1];
- t3 = pf.d_node[1];
- ret = pf.d_node;
- Debug("mgd") << "t1 " << t1 << "\nt2 " << t2 << "\nt3 " << t3 << "\n";
- }
- out << "(row1 _ _ ";
- tp->printTerm(t1.toExpr(), out, map);
- out << " ";
- tp->printTerm(t2.toExpr(), out, map);
- out << " ";
- tp->printTerm(t3.toExpr(), out, map);
- out << ")";
- return ret;
- }
- else if (pf.d_id == d_reasonExt) {
- Assert(pf.d_node.getKind() == kind::NOT);
- Assert(pf.d_node[0].getKind() == kind::EQUAL);
- Assert(pf.d_children.size() == 1);
- std::shared_ptr<theory::eq::EqProof> child_proof = pf.d_children[0];
- Assert(child_proof->d_node.getKind() == kind::NOT);
- Assert(child_proof->d_node[0].getKind() == kind::EQUAL);
-
- Debug("mgd") << "EXT lemma: " << pf.d_node << std::endl;
-
- TNode t1, t2, t3;
- t1 = child_proof->d_node[0][0];
- t2 = child_proof->d_node[0][1];
- t3 = pf.d_node[0][0][1];
-
- Debug("mgd") << "t1 " << t1 << "\nt2 " << t2 << "\nt3 " << t3 << "\n";
-
- out << "(or_elim_1 _ _ ";
- out << ProofManager::getLitName(child_proof->d_node[0]);
- out << " ";
- out << ProofManager::getArrayProof()->skolemToLiteral(t3.toExpr());
- out << ")";
-
- return pf.d_node;
- }
-
- else {
- Assert(!pf.d_node.isNull());
- Assert(pf.d_children.empty());
- Debug("mgd") << "theory proof: " << pf.d_node << " by rule " << int(pf.d_id) << std::endl;
- AlwaysAssert(false);
- return pf.d_node;
- }
-}
- }
-}
-
-ArrayProof::ArrayProof(theory::arrays::TheoryArrays* arrays, TheoryProofEngine* pe)
- : TheoryProof(arrays, pe)
-{}
-
-theory::TheoryId ArrayProof::getTheoryId() { return theory::THEORY_ARRAYS; }
-void ArrayProof::registerTerm(Expr term) {
- // already registered
- if (d_declarations.find(term) != d_declarations.end())
- return;
-
- Type type = term.getType();
- if (type.isSort()) {
- // declare uninterpreted sorts
- d_sorts.insert(type);
- }
-
- if (term.getKind() == kind::APPLY_UF) {
- Expr function = term.getOperator();
- d_declarations.insert(function);
- }
-
- if (term.isVariable()) {
- d_declarations.insert(term);
- }
-
- if (term.getKind() == kind::SELECT && term.getType().isBoolean()) {
- // Ensure cnf literals
- Node asNode(term);
- ProofManager::currentPM()->ensureLiteral(
- asNode.eqNode(NodeManager::currentNM()->mkConst(true)));
- ProofManager::currentPM()->ensureLiteral(
- asNode.eqNode(NodeManager::currentNM()->mkConst(false)));
- }
-
- // recursively declare all other terms
- for (unsigned i = 0; i < term.getNumChildren(); ++i) {
- // could belong to other theories
- d_proofEngine->registerTerm(term[i]);
- }
-}
-
-std::string ArrayProof::skolemToLiteral(Expr skolem) {
- Debug("pf::array") << "ArrayProof::skolemToLiteral( " << skolem << ")" << std::endl;
- Assert(d_skolemToLiteral.find(skolem) != d_skolemToLiteral.end());
- return d_skolemToLiteral[skolem];
-}
-
-void LFSCArrayProof::printOwnedTermAsType(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType)
-{
- Assert(theory::Theory::theoryOf(term) == theory::THEORY_ARRAYS);
-
- if (theory::Theory::theoryOf(term) != theory::THEORY_ARRAYS) {
- // We can get here, for instance, if there's a (select ite ...), e.g. a non-array term
- // hiding as a subterm of an array term. In that case, send it back to the dispatcher.
- d_proofEngine->printBoundTerm(term, os, map);
- return;
- }
-
- if (term.getKind() == kind::VARIABLE || term.getKind() == kind::SKOLEM) {
- os << term;
- return;
- }
-
- Assert((term.getKind() == kind::SELECT)
- || (term.getKind() == kind::PARTIAL_SELECT_0)
- || (term.getKind() == kind::PARTIAL_SELECT_1)
- || (term.getKind() == kind::STORE));
-
- switch (term.getKind()) {
- case kind::SELECT: {
- Assert(term.getNumChildren() == 2);
-
- bool convertToBool = (term[1].getType().isBoolean() && !d_proofEngine->printsAsBool(term[1]));
-
- os << "(apply _ _ (apply _ _ (read ";
- printSort(ArrayType(term[0].getType()).getIndexType(), os);
- os << " ";
- printSort(ArrayType(term[0].getType()).getConstituentType(), os);
- os << ") ";
- printTerm(term[0], os, map);
- os << ") ";
- if (convertToBool) os << "(f_to_b ";
- printTerm(term[1], os, map);
- if (convertToBool) os << ")";
- os << ") ";
- return;
- }
-
- case kind::PARTIAL_SELECT_0:
- Assert(term.getNumChildren() == 1);
- os << "(read ";
- printSort(ArrayType(term[0].getType()).getIndexType(), os);
- os << " ";
- printSort(ArrayType(term[0].getType()).getConstituentType(), os);
- os << ") ";
- return;
-
- case kind::PARTIAL_SELECT_1:
- Debug("pf::array") << "This branch has not beed tested yet." << std::endl;
- Unreachable();
-
- Assert(term.getNumChildren() == 1);
- os << "(apply _ _ (read ";
- printSort(ArrayType(term[0].getType()).getIndexType(), os);
- os << " ";
- printSort(ArrayType(term[0].getType()).getConstituentType(), os);
- os << ") ";
- printTerm(term[0], os, map);
- os << ") ";
- return;
-
- case kind::STORE:
- os << "(apply _ _ (apply _ _ (apply _ _ (write ";
- printSort(ArrayType(term[0].getType()).getIndexType(), os);
- os << " ";
- printSort(ArrayType(term[0].getType()).getConstituentType(), os);
- os << ") ";
- printTerm(term[0], os, map);
- os << ") ";
- printTerm(term[1], os, map);
- os << ") ";
- printTerm(term[2], os, map);
- os << ") ";
- return;
-
- default:
- Unreachable();
- return;
- }
-}
-
-void LFSCArrayProof::printOwnedSort(Type type, std::ostream& os) {
- Debug("pf::array") << std::endl << "(pf::array) LFSCArrayProof::printOwnedSort: type is: " << type << std::endl;
- Assert(type.isArray() || type.isSort());
- if (type.isArray()){
- ArrayType array_type(type);
-
- Debug("pf::array") << "LFSCArrayProof::printOwnedSort: type is an array. Index type: "
- << array_type.getIndexType()
- << ", element type: " << array_type.getConstituentType() << std::endl;
-
- os << "(Array ";
- printSort(array_type.getIndexType(), os);
- os << " ";
- printSort(array_type.getConstituentType(), os);
- os << ")";
- } else {
- os << type;
- }
-}
-
-void LFSCArrayProof::printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren, const ProofLetMap& map) {
- os << " ;; Array Theory Lemma \n;;";
- for (unsigned i = 0; i < lemma.size(); ++i) {
- os << lemma[i] <<" ";
- }
- os <<"\n";
- //os << " (clausify_false trust)";
- ArrayProof::printTheoryLemmaProof(lemma, os, paren, map);
-}
-
-void LFSCArrayProof::printSortDeclarations(std::ostream& os, std::ostream& paren) {
- // declaring the sorts
- for (TypeSet::const_iterator it = d_sorts.begin(); it != d_sorts.end(); ++it) {
- if (!ProofManager::currentPM()->wasPrinted(*it)) {
- os << "(% " << *it << " sort\n";
- paren << ")";
- ProofManager::currentPM()->markPrinted(*it);
- }
- }
-}
-
-void LFSCArrayProof::printTermDeclarations(std::ostream& os, std::ostream& paren) {
- Debug("pf::array") << "Arrays declaring terms..." << std::endl;
-
- for (ExprSet::const_iterator it = d_declarations.begin(); it != d_declarations.end(); ++it) {
- Expr term = *it;
-
- Assert(term.getType().isArray() || term.isVariable());
-
- Debug("pf::array") << "LFSCArrayProof::printDeclarations: term is: " << term
- << ". It's type is: " << term.getType()
- << std::endl;
-
- if (term.getType().isArray()){
- ArrayType array_type(term.getType());
-
- Debug("pf::array") << "LFSCArrayProof::printDeclarations: term is an array. Index type: "
- << array_type.getIndexType()
- << ", element type: " << array_type.getConstituentType() << std::endl;
-
- os << "(% " << ProofManager::sanitize(term) << " ";
- os << "(term ";
- os << "(Array ";
-
- printSort(array_type.getIndexType(), os);
- os << " ";
- printSort(array_type.getConstituentType(), os);
-
- os << "))\n";
- paren << ")";
- } else {
- Assert(term.isVariable());
- if (ProofManager::getSkolemizationManager()->isSkolem(*it)) {
- Debug("pf::array") << "This term is a skoelm!" << std::endl;
- d_skolemDeclarations.insert(*it);
- } else {
- os << "(% " << ProofManager::sanitize(term) << " ";
- os << "(term ";
- os << term.getType() << ")\n";
- paren << ")";
- }
- }
- }
-
- Debug("pf::array") << "Declaring terms done!" << std::endl;
-}
-
-void LFSCArrayProof::printDeferredDeclarations(std::ostream& os, std::ostream& paren) {
- Debug("pf::array") << "Array: print deferred declarations called" << std::endl;
-
- unsigned count = 1;
- for (ExprSet::const_iterator it = d_skolemDeclarations.begin(); it != d_skolemDeclarations.end(); ++it) {
- Expr term = *it;
- Node equality = ProofManager::getSkolemizationManager()->getDisequality(*it);
-
- Debug("pf::array") << "LFSCArrayProof::printDeferredDeclarations: term is: " << *it << std::endl
- << "It is a witness for: " << equality << std::endl;
-
- std::ostringstream newSkolemLiteral;
- newSkolemLiteral << ".sl" << count++;
- std::string skolemLiteral = newSkolemLiteral.str();
-
- d_skolemToLiteral[*it] = skolemLiteral;
-
- Debug("pf::array") << "LFSCArrayProof::printDeferredDeclarations: new skolem literal is: " << skolemLiteral << std::endl;
-
- Assert(equality.getKind() == kind::NOT);
- Assert(equality[0].getKind() == kind::EQUAL);
-
- Node array_one = equality[0][0];
- Node array_two = equality[0][1];
-
- ProofLetMap map;
- os << "(ext _ _ ";
- printTerm(array_one.toExpr(), os, map);
- os << " ";
- printTerm(array_two.toExpr(), os, map);
- os << " (\\ ";
- os << ProofManager::sanitize(*it);
- os << " (\\ ";
- os << skolemLiteral.c_str();
- os << "\n";
-
- paren << ")))";
- }
-}
-
-void LFSCArrayProof::printAliasingDeclarations(std::ostream& os, std::ostream& paren, const ProofLetMap &globalLetMap) {
- // Nothing to do here at this point.
-}
-
-bool LFSCArrayProof::printsAsBool(const Node &n)
-{
- if (n.getKind() == kind::SELECT)
- return true;
-
- return false;
-}
-
-} /* CVC4 namespace */
diff --git a/src/proof/array_proof.h b/src/proof/array_proof.h
deleted file mode 100644
index ffcff165a..000000000
--- a/src/proof/array_proof.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/********************* */
-/*! \file array_proof.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Tim King, Mathias Preiner, Guy Katz
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief Arrray proof
- **
- ** Arrau proof
- **/
-
-#include "cvc4_private.h"
-
-#ifndef CVC4__ARRAY__PROOF_H
-#define CVC4__ARRAY__PROOF_H
-
-#include <memory>
-#include <unordered_set>
-
-#include "expr/expr.h"
-#include "proof/proof_manager.h"
-#include "proof/theory_proof.h"
-#include "theory/arrays/theory_arrays.h"
-#include "theory/uf/equality_engine.h"
-
-namespace CVC4 {
-
-// Proof object outputted by TheoryARRAY.
-class ProofArray : public Proof {
- public:
- ProofArray(std::shared_ptr<theory::eq::EqProof> pf, unsigned row,
- unsigned row1, unsigned ext);
-
- void registerSkolem(Node equality, Node skolem);
-
- void toStream(std::ostream& out) const override;
- void toStream(std::ostream& out, const ProofLetMap& map) const override;
-
- private:
- void toStreamLFSC(std::ostream& out,
- TheoryProof* tp,
- const theory::eq::EqProof& pf,
- const ProofLetMap& map) const;
-
- Node toStreamRecLFSC(std::ostream& out,
- TheoryProof* tp,
- const theory::eq::EqProof& pf,
- unsigned tb,
- const ProofLetMap& map) const;
-
- // It is simply an equality engine proof.
- std::shared_ptr<theory::eq::EqProof> d_proof;
-
- /** Merge tag for ROW applications */
- unsigned d_reasonRow;
- /** Merge tag for ROW1 applications */
- unsigned d_reasonRow1;
- /** Merge tag for EXT applications */
- unsigned d_reasonExt;
-};
-
-namespace theory {
-namespace arrays{
-class TheoryArrays;
-} /* namespace CVC4::theory::arrays */
-} /* namespace CVC4::theory */
-
-typedef std::unordered_set<Type, TypeHashFunction > TypeSet;
-
-class ArrayProof : public TheoryProof {
- // TODO: whatever goes in this theory
-protected:
- TypeSet d_sorts; // all the uninterpreted sorts in this theory
- ExprSet d_declarations; // all the variable/function declarations
- ExprSet d_skolemDeclarations; // all the skolem variable declarations
- std::map<Expr, std::string> d_skolemToLiteral;
- theory::TheoryId getTheoryId() override;
-
- public:
- ArrayProof(theory::arrays::TheoryArrays* arrays, TheoryProofEngine* proofEngine);
-
- std::string skolemToLiteral(Expr skolem);
-
- void registerTerm(Expr term) override;
-};
-
-class LFSCArrayProof : public ArrayProof {
-public:
- LFSCArrayProof(theory::arrays::TheoryArrays* arrays, TheoryProofEngine* proofEngine)
- : ArrayProof(arrays, proofEngine)
- {}
-
- void printOwnedTermAsType(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType) override;
- void printOwnedSort(Type type, std::ostream& os) override;
- void printTheoryLemmaProof(std::vector<Expr>& lemma,
- std::ostream& os,
- std::ostream& paren,
- const ProofLetMap& map) override;
- void printSortDeclarations(std::ostream& os, std::ostream& paren) override;
- void printTermDeclarations(std::ostream& os, std::ostream& paren) override;
- void printDeferredDeclarations(std::ostream& os,
- std::ostream& paren) override;
- void printAliasingDeclarations(std::ostream& os,
- std::ostream& paren,
- const ProofLetMap& globalLetMap) override;
-
- bool printsAsBool(const Node& n) override;
-};
-
-
-}/* CVC4 namespace */
-
-#endif /* CVC4__ARRAY__PROOF_H */
diff --git a/src/proof/bitvector_proof.cpp b/src/proof/bitvector_proof.cpp
deleted file mode 100644
index 98e3300f5..000000000
--- a/src/proof/bitvector_proof.cpp
+++ /dev/null
@@ -1,792 +0,0 @@
-/********************* */
-/*! \file bitvector_proof.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Liana Hadarean, Guy Katz, Alex Ozdemir
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** Contains implementions (e.g. code for printing bitblasting bindings that is
- ** common to all kinds of bitvector proofs.
- **/
-
-#include "proof/bitvector_proof.h"
-#include "options/bv_options.h"
-#include "options/proof_options.h"
-#include "proof/proof_output_channel.h"
-#include "proof/theory_proof.h"
-#include "prop/sat_solver_types.h"
-#include "theory/bv/bitblast/bitblaster.h"
-#include "theory/bv/theory_bv.h"
-
-namespace CVC4 {
-
-namespace proof {
-BitVectorProof::BitVectorProof(theory::bv::TheoryBV* bv,
- TheoryProofEngine* proofEngine)
- : TheoryProof(bv, proofEngine),
- d_declarations(),
- d_seenBBTerms(),
- d_bbTerms(),
- d_bbAtoms(),
- d_bitblaster(nullptr),
- d_useConstantLetification(false),
- d_cnfProof()
-{
-}
-
-void BitVectorProof::setBitblaster(theory::bv::TBitblaster<Node>* bb)
-{
- Assert(d_bitblaster == NULL);
- d_bitblaster = bb;
-}
-
-void BitVectorProof::registerTermBB(Expr term)
-{
- Debug("pf::bv") << "BitVectorProof::registerTermBB( " << term
- << " )" << std::endl;
-
- if (d_seenBBTerms.find(term) != d_seenBBTerms.end()) return;
-
- d_seenBBTerms.insert(term);
- d_bbTerms.push_back(term);
-
- // If this term gets used in the final proof, we will want to register it.
- // However, we don't know this at this point; and when the theory proof engine
- // sees it, if it belongs to another theory, it won't register it with this
- // proof. So, we need to tell the engine to inform us.
-
- if (theory::Theory::theoryOf(term) != theory::THEORY_BV)
- {
- Debug("pf::bv") << "\tMarking term " << term
- << " for future BV registration" << std::endl;
- d_proofEngine->markTermForFutureRegistration(term, theory::THEORY_BV);
- }
-}
-
-void BitVectorProof::registerAtomBB(Expr atom, Expr atom_bb) {
- Debug("pf::bv") << "BitVectorProof::registerAtomBB( " << atom
- << ", " << atom_bb << " )" << std::endl;
-
- Expr def = atom.eqExpr(atom_bb);
- d_bbAtoms.insert(std::make_pair(atom, def));
- registerTerm(atom);
-
- // Register the atom's terms for bitblasting
- registerTermBB(atom[0]);
- registerTermBB(atom[1]);
-}
-
-void BitVectorProof::registerTerm(Expr term) {
- Debug("pf::bv") << "BitVectorProof::registerTerm( " << term << " )"
- << std::endl;
-
- if (options::lfscLetification() && term.isConst()
- && term.getType().isBitVector())
- {
- if (d_constantLetMap.find(term) == d_constantLetMap.end()) {
- std::ostringstream name;
- name << "letBvc" << d_constantLetMap.size();
- d_constantLetMap[term] = name.str();
- }
- }
-
- d_usedBB.insert(term);
-
- if (theory::Theory::isLeafOf(term, theory::THEORY_BV) && !term.isConst())
- {
- d_declarations.insert(term);
- }
-
- Debug("pf::bv") << "Going to register children: " << std::endl;
- for (unsigned i = 0; i < term.getNumChildren(); ++i) {
- Debug("pf::bv") << "\t" << term[i] << std::endl;
- }
-
- // don't care about parametric operators for bv?
- for (unsigned i = 0; i < term.getNumChildren(); ++i) {
- d_proofEngine->registerTerm(term[i]);
- }
-}
-
-std::string BitVectorProof::getBBTermName(Expr expr)
-{
- Debug("pf::bv") << "BitVectorProof::getBBTermName( " << expr << " ) = bt"
- << expr.getId() << std::endl;
- std::ostringstream os;
- os << "bt" << expr.getId();
- return os.str();
-}
-
-void BitVectorProof::printOwnedTermAsType(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType)
-{
- Debug("pf::bv") << std::endl
- << "(pf::bv) BitVectorProof::printOwnedTerm( " << term
- << " ), theory is: " << theory::Theory::theoryOf(term)
- << std::endl;
-
- Assert(theory::Theory::theoryOf(term) == theory::THEORY_BV);
-
- // peel off eager bit-blasting trick
- if (term.getKind() == kind::BITVECTOR_EAGER_ATOM) {
- d_proofEngine->printBoundTerm(term[0], os, map);
- return;
- }
-
- switch (term.getKind()) {
- case kind::CONST_BITVECTOR : {
- printConstant(term, os);
- return;
- }
- case kind::BITVECTOR_AND :
- case kind::BITVECTOR_OR :
- case kind::BITVECTOR_XOR :
- case kind::BITVECTOR_NAND :
- case kind::BITVECTOR_NOR :
- case kind::BITVECTOR_XNOR :
- case kind::BITVECTOR_COMP :
- case kind::BITVECTOR_MULT :
- case kind::BITVECTOR_PLUS :
- case kind::BITVECTOR_SUB :
- case kind::BITVECTOR_UDIV :
- case kind::BITVECTOR_UREM :
- case kind::BITVECTOR_UDIV_TOTAL :
- case kind::BITVECTOR_UREM_TOTAL :
- case kind::BITVECTOR_SDIV :
- case kind::BITVECTOR_SREM :
- case kind::BITVECTOR_SMOD :
- case kind::BITVECTOR_SHL :
- case kind::BITVECTOR_LSHR :
- case kind::BITVECTOR_ASHR :
- case kind::BITVECTOR_CONCAT : {
- printOperatorNary(term, os, map);
- return;
- }
- case kind::BITVECTOR_NEG :
- case kind::BITVECTOR_NOT :
- case kind::BITVECTOR_ROTATE_LEFT :
- case kind::BITVECTOR_ROTATE_RIGHT : {
- printOperatorUnary(term, os, map);
- return;
- }
- case kind::EQUAL :
- case kind::BITVECTOR_ULT :
- case kind::BITVECTOR_ULE :
- case kind::BITVECTOR_UGT :
- case kind::BITVECTOR_UGE :
- case kind::BITVECTOR_SLT :
- case kind::BITVECTOR_SLE :
- case kind::BITVECTOR_SGT :
- case kind::BITVECTOR_SGE : {
- printPredicate(term, os, map);
- return;
- }
- case kind::BITVECTOR_EXTRACT :
- case kind::BITVECTOR_REPEAT :
- case kind::BITVECTOR_ZERO_EXTEND :
- case kind::BITVECTOR_SIGN_EXTEND : {
- printOperatorParametric(term, os, map);
- return;
- }
- case kind::BITVECTOR_BITOF : {
- printBitOf(term, os, map);
- return;
- }
-
- case kind::VARIABLE: {
- os << "(a_var_bv " << utils::getSize(term)<< " " << ProofManager::sanitize(term) << ")";
- return;
- }
-
- case kind::SKOLEM: {
-
- // TODO: we need to distinguish between "real" skolems (e.g. from array) and "fake" skolems,
- // like ITE terms. Is there a more elegant way?
-
- if (ProofManager::getSkolemizationManager()->isSkolem(term)) {
- os << ProofManager::sanitize(term);
- } else {
- os << "(a_var_bv " << utils::getSize(term)<< " " << ProofManager::sanitize(term) << ")";
- }
- return;
- }
-
- default:
- Unreachable();
- }
-}
-
-void BitVectorProof::printEmptyClauseProof(std::ostream& os,
- std::ostream& paren)
-{
- Assert(options::bitblastMode() == options::BitblastMode::EAGER)
- << "the BV theory should only be proving bottom directly in the eager "
- "bitblasting mode";
-}
-
-void BitVectorProof::printBitOf(Expr term,
- std::ostream& os,
- const ProofLetMap& map)
-{
- Assert(term.getKind() == kind::BITVECTOR_BITOF);
- unsigned bit = term.getOperator().getConst<BitVectorBitOf>().d_bitIndex;
- Expr var = term[0];
-
- Debug("pf::bv") << "BitVectorProof::printBitOf( " << term << " ), "
- << "bit = " << bit << ", var = " << var << std::endl;
-
- os << "(bitof ";
- os << d_exprToVariableName[var];
- os << " " << bit << ")";
-}
-
-void BitVectorProof::printConstant(Expr term, std::ostream& os)
-{
- Assert(term.isConst());
- os << "(a_bv " << utils::getSize(term) << " ";
-
- if (d_useConstantLetification) {
- os << d_constantLetMap[term] << ")";
- } else {
- std::ostringstream paren;
- int size = utils::getSize(term);
- for (int i = size - 1; i >= 0; --i) {
- os << "(bvc ";
- os << (utils::getBit(term, i) ? "b1" : "b0") <<" ";
- paren << ")";
- }
- os << " bvn)";
- os << paren.str();
- }
-}
-
-void BitVectorProof::printOperatorNary(Expr term,
- std::ostream& os,
- const ProofLetMap& map)
-{
- std::string op = utils::toLFSCKindTerm(term);
- std::ostringstream paren;
- std::string holes = term.getKind() == kind::BITVECTOR_CONCAT ? "_ _ " : "";
- unsigned size = term.getKind() == kind::BITVECTOR_CONCAT? utils::getSize(term) :
- utils::getSize(term[0]); // cause of COMP
-
- for (unsigned i = 0; i < term.getNumChildren() - 1; ++i) {
- os <<"("<< op <<" " << size <<" " << holes;
- }
- d_proofEngine->printBoundTerm(term[0], os, map);
- os <<" ";
- for (unsigned i = 1; i < term.getNumChildren(); ++i) {
- d_proofEngine->printBoundTerm(term[i], os, map);
- os << ")";
- }
-}
-
-void BitVectorProof::printOperatorUnary(Expr term,
- std::ostream& os,
- const ProofLetMap& map)
-{
- os <<"(";
- os << utils::toLFSCKindTerm(term) << " " << utils::getSize(term) <<" ";
- os << " ";
- d_proofEngine->printBoundTerm(term[0], os, map);
- os <<")";
-}
-
-void BitVectorProof::printPredicate(Expr term,
- std::ostream& os,
- const ProofLetMap& map)
-{
- os <<"(";
- os << utils::toLFSCKindTerm(term) << " " << utils::getSize(term[0]) <<" ";
- os << " ";
- d_proofEngine->printBoundTerm(term[0], os, map);
- os << " ";
- d_proofEngine->printBoundTerm(term[1], os, map);
- os <<")";
-}
-
-void BitVectorProof::printOperatorParametric(Expr term,
- std::ostream& os,
- const ProofLetMap& map)
-{
- os <<"(";
- os << utils::toLFSCKindTerm(term) << " " << utils::getSize(term) <<" ";
- os <<" ";
- if (term.getKind() == kind::BITVECTOR_REPEAT) {
- unsigned amount =
- term.getOperator().getConst<BitVectorRepeat>().d_repeatAmount;
- os << amount <<" _ ";
- }
- if (term.getKind() == kind::BITVECTOR_SIGN_EXTEND) {
- unsigned amount =
- term.getOperator().getConst<BitVectorSignExtend>().d_signExtendAmount;
- os << amount <<" _ ";
- }
-
- if (term.getKind() == kind::BITVECTOR_ZERO_EXTEND) {
- unsigned amount =
- term.getOperator().getConst<BitVectorZeroExtend>().d_zeroExtendAmount;
- os << amount<<" _ ";
- }
- if (term.getKind() == kind::BITVECTOR_EXTRACT) {
- unsigned low = utils::getExtractLow(term);
- unsigned high = utils::getExtractHigh(term);
- os << high <<" " << low << " " << utils::getSize(term[0]);
- }
- os <<" ";
- Assert(term.getNumChildren() == 1);
- d_proofEngine->printBoundTerm(term[0], os, map);
- os <<")";
-}
-
-void BitVectorProof::printOwnedSort(Type type, std::ostream& os)
-{
- Debug("pf::bv") << std::endl
- << "(pf::bv) BitVectorProof::printOwnedSort( " << type << " )"
- << std::endl;
- Assert(type.isBitVector());
- unsigned width = utils::getSize(type);
- os << "(BitVec " << width << ")";
-}
-
-void BitVectorProof::printSortDeclarations(std::ostream& os,
- std::ostream& paren)
-{
- // Nothing to do here at this point.
-}
-
-void BitVectorProof::printTermDeclarations(std::ostream& os,
- std::ostream& paren)
-{
- ExprSet::const_iterator it = d_declarations.begin();
- ExprSet::const_iterator end = d_declarations.end();
- for (; it != end; ++it) {
- if ((it->isVariable() || it->isConst()) && !ProofManager::getSkolemizationManager()->isSkolem(*it)) {
- d_exprToVariableName[*it] = ProofManager::sanitize(*it);
- } else {
- std::string newAlias = assignAlias(*it);
- d_exprToVariableName[*it] = newAlias;
- }
-
- os << "(% " << d_exprToVariableName[*it] <<" var_bv" << "\n";
- paren <<")";
- }
-}
-
-void BitVectorProof::printDeferredDeclarations(std::ostream& os,
- std::ostream& paren)
-{
- if (options::lfscLetification()) {
- os << std::endl << ";; BV const letification\n" << std::endl;
- std::map<Expr,std::string>::const_iterator it;
- for (it = d_constantLetMap.begin(); it != d_constantLetMap.end(); ++it) {
- os << "\n(@ " << it->second << " ";
- std::ostringstream localParen;
- int size = utils::getSize(it->first);
- for (int i = size - 1; i >= 0; --i) {
- os << "(bvc ";
- os << (utils::getBit(it->first, i) ? "b1" : "b0") << " ";
- localParen << ")";
- }
- os << "bvn";
- os << localParen.str();
- paren << ")";
- }
- os << std::endl;
-
- d_useConstantLetification = true;
- }
-}
-
-void BitVectorProof::printAliasingDeclarations(std::ostream& os,
- std::ostream& paren,
- const ProofLetMap& globalLetMap)
-{
- // Print "trust" statements to bind complex bv variables to their associated terms
-
- ExprToString::const_iterator it = d_assignedAliases.begin();
- ExprToString::const_iterator end = d_assignedAliases.end();
-
- for (; it != end; ++it) {
- Debug("pf::bv") << "Printing aliasing declaration for: " << *it << std::endl;
- std::stringstream declaration;
- declaration << ".fbvd" << d_aliasToBindDeclaration.size();
- d_aliasToBindDeclaration[it->second] = declaration.str();
-
- os << "(th_let_pf _ ";
-
- os << "(trust_f ";
- os << "(= (BitVec " << utils::getSize(it->first) << ") ";
- os << "(a_var_bv " << utils::getSize(it->first) << " " << it->second << ") ";
- d_proofEngine->printBoundTerm(it->first, os, globalLetMap);
- os << ")) ";
- os << "(\\ "<< d_aliasToBindDeclaration[it->second] << "\n";
- paren << "))";
- }
-
- os << "\n";
-}
-
-void BitVectorProof::printTermBitblasting(Expr term, std::ostream& os)
-{
- // TODO: once we have the operator elimination rules remove those that we
- // eliminated
- Assert(term.getType().isBitVector());
- Kind kind = term.getKind();
-
- if (theory::Theory::isLeafOf(term, theory::THEORY_BV) && !term.isConst())
- {
- // A term is a leaf if it has no children, or if it belongs to another theory
- os << "(bv_bbl_var " << utils::getSize(term) << " " << d_exprToVariableName[term];
- os << " _)";
- return;
- }
-
- switch(kind) {
- case kind::CONST_BITVECTOR : {
- os << "(bv_bbl_const "<< utils::getSize(term) <<" _ ";
- std::ostringstream paren;
- int size = utils::getSize(term);
- if (d_useConstantLetification) {
- os << d_constantLetMap[term] << ")";
- } else {
- for (int i = size - 1; i>= 0; --i) {
- os << "(bvc ";
- os << (utils::getBit(term, i) ? "b1" : "b0") <<" ";
- paren << ")";
- }
- os << " bvn)";
- os << paren.str();
- }
- return;
- }
-
- case kind::BITVECTOR_AND :
- case kind::BITVECTOR_OR :
- case kind::BITVECTOR_XOR :
- case kind::BITVECTOR_NAND :
- case kind::BITVECTOR_NOR :
- case kind::BITVECTOR_XNOR :
- case kind::BITVECTOR_COMP :
- case kind::BITVECTOR_MULT :
- case kind::BITVECTOR_PLUS :
- case kind::BITVECTOR_SUB :
- case kind::BITVECTOR_CONCAT : {
- Debug("pf::bv") << "Bitblasing kind = " << kind << std::endl;
-
- for (int i = term.getNumChildren() - 1; i > 0; --i) {
- os <<"(bv_bbl_"<< utils::toLFSCKind(kind);
-
- if (kind == kind::BITVECTOR_CONCAT) {
- os << " " << utils::getSize(term) << " _";
- }
- os << " _ _ _ _ _ _ ";
- }
-
- os << getBBTermName(term[0]) << " ";
-
- for (unsigned i = 1; i < term.getNumChildren(); ++i) {
- os << getBBTermName(term[i]);
- os << ") ";
- }
- return;
- }
-
- case kind::BITVECTOR_NEG :
- case kind::BITVECTOR_NOT :
- case kind::BITVECTOR_ROTATE_LEFT :
- case kind::BITVECTOR_ROTATE_RIGHT : {
- os << "(bv_bbl_"<<utils::toLFSCKind(kind);
- os << " _ _ _ _ ";
- os << getBBTermName(term[0]);
- os << ")";
- return;
- }
- case kind::BITVECTOR_EXTRACT : {
- os <<"(bv_bbl_"<<utils::toLFSCKind(kind);
-
- os << " " << utils::getSize(term) << " ";
- os << utils::getExtractHigh(term) << " ";
- os << utils::getExtractLow(term) << " ";
- os << " _ _ _ _ ";
-
- os << getBBTermName(term[0]);
- os <<")";
- return;
- }
- case kind::BITVECTOR_REPEAT :
- case kind::BITVECTOR_ZERO_EXTEND :
- case kind::BITVECTOR_SIGN_EXTEND : {
- os << "(bv_bbl_" << utils::toLFSCKind(kind) << " ";
- os << utils::getSize(term) << " ";
- if (term.getKind() == kind::BITVECTOR_REPEAT) {
- unsigned amount =
- term.getOperator().getConst<BitVectorRepeat>().d_repeatAmount;
- os << amount;
- }
- if (term.getKind() == kind::BITVECTOR_SIGN_EXTEND) {
- unsigned amount =
- term.getOperator().getConst<BitVectorSignExtend>().d_signExtendAmount;
- os << amount;
- }
-
- if (term.getKind() == kind::BITVECTOR_ZERO_EXTEND) {
- unsigned amount =
- term.getOperator().getConst<BitVectorZeroExtend>().d_zeroExtendAmount;
- os << amount;
- }
-
- os <<" _ _ _ _ ";
- os << getBBTermName(term[0]);
- os <<")";
- return;
- }
- case kind::BITVECTOR_UDIV :
- case kind::BITVECTOR_UREM :
- case kind::BITVECTOR_UDIV_TOTAL :
- case kind::BITVECTOR_UREM_TOTAL :
- case kind::BITVECTOR_SDIV :
- case kind::BITVECTOR_SREM :
- case kind::BITVECTOR_SMOD :
- case kind::BITVECTOR_SHL :
- case kind::BITVECTOR_LSHR :
- case kind::BITVECTOR_ASHR : {
- // these are terms for which bit-blasting is not supported yet
- std::ostringstream paren;
- os <<"(trust_bblast_term _ ";
- paren <<")";
- d_proofEngine->printLetTerm(term, os);
- os <<" ";
- std::vector<Node> bits;
- d_bitblaster->bbTerm(term, bits);
-
- for (int i = utils::getSize(term) - 1; i >= 0; --i) {
- os << "(bbltc ";
- d_proofEngine->printLetTerm((bits[i]).toExpr(), os);
- paren << ")";
- }
- os << "bbltn" << paren.str();
- return;
- }
-
- default: Unreachable() << "BitVectorProof Unknown operator";
- }
-}
-
-void BitVectorProof::printAtomBitblasting(Expr atom,
- std::ostream& os,
- bool swap)
-{
- Kind kind = atom.getKind();
- switch(kind) {
- case kind::BITVECTOR_ULT :
- case kind::BITVECTOR_ULE :
- case kind::BITVECTOR_UGT :
- case kind::BITVECTOR_UGE :
- case kind::BITVECTOR_SLT :
- case kind::BITVECTOR_SLE :
- case kind::BITVECTOR_SGT :
- case kind::BITVECTOR_SGE :
- case kind::EQUAL: {
- Debug("pf::bv") << "Bitblasing kind = " << kind << std::endl;
-
- os << "(bv_bbl_" << utils::toLFSCKindTerm(atom);
-
- if (swap) {os << "_swap";}
-
- os << " _ _ _ _ _ _ ";
- os << getBBTermName(atom[0]);
- os << " ";
- os << getBBTermName(atom[1]);
- os << ")";
-
- return;
- }
- default: Unreachable() << "BitVectorProof Unknown atom kind";
- }
-}
-
-void BitVectorProof::printAtomBitblastingToFalse(Expr atom, std::ostream& os)
-{
- Assert(atom.getKind() == kind::EQUAL);
-
- os << "(bv_bbl_=_false";
- os << " _ _ _ _ _ _ ";
- os << getBBTermName(atom[0]);
-
- os << " ";
-
- os << getBBTermName(atom[1]);
-
- os << ")";
-}
-
-void BitVectorProof::printBitblasting(std::ostream& os, std::ostream& paren)
-{
- // bit-blast terms
- {
- Debug("pf::bv")
- << "BitVectorProof::printBitblasting: the bitblasted terms are: "
- << std::endl;
- std::vector<Expr>::const_iterator it = d_bbTerms.begin();
- std::vector<Expr>::const_iterator end = d_bbTerms.end();
-
- for (; it != end; ++it) {
- if (d_usedBB.find(*it) == d_usedBB.end()) {
- Debug("pf::bv") << "\t" << *it << "\t(UNUSED)" << std::endl;
- } else {
- Debug("pf::bv") << "\t" << *it << std::endl;
- }
- }
-
- Debug("pf::bv") << std::endl;
- }
-
- std::vector<Expr>::const_iterator it = d_bbTerms.begin();
- std::vector<Expr>::const_iterator end = d_bbTerms.end();
- for (; it != end; ++it) {
- if (d_usedBB.find(*it) == d_usedBB.end()
- && options::bitblastMode() != options::BitblastMode::EAGER)
- continue;
-
- // Is this term has an alias, we inject it through the decl_bblast statement
- if (hasAlias(*it)) {
- os << "(decl_bblast_with_alias _ _ _ _ ";
- printTermBitblasting(*it, os);
- os << " " << d_aliasToBindDeclaration[d_assignedAliases[*it]] << " ";
- os << "(\\ "<< getBBTermName(*it);
- os << "\n";
- paren <<"))";
- } else {
- os << "(decl_bblast _ _ _ ";
- printTermBitblasting(*it, os);
- os << "(\\ "<< getBBTermName(*it);
- os << "\n";
- paren <<"))";
- }
- }
- // bit-blast atoms
- ExprToExpr::const_iterator ait = d_bbAtoms.begin();
- ExprToExpr::const_iterator aend = d_bbAtoms.end();
- for (; ait != aend; ++ait) {
- if (d_usedBB.find(ait->first) == d_usedBB.end()
- && options::bitblastMode() != options::BitblastMode::EAGER)
- continue;
-
- os << "(th_let_pf _ ";
- if (ait->first.getKind() == kind::CONST_BOOLEAN) {
- bool val = ait->first.getConst<bool>();
- os << "(iff_symm " << (val ? "true" : "false" ) << ")";
- } else {
- Assert(ait->first == ait->second[0]);
-
- bool swap = false;
- if (ait->first.getKind() == kind::EQUAL) {
- Expr bitwiseEquivalence = ait->second[1];
- if ((bitwiseEquivalence.getKind() == kind::CONST_BOOLEAN) && !bitwiseEquivalence.getConst<bool>()) {
- printAtomBitblastingToFalse(ait->first, os);
- } else {
- if (bitwiseEquivalence.getKind() != kind::AND) {
- // Just one bit
- if (bitwiseEquivalence.getNumChildren() > 0 && bitwiseEquivalence[0].getKind() == kind::BITVECTOR_BITOF) {
- swap = (ait->first[1] == bitwiseEquivalence[0][0]);
- }
- } else {
- // Multiple bits
- if (bitwiseEquivalence[0].getNumChildren() > 0 &&
- bitwiseEquivalence[0][0].getKind() == kind::BITVECTOR_BITOF) {
- swap = (ait->first[1] == bitwiseEquivalence[0][0][0]);
- } else if (bitwiseEquivalence[0].getNumChildren() > 0 &&
- bitwiseEquivalence[0][1].getKind() == kind::BITVECTOR_BITOF) {
- swap = (ait->first[0] == bitwiseEquivalence[0][1][0]);
- }
- }
-
- printAtomBitblasting(ait->first, os, swap);
- }
- } else {
- printAtomBitblasting(ait->first, os, swap);
- }
- }
-
- os <<"(\\ " << ProofManager::getPreprocessedAssertionName(ait->second) <<"\n";
- paren <<"))";
- }
-}
-
-theory::TheoryId BitVectorProof::getTheoryId() { return theory::THEORY_BV; }
-
-const std::set<Node>* BitVectorProof::getAtomsInBitblastingProof()
-{
- return &d_atomsInBitblastingProof;
-}
-
-std::string BitVectorProof::assignAlias(Expr expr)
-{
- Assert(d_exprToVariableName.find(expr) == d_exprToVariableName.end());
-
- std::stringstream ss;
- ss << "fbv" << d_assignedAliases.size();
- Debug("pf::bv") << "assignAlias( " << expr << ") = " << ss.str() << std::endl;
- d_assignedAliases[expr] = ss.str();
- return ss.str();
-}
-
-bool BitVectorProof::hasAlias(Expr expr)
-{
- return d_assignedAliases.find(expr) != d_assignedAliases.end();
-}
-
-void BitVectorProof::printConstantDisequalityProof(
- std::ostream& os, Expr c1, Expr c2, const ProofLetMap& globalLetMap)
-{
- Assert(c1.isConst());
- Assert(c2.isConst());
- Assert(utils::getSize(c1) == utils::getSize(c2));
-
- os << "(bv_disequal_constants " << utils::getSize(c1) << " ";
-
- std::ostringstream paren;
-
- for (int i = utils::getSize(c1) - 1; i >= 0; --i) {
- os << "(bvc ";
- os << (utils::getBit(c1, i) ? "b1" : "b0") << " ";
- paren << ")";
- }
- os << "bvn";
- os << paren.str();
-
- os << " ";
-
- for (int i = utils::getSize(c2) - 1; i >= 0; --i) {
- os << "(bvc ";
- os << (utils::getBit(c2, i) ? "b1" : "b0") << " ";
-
- }
- os << "bvn";
- os << paren.str();
-
- os << ")";
-}
-
-void BitVectorProof::printRewriteProof(std::ostream& os,
- const Node& n1,
- const Node& n2)
-{
- ProofLetMap emptyMap;
- os << "(rr_bv_default ";
- d_proofEngine->printBoundTerm(n2.toExpr(), os, emptyMap);
- os << " ";
- d_proofEngine->printBoundTerm(n1.toExpr(), os, emptyMap);
- os << ")";
-}
-
-} // namespace proof
-
-} // namespace CVC4
diff --git a/src/proof/bitvector_proof.h b/src/proof/bitvector_proof.h
deleted file mode 100644
index 9a9071e58..000000000
--- a/src/proof/bitvector_proof.h
+++ /dev/null
@@ -1,280 +0,0 @@
-/********************* */
-/*! \file bitvector_proof.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir, Mathias Preiner, Liana Hadarean
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief Bitvector proof base class
- **
- ** Contains code (e.g. proof printing code) which is common to all bitvector
- *proofs.
- **/
-
-#include "cvc4_private.h"
-
-#ifndef CVC4__BITVECTOR_PROOF_H
-#define CVC4__BITVECTOR_PROOF_H
-
-#include <set>
-#include <unordered_map>
-#include <unordered_set>
-#include <vector>
-
-#include "expr/expr.h"
-#include "proof/cnf_proof.h"
-#include "proof/theory_proof.h"
-#include "prop/sat_solver.h"
-#include "theory/bv/theory_bv.h"
-
-// Since TBitblaster and BitVectorProof are cyclically dependent, we need this
-// forward declaration
-namespace CVC4 {
-namespace theory {
-namespace bv {
-template <class T>
-class TBitblaster;
-}
-} // namespace theory
-} // namespace CVC4
-
-namespace CVC4 {
-
-namespace proof {
-
-typedef std::unordered_set<Expr, ExprHashFunction> ExprSet;
-typedef std::unordered_map<Expr, ClauseId, ExprHashFunction> ExprToClauseId;
-typedef std::unordered_map<Expr, unsigned, ExprHashFunction> ExprToId;
-typedef std::unordered_map<Expr, Expr, ExprHashFunction> ExprToExpr;
-typedef std::unordered_map<Expr, std::string, ExprHashFunction> ExprToString;
-
-/**
- * A bitvector proof is best understood as having
- *
- * 1. A declaration of a "bitblasted formulas" -- boolean formulas
- * that are each translations of a BV-literal (a comparison between BVs).
- *
- * (and a proof that each "bitblasted formula" is implied by the
- * corresponding BV literal)
- *
- * 2. A declaration of a cnf formula equisatisfiable to the bitblasted
- * formula
- *
- * (and a proof that each clause is implied by some bitblasted formula)
- *
- * 3. A proof of UNSAT from the clauses.
- *
- * This class is responsible for 1 & 2. The proof of UNSAT is delegated to a
- * subclass.
- */
-class BitVectorProof : public TheoryProof
-{
- protected:
- BitVectorProof(theory::bv::TheoryBV* bv, TheoryProofEngine* proofEngine);
- virtual ~BitVectorProof(){};
-
- // Set of BV variables in the input. (e.g. "a" in [ a = 000 ] ^ [ a == 001 ])
- ExprSet d_declarations;
-
- // terms and formulas that are actually relevant to the proof
- ExprSet d_usedBB;
-
- ExprSet d_seenBBTerms; // terms that need to be bit-blasted
- std::vector<Expr> d_bbTerms; // order of bit-blasting
-
- /** atoms that need to be bit-blasted,
- * BV-literals -> (BV-literals <=> bool formula)
- * where a BV literal is a signed or unsigned comparison.
- */
- ExprToExpr d_bbAtoms;
-
- // map from Expr representing normalized lemma to ClauseId in SAT solver
- ExprToClauseId d_bbConflictMap;
-
- theory::bv::TBitblaster<Node>* d_bitblaster;
-
- /** In an LFSC proof the manifestation of this expression bit-level
- * representation will have a string name. This method returns that name.
- */
- std::string getBBTermName(Expr expr);
-
- /** A mapping from constant BV terms to identifiers that will refer to them in
- * an LFSC proof, if constant-letification is enabled.
- */
- std::map<Expr, std::string> d_constantLetMap;
-
- /** Should we introduced identifiers to refer to BV constant terms? It may
- * reduce the textual size of a proof!
- */
- bool d_useConstantLetification;
-
- /** Temporary storage for the set of nodes in the bitblasted formula which
- * correspond to CNF variables eventually used in the proof of unsat on the
- * CNF formula
- */
- std::set<Node> d_atomsInBitblastingProof;
-
- /**
- * Prints out
- * (a) a declaration of bit-level interpretations corresponding to bits in
- * the input BV terms.
- * (b) a proof that the each BV literal entails a boolean formula on
- * bitof expressions.
- */
- void printBitblasting(std::ostream& os, std::ostream& paren);
-
- /**
- * The proof that the bit-blasted SAT formula is correctly converted to CNF
- */
- std::unique_ptr<CnfProof> d_cnfProof;
-
- theory::TheoryId getTheoryId() override;
-
- public:
- void printOwnedTermAsType(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType) override;
-
- void printOwnedSort(Type type, std::ostream& os) override;
-
- /**
- * Populate the d_atomsInBitblastingProof member.
- * See its documentation
- */
- virtual void calculateAtomsInBitblastingProof() = 0;
-
- /**
- * Prints out a declaration of the bit-blasting, and the subsequent
- * conversion of the result to CNF
- *
- * @param os the stream to print to
- * @param paren a stream that will be placed at the back of the proof (for
- * closing parens)
- * @param letMap The let-map, which contains information about LFSC
- * identifiers and the values they reference.
- */
- virtual void printBBDeclarationAndCnf(std::ostream& os,
- std::ostream& paren,
- ProofLetMap& letMap) = 0;
-
- /**
- * Prints a proof of the empty clause.
- *
- * @param os the stream to print to
- * @param paren any parentheses to add to the end of the global proof
- */
- virtual void printEmptyClauseProof(std::ostream& os, std::ostream& paren);
-
- /**
- * Read the d_atomsInBitblastingProof member.
- * See its documentation.
- */
- const std::set<Node>* getAtomsInBitblastingProof();
-
- void registerTermBB(Expr term);
-
- /**
- * Informs the proof that the `atom` predicate was bitblasted into the
- * `atom_bb` term.
- *
- * The `atom` term must be a comparison of bitvectors, and the `atom_bb` term
- * a boolean formula on bitof expressions
- */
- void registerAtomBB(Expr atom, Expr atom_bb);
-
- void registerTerm(Expr term) override;
-
- /**
- * This must be done before registering any terms or atoms, since the CNF
- * proof must reflect the result of bitblasting those
- *
- * Feeds the SAT solver's true and false variables into the CNF stream.
- */
- virtual void initCnfProof(prop::CnfStream* cnfStream,
- context::Context* cnf,
- prop::SatVariable trueVar,
- prop::SatVariable falseVar) = 0;
-
- CnfProof* getCnfProof() { return d_cnfProof.get(); }
-
- /**
- * Attaches this BVP to the given SAT solver, initializing a SAT proof.
- *
- * This must be invoked before `initCnfProof` because a SAT proof must already
- * exist to initialize a CNF proof.
- */
- virtual void attachToSatSolver(prop::SatSolver& sat_solver) = 0;
-
- void setBitblaster(theory::bv::TBitblaster<Node>* bb);
-
- /**
- * Kind of a mess. Used for resulution-based BVP's, where in eager mode this
- * must be invoked before printing a proof of the empty clause. In lazy mode
- * the behavior and purpose are both highly unclear.
- *
- * This exists as a virtual method of BitVectorProof, and not
- * ResolutionBitVectorProof, because the machinery that invokes it is
- * high-level enough that it doesn't know the difference between clausal and
- * resolution proofs.
- *
- * TODO(aozdemir) figure out what is going on and clean this up
- * Issue: https://github.com/CVC4/CVC4/issues/2789
- */
- virtual void finalizeConflicts(std::vector<Expr>& conflicts){};
-
- private:
- ExprToString d_exprToVariableName;
-
- ExprToString d_assignedAliases;
- std::map<std::string, std::string> d_aliasToBindDeclaration;
- std::string assignAlias(Expr expr);
- bool hasAlias(Expr expr);
-
- // Functions for printing various BV terms. Helpers for BV's `printOwnedTerm`
- void printConstant(Expr term, std::ostream& os);
- void printOperatorNary(Expr term, std::ostream& os, const ProofLetMap& map);
- void printOperatorUnary(Expr term, std::ostream& os, const ProofLetMap& map);
- void printPredicate(Expr term, std::ostream& os, const ProofLetMap& map);
- void printOperatorParametric(Expr term, std::ostream& os, const ProofLetMap& map);
- void printBitOf(Expr term, std::ostream& os, const ProofLetMap& map);
-
- /**
- * Prints the LFSC construction of a bblast_term for `term`
- */
- void printTermBitblasting(Expr term, std::ostream& os);
-
- /**
- * For a given BV-atom (a comparison), prints a proof that that comparison
- * holds iff the bitblasted equivalent of it holds.
- * Uses a side-condidition to do the bit-blasting.
- */
- void printAtomBitblasting(Expr term, std::ostream& os, bool swap);
- void printAtomBitblastingToFalse(Expr term, std::ostream& os);
-
- void printSortDeclarations(std::ostream& os, std::ostream& paren) override;
- void printTermDeclarations(std::ostream& os, std::ostream& paren) override;
- void printDeferredDeclarations(std::ostream& os,
- std::ostream& paren) override;
- void printAliasingDeclarations(std::ostream& os,
- std::ostream& paren,
- const ProofLetMap& globalLetMap) override;
-
- void printConstantDisequalityProof(std::ostream& os,
- Expr c1,
- Expr c2,
- const ProofLetMap& globalLetMap) override;
- void printRewriteProof(std::ostream& os,
- const Node& n1,
- const Node& n2) override;
-};
-
-} // namespace proof
-
-}/* CVC4 namespace */
-
-#endif /* CVC4__BITVECTOR__PROOF_H */
diff --git a/src/proof/clausal_bitvector_proof.cpp b/src/proof/clausal_bitvector_proof.cpp
deleted file mode 100644
index 21e8056ca..000000000
--- a/src/proof/clausal_bitvector_proof.cpp
+++ /dev/null
@@ -1,412 +0,0 @@
-/********************* */
-/*! \file clausal_bitvector_proof.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir, Mathias Preiner, Andres Noetzli
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief Bitvector proof using the DRAT proof format
- **
- ** Contains DRAT-specific printing logic.
- **/
-
-#include "cvc4_private.h"
-
-#include <algorithm>
-#include <iostream>
-#include <iterator>
-#include <map>
-
-#include "options/bv_options.h"
-#include "proof/clausal_bitvector_proof.h"
-#include "proof/dimacs.h"
-#include "proof/drat/drat_proof.h"
-#include "proof/er/er_proof.h"
-#include "proof/lfsc_proof_printer.h"
-#include "proof/lrat/lrat_proof.h"
-#include "prop/sat_solver_types.h"
-#include "smt/smt_statistics_registry.h"
-#include "theory/bv/theory_bv.h"
-
-#if CVC4_USE_DRAT2ER
-#include "drat2er_options.h"
-#include "drat_trim_interface.h"
-#endif
-
-namespace CVC4 {
-
-namespace proof {
-
-ClausalBitVectorProof::ClausalBitVectorProof(theory::bv::TheoryBV* bv,
- TheoryProofEngine* proofEngine)
- : BitVectorProof(bv, proofEngine),
- d_clauses(),
- d_originalClauseIndices(),
- d_binaryDratProof(),
- d_coreClauseIndices(),
- d_dratTranslationStatistics(),
- d_dratOptimizationStatistics()
-{
-}
-
-void ClausalBitVectorProof::attachToSatSolver(prop::SatSolver& sat_solver)
-{
- sat_solver.setClausalProofLog(this);
-}
-
-void ClausalBitVectorProof::initCnfProof(prop::CnfStream* cnfStream,
- context::Context* cnf,
- prop::SatVariable trueVar,
- prop::SatVariable falseVar)
-{
- Assert(d_cnfProof == nullptr);
- d_cnfProof.reset(new LFSCCnfProof(cnfStream, cnf, "bb"));
-
- // Create a clause which forces the true variable to be true, and register it
- int trueClauseId = ClauseId(ProofManager::currentPM()->nextId());
- // with the CNF proof
- d_cnfProof->registerTrueUnitClause(trueClauseId);
- // and with (this) bit-vector proof
- prop::SatClause c{prop::SatLiteral(trueVar, false)};
- registerUsedClause(trueClauseId, c);
-
- // The same for false.
- int falseClauseId = ClauseId(ProofManager::currentPM()->nextId());
- d_cnfProof->registerFalseUnitClause(falseClauseId);
- c[0] = prop::SatLiteral(falseVar, true);
- registerUsedClause(falseClauseId, c);
-}
-
-void ClausalBitVectorProof::registerUsedClause(ClauseId id,
- prop::SatClause& clause)
-{
- prop::SatClause& emplaced_clause =
- d_clauses.emplace(id, clause).first->second;
- canonicalizeClause(emplaced_clause);
- d_originalClauseIndices.push_back(id);
-};
-
-void ClausalBitVectorProof::calculateAtomsInBitblastingProof()
-{
- optimizeDratProof();
-
- // Debug dump of DRAT Proof
- if (Debug.isOn("bv::clausal"))
- {
- std::string serializedDratProof = d_binaryDratProof.str();
- Debug("bv::clausal") << "option: " << options::bvOptimizeSatProof()
- << std::endl;
- Debug("bv::clausal") << "binary DRAT proof byte count: "
- << serializedDratProof.size() << std::endl;
- Debug("bv::clausal") << "clause count: " << d_coreClauseIndices.size()
- << std::endl;
- }
-
- // Empty any old record of which atoms were used
- d_atomsInBitblastingProof.clear();
- Assert(d_atomsInBitblastingProof.size() == 0);
-
- // For each used clause, ask the CNF proof which atoms are used in it
- for (const ClauseId usedIdx : d_coreClauseIndices)
- {
- d_cnfProof->collectAtoms(&d_clauses.at(usedIdx), d_atomsInBitblastingProof);
- }
-}
-
-struct SatClausePointerComparator
-{
- inline bool operator()(const prop::SatClause* const& l,
- const prop::SatClause* const& r) const
- {
- prop::SatClauseLessThan cmp;
- return cmp(*l, *r);
- }
-};
-
-void ClausalBitVectorProof::optimizeDratProof()
-{
- TimerStat::CodeTimer optimizeDratProofTimer{
- d_dratOptimizationStatistics.d_totalTime};
- if (options::bvOptimizeSatProof() == options::BvOptimizeSatProof::PROOF
- || options::bvOptimizeSatProof() == options::BvOptimizeSatProof::FORMULA)
- {
- Debug("bv::clausal") << "Optimizing DRAT" << std::endl;
- std::string formulaFilename("cvc4-dimacs-XXXXXX");
- std::string dratFilename("cvc4-drat-XXXXXX");
- std::string optDratFilename("cvc4-optimized-drat-XXXXXX");
- std::string optFormulaFilename("cvc4-optimized-formula-XXXXXX");
-
- {
- std::unique_ptr<std::fstream> formStream = openTmpFile(&formulaFilename);
- const int64_t startPos = static_cast<int64_t>(formStream->tellp());
- printDimacs(*formStream, d_clauses, d_originalClauseIndices);
- d_dratOptimizationStatistics.d_initialFormulaSize.setData(
- static_cast<int64_t>(formStream->tellp()) - startPos);
- formStream->close();
- }
-
- {
- std::unique_ptr<std::fstream> dratStream = openTmpFile(&dratFilename);
- const int64_t startPos = static_cast<int64_t>(dratStream->tellp());
- (*dratStream) << d_binaryDratProof.str();
- d_dratOptimizationStatistics.d_initialDratSize.setData(
- static_cast<int64_t>(dratStream->tellp()) - startPos);
- dratStream->close();
- }
-
- std::unique_ptr<std::fstream> optDratStream = openTmpFile(&optDratFilename);
- std::unique_ptr<std::fstream> optFormulaStream =
- openTmpFile(&optFormulaFilename);
-
-#if CVC4_USE_DRAT2ER
- {
- TimerStat::CodeTimer runDratTimeOptimizationTimer{
- d_dratOptimizationStatistics.d_toolTime};
- int dratTrimExitCode =
- drat2er::drat_trim::OptimizeWithDratTrim(formulaFilename,
- dratFilename,
- optFormulaFilename,
- optDratFilename,
- drat2er::options::QUIET);
- AlwaysAssert(dratTrimExitCode == 0)
- << "drat-trim exited with " << dratTrimExitCode;
- }
-#else
- Unimplemented()
- << "Proof production when using CryptoMiniSat requires drat2er.\n"
- << "Run contrib/get-drat2er, reconfigure with --drat2er, and rebuild";
-#endif
-
- {
- d_binaryDratProof.str("");
- Assert(d_binaryDratProof.str().size() == 0);
-
- const int64_t startPos = static_cast<int64_t>(d_binaryDratProof.tellp());
- std::ifstream lratStream(optDratFilename);
- std::copy(std::istreambuf_iterator<char>(lratStream),
- std::istreambuf_iterator<char>(),
- std::ostreambuf_iterator<char>(d_binaryDratProof));
- d_dratOptimizationStatistics.d_optimizedDratSize.setData(
- static_cast<int64_t>(d_binaryDratProof.tellp()) - startPos);
- }
-
- if (options::bvOptimizeSatProof() == options::BvOptimizeSatProof::FORMULA)
- {
- std::ifstream optFormulaInStream{optFormulaFilename};
- const int64_t startPos = static_cast<int64_t>(optFormulaInStream.tellg());
- std::vector<prop::SatClause> core = parseDimacs(optFormulaInStream);
- d_dratOptimizationStatistics.d_optimizedFormulaSize.setData(
- static_cast<int64_t>(optFormulaInStream.tellg()) - startPos);
-
- CodeTimer clauseMatchingTimer{
- d_dratOptimizationStatistics.d_clauseMatchingTime};
-
- // Now we need to compute the clause indices for the UNSAT core. This is a
- // bit difficult because drat-trim may have reordered clauses, and/or
- // removed duplicate literals. We use literal sets as the canonical clause
- // form.
- //
- // TODO (aozdemir) It may be better to use a hash map instead of a tree
- // map here.
- std::map<const prop::SatClause*, ClauseId, SatClausePointerComparator>
- cannonicalClausesToIndices;
- for (const auto& kv : d_clauses)
- {
- cannonicalClausesToIndices[&kv.second] = kv.first;
- }
-
- d_coreClauseIndices.clear();
-
- for (prop::SatClause& coreClause : core)
- {
- canonicalizeClause(coreClause);
- d_coreClauseIndices.push_back(
- cannonicalClausesToIndices.at(&coreClause));
- }
- Debug("bv::clausal") << "Optimizing the DRAT proof and the formula"
- << std::endl;
- }
- else
- {
- Debug("bv::clausal") << "Optimizing the DRAT proof but not the formula"
- << std::endl;
- d_coreClauseIndices = d_originalClauseIndices;
- }
-
- optFormulaStream->close();
-
- Assert(d_coreClauseIndices.size() > 0);
- remove(formulaFilename.c_str());
- remove(dratFilename.c_str());
- remove(optDratFilename.c_str());
- remove(optFormulaFilename.c_str());
- Debug("bv::clausal") << "Optimized DRAT" << std::endl;
- }
- else
- {
- Debug("bv::clausal") << "Not optimizing the formula or the DRAT proof"
- << std::endl;
- d_coreClauseIndices = d_originalClauseIndices;
- }
-}
-
-void ClausalBitVectorProof::canonicalizeClause(prop::SatClause& clause)
-{
- std::sort(clause.begin(), clause.end());
- clause.erase(std::unique(clause.begin(), clause.end()), clause.end());
-}
-
-ClausalBitVectorProof::DratTranslationStatistics::DratTranslationStatistics()
- : d_totalTime("proof::bv::dratTranslation::totalTime"),
- d_toolTime("proof::bv::dratTranslation::toolTime")
-{
- smtStatisticsRegistry()->registerStat(&d_totalTime);
- smtStatisticsRegistry()->registerStat(&d_toolTime);
-}
-
-ClausalBitVectorProof::DratTranslationStatistics::~DratTranslationStatistics()
-{
- smtStatisticsRegistry()->unregisterStat(&d_totalTime);
- smtStatisticsRegistry()->unregisterStat(&d_toolTime);
-}
-
-ClausalBitVectorProof::DratOptimizationStatistics::DratOptimizationStatistics()
- : d_totalTime("proof::bv::dratOptimization::totalTime"),
- d_toolTime("proof::bv::dratOptimization::toolTime"),
- d_clauseMatchingTime("proof::bv::dratOptimization::clauseMatchingTime"),
- d_initialDratSize("proof::bv::dratOptimization::initialDratSize", 0),
- d_optimizedDratSize("proof::bv::dratOptimization::optimizedDratSize", 0),
- d_initialFormulaSize("proof::bv::dratOptimization::initialFormulaSize",
- 0),
- d_optimizedFormulaSize(
- "proof::bv::dratOptimization::optimizedFormulaSize", 0)
-{
- smtStatisticsRegistry()->registerStat(&d_totalTime);
- smtStatisticsRegistry()->registerStat(&d_toolTime);
- smtStatisticsRegistry()->registerStat(&d_clauseMatchingTime);
- smtStatisticsRegistry()->registerStat(&d_initialDratSize);
- smtStatisticsRegistry()->registerStat(&d_optimizedDratSize);
- smtStatisticsRegistry()->registerStat(&d_initialFormulaSize);
- smtStatisticsRegistry()->registerStat(&d_optimizedFormulaSize);
-}
-
-ClausalBitVectorProof::DratOptimizationStatistics::~DratOptimizationStatistics()
-{
- smtStatisticsRegistry()->unregisterStat(&d_totalTime);
- smtStatisticsRegistry()->unregisterStat(&d_toolTime);
- smtStatisticsRegistry()->unregisterStat(&d_clauseMatchingTime);
- smtStatisticsRegistry()->unregisterStat(&d_initialDratSize);
- smtStatisticsRegistry()->unregisterStat(&d_optimizedDratSize);
- smtStatisticsRegistry()->unregisterStat(&d_initialFormulaSize);
- smtStatisticsRegistry()->unregisterStat(&d_optimizedFormulaSize);
-}
-
-void LfscClausalBitVectorProof::printTheoryLemmaProof(std::vector<Expr>& lemma,
- std::ostream& os,
- std::ostream& paren,
- const ProofLetMap& map)
-{
- Unreachable() << "Clausal bit-vector proofs should only be used in "
- "combination with eager "
- "bitblasting, which **does not use theory lemmas**";
-}
-
-void LfscClausalBitVectorProof::printBBDeclarationAndCnf(std::ostream& os,
- std::ostream& paren,
- ProofLetMap& letMap)
-{
- os << "\n;; Bitblasting mappings\n";
- printBitblasting(os, paren);
-
- os << "\n;; BB-CNF mappings\n";
- d_cnfProof->printAtomMapping(d_atomsInBitblastingProof, os, paren, letMap);
-
- os << "\n;; BB-CNF proofs\n";
- for (const ClauseId id : d_coreClauseIndices)
- {
- d_cnfProof->printCnfProofForClause(id, &d_clauses.at(id), os, paren);
- }
-}
-
-void LfscDratBitVectorProof::printEmptyClauseProof(std::ostream& os,
- std::ostream& paren)
-{
- Assert(options::bitblastMode() == options::BitblastMode::EAGER)
- << "the BV theory should only be proving bottom directly in the eager "
- "bitblasting mode";
-
- os << "\n;; Proof of input to SAT solver\n";
- os << "(@ proofOfSatInput ";
- paren << ")";
-
- LFSCProofPrinter::printSatInputProof(d_coreClauseIndices, os, "bb");
-
- os << "\n;; DRAT Proof Value\n";
- os << "(@ dratProof ";
- paren << ")";
- d_dratTranslationStatistics.d_totalTime.start();
- drat::DratProof pf = drat::DratProof::fromBinary(d_binaryDratProof.str());
- d_dratTranslationStatistics.d_totalTime.stop();
- pf.outputAsLfsc(os, 2);
- os << "\n";
-
- os << "\n;; Verification of DRAT Proof\n";
- os << "(drat_proof_of_bottom _ proofOfSatInput dratProof "
- << "\n)";
-}
-
-void LfscLratBitVectorProof::printEmptyClauseProof(std::ostream& os,
- std::ostream& paren)
-{
- Assert(options::bitblastMode() == options::BitblastMode::EAGER)
- << "the BV theory should only be proving bottom directly in the eager "
- "bitblasting mode";
-
- os << "\n;; Proof of input to SAT solver\n";
- os << "(@ proofOfCMap ";
- paren << ")";
- LFSCProofPrinter::printCMapProof(d_coreClauseIndices, os, "bb");
-
- os << "\n;; DRAT Proof Value\n";
- os << "(@ lratProof ";
- paren << ")";
- d_dratTranslationStatistics.d_totalTime.start();
- lrat::LratProof pf =
- lrat::LratProof::fromDratProof(d_clauses,
- d_coreClauseIndices,
- d_binaryDratProof.str(),
- d_dratTranslationStatistics.d_toolTime);
- d_dratTranslationStatistics.d_totalTime.stop();
- pf.outputAsLfsc(os);
- os << "\n";
-
- os << "\n;; Verification of DRAT Proof\n";
- os << "(lrat_proof_of_bottom _ proofOfCMap lratProof "
- << "\n)";
-}
-
-void LfscErBitVectorProof::printEmptyClauseProof(std::ostream& os,
- std::ostream& paren)
-{
- Assert(options::bitblastMode() == options::BitblastMode::EAGER)
- << "the BV theory should only be proving bottom directly in the eager "
- "bitblasting mode";
-
- d_dratTranslationStatistics.d_totalTime.start();
- er::ErProof pf =
- er::ErProof::fromBinaryDratProof(d_clauses,
- d_coreClauseIndices,
- d_binaryDratProof.str(),
- d_dratTranslationStatistics.d_toolTime);
- d_dratTranslationStatistics.d_totalTime.stop();
-
- pf.outputAsLfsc(os);
-}
-
-} // namespace proof
-
-}; // namespace CVC4
diff --git a/src/proof/clausal_bitvector_proof.h b/src/proof/clausal_bitvector_proof.h
deleted file mode 100644
index 28a53c90c..000000000
--- a/src/proof/clausal_bitvector_proof.h
+++ /dev/null
@@ -1,189 +0,0 @@
-/********************* */
-/*! \file clausal_bitvector_proof.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir, Mathias Preiner
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief Bitvector proof for clausal (DRAT/LRAT) formats
- **
- ** An internal string stream is hooked up to CryptoMiniSat, which spits out a
- ** binary DRAT proof. Depending on which kind of proof we're going to turn
- ** that into, we process it in different ways.
- **/
-
-#include "cvc4_private.h"
-
-#ifndef CVC4__PROOF__CLAUSAL_BITVECTOR_PROOF_H
-#define CVC4__PROOF__CLAUSAL_BITVECTOR_PROOF_H
-
-#include <iostream>
-#include <sstream>
-#include <unordered_map>
-
-#include "expr/expr.h"
-#include "proof/bitvector_proof.h"
-#include "proof/drat/drat_proof.h"
-#include "proof/lrat/lrat_proof.h"
-#include "proof/theory_proof.h"
-#include "prop/cnf_stream.h"
-#include "prop/sat_solver_types.h"
-#include "theory/bv/theory_bv.h"
-#include "util/statistics_registry.h"
-
-namespace CVC4 {
-
-namespace proof {
-
-class ClausalBitVectorProof : public BitVectorProof
-{
- public:
- ClausalBitVectorProof(theory::bv::TheoryBV* bv,
- TheoryProofEngine* proofEngine);
-
- ~ClausalBitVectorProof() = default;
-
- void attachToSatSolver(prop::SatSolver& sat_solver) override;
-
- void initCnfProof(prop::CnfStream* cnfStream,
- context::Context* cnf,
- prop::SatVariable trueVar,
- prop::SatVariable falseVar) override;
-
- std::ostream& getDratOstream() { return d_binaryDratProof; }
-
- void registerUsedClause(ClauseId id, prop::SatClause& clause);
-
- void calculateAtomsInBitblastingProof() override;
-
- protected:
- // A list of all clauses and their ids which are passed into the SAT solver
- std::unordered_map<ClauseId, prop::SatClause> d_clauses{};
- std::vector<ClauseId> d_originalClauseIndices{};
- // Stores the proof recieved from the SAT solver.
- std::ostringstream d_binaryDratProof{};
- std::vector<ClauseId> d_coreClauseIndices{};
-
- struct DratTranslationStatistics
- {
- DratTranslationStatistics();
- ~DratTranslationStatistics();
-
- // Total time spent doing translation (optimized binary DRAT -> in memory
- // target format including IO, postprocessing, etc.)
- TimerStat d_totalTime;
- // Time that the external tool actually spent
- TimerStat d_toolTime;
- };
-
- DratTranslationStatistics d_dratTranslationStatistics;
-
- private:
- // Optimizes the DRAT proof stored in `d_binaryDratProof` and returns a list
- // of clause actually needed to check that proof (a smaller UNSAT core)
- void optimizeDratProof();
-
- // Given reference to a SAT clause encoded as a vector of literals, puts the
- // literals into a canonical order
- static void canonicalizeClause(prop::SatClause& clause);
-
- struct DratOptimizationStatistics
- {
- DratOptimizationStatistics();
- ~DratOptimizationStatistics();
-
- // Total time spent using drat-trim to optimize the DRAT proof/formula
- // (including IO, etc.)
- TimerStat d_totalTime;
- // Time that drat-trim actually spent optimizing the DRAT proof/formula
- TimerStat d_toolTime;
- // Time that was spent matching clauses in drat-trim's output to clauses in
- // its input
- TimerStat d_clauseMatchingTime;
- // Bytes in binary DRAT proof before optimization
- IntStat d_initialDratSize;
- // Bytes in binary DRAT proof after optimization
- IntStat d_optimizedDratSize;
- // Bytes in textual DIMACS bitblasted formula before optimization
- IntStat d_initialFormulaSize;
- // Bytes in textual DIMACS bitblasted formula after optimization
- IntStat d_optimizedFormulaSize;
- };
-
- DratOptimizationStatistics d_dratOptimizationStatistics;
-};
-
-/**
- * A representation of a clausal proof of a bitvector problem's UNSAT nature
- */
-class LfscClausalBitVectorProof : public ClausalBitVectorProof
-{
- public:
- LfscClausalBitVectorProof(theory::bv::TheoryBV* bv,
- TheoryProofEngine* proofEngine)
- : ClausalBitVectorProof(bv, proofEngine)
- {
- }
-
- void printTheoryLemmaProof(std::vector<Expr>& lemma,
- std::ostream& os,
- std::ostream& paren,
- const ProofLetMap& map) override;
- void printBBDeclarationAndCnf(std::ostream& os,
- std::ostream& paren,
- ProofLetMap& letMap) override;
-};
-
-/**
- * A DRAT proof for a bit-vector problem
- */
-class LfscDratBitVectorProof : public LfscClausalBitVectorProof
-{
- public:
- LfscDratBitVectorProof(theory::bv::TheoryBV* bv,
- TheoryProofEngine* proofEngine)
- : LfscClausalBitVectorProof(bv, proofEngine)
- {
- }
-
- void printEmptyClauseProof(std::ostream& os, std::ostream& paren) override;
-};
-
-/**
- * An LRAT proof for a bit-vector problem
- */
-class LfscLratBitVectorProof : public LfscClausalBitVectorProof
-{
- public:
- LfscLratBitVectorProof(theory::bv::TheoryBV* bv,
- TheoryProofEngine* proofEngine)
- : LfscClausalBitVectorProof(bv, proofEngine)
- {
- }
-
- void printEmptyClauseProof(std::ostream& os, std::ostream& paren) override;
-};
-
-/**
- * An Extended Resolution proof for a bit-vector problem
- */
-class LfscErBitVectorProof : public LfscClausalBitVectorProof
-{
- public:
- LfscErBitVectorProof(theory::bv::TheoryBV* bv, TheoryProofEngine* proofEngine)
- : LfscClausalBitVectorProof(bv, proofEngine)
- {
- }
-
- void printEmptyClauseProof(std::ostream& os, std::ostream& paren) override;
-};
-
-} // namespace proof
-
-} // namespace CVC4
-
-#endif /* CVC4__PROOF__CLAUSAL_BITVECTOR_PROOF_H */
diff --git a/src/proof/clause_id.h b/src/proof/clause_id.h
index b2d36c9cb..5d7ec94f6 100644
--- a/src/proof/clause_id.h
+++ b/src/proof/clause_id.h
@@ -28,6 +28,13 @@ namespace CVC4 {
*/
typedef unsigned ClauseId;
+/** Reserved clauseId values used in the resolution proof. The represent,
+ * respectively, the empty clause, that adding the clause to the SAT solver was
+ * a no-op, and that an error occurred when trying to add. */
+const ClauseId ClauseIdEmpty(-1);
+const ClauseId ClauseIdUndef(-2);
+const ClauseId ClauseIdError(-3);
+
}/* CVC4 namespace */
#endif /* CVC4__PROOF__CLAUSE_ID_H */
diff --git a/src/proof/cnf_proof.cpp b/src/proof/cnf_proof.cpp
index 677bf2f8c..258e2fdb2 100644
--- a/src/proof/cnf_proof.cpp
+++ b/src/proof/cnf_proof.cpp
@@ -19,8 +19,6 @@
#include "proof/clause_id.h"
#include "proof/proof_manager.h"
-#include "proof/proof_utils.h"
-#include "proof/theory_proof.h"
#include "prop/cnf_stream.h"
#include "prop/minisat/minisat.h"
#include "prop/sat_solver_types.h"
@@ -32,11 +30,7 @@ CnfProof::CnfProof(prop::CnfStream* stream,
const std::string& name)
: d_cnfStream(stream)
, d_clauseToAssertion(ctx)
- , d_assertionToProofRule(ctx)
, d_currentAssertionStack()
- , d_currentDefinitionStack()
- , d_clauseToDefinition(ctx)
- , d_definitions()
, d_cnfDeps()
, d_name(name)
{
@@ -46,86 +40,22 @@ CnfProof::CnfProof(prop::CnfStream* stream,
CnfProof::~CnfProof() {}
-bool CnfProof::isAssertion(Node node) {
- return d_assertionToProofRule.find(node) !=
- d_assertionToProofRule.end();
-}
-
-bool CnfProof::isDefinition(Node node) {
- return d_definitions.find(node) !=
- d_definitions.end();
-}
-
-ProofRule CnfProof::getProofRule(Node node) {
- Assert(isAssertion(node));
- NodeToProofRule::iterator it = d_assertionToProofRule.find(node);
- return (*it).second;
-}
-
-ProofRule CnfProof::getProofRule(ClauseId clause) {
- TNode assertion = getAssertionForClause(clause);
- return getProofRule(assertion);
-}
-
Node CnfProof::getAssertionForClause(ClauseId clause) {
ClauseIdToNode::const_iterator it = d_clauseToAssertion.find(clause);
Assert(it != d_clauseToAssertion.end() && !(*it).second.isNull());
return (*it).second;
}
-Node CnfProof::getDefinitionForClause(ClauseId clause) {
- ClauseIdToNode::const_iterator it = d_clauseToDefinition.find(clause);
- Assert(it != d_clauseToDefinition.end());
- return (*it).second;
-}
-
-void CnfProof::registerConvertedClause(ClauseId clause, bool explanation) {
+void CnfProof::registerConvertedClause(ClauseId clause)
+{
Assert(clause != ClauseIdUndef && clause != ClauseIdError
&& clause != ClauseIdEmpty);
-
- // Explanations do not need a CNF conversion proof since they are in CNF
- // (they will only need a theory proof as they are theory valid)
- if (explanation) {
- Debug("proof:cnf") << "CnfProof::registerConvertedClause "
- << clause << " explanation? " << explanation << std::endl;
- Assert(d_explanations.find(clause) == d_explanations.end());
- d_explanations.insert(clause);
- return;
- }
-
Node current_assertion = getCurrentAssertion();
- Node current_expr = getCurrentDefinition();
- Debug("proof:cnf") << "CnfProof::registerConvertedClause "
- << clause << " assertion = " << current_assertion
- << clause << " definition = " << current_expr << std::endl;
+ Debug("proof:cnf") << "CnfProof::registerConvertedClause " << clause
+ << " assertion = " << current_assertion << std::endl;
setClauseAssertion(clause, current_assertion);
- setClauseDefinition(clause, current_expr);
-}
-
-void CnfProof::registerTrueUnitClause(ClauseId clauseId)
-{
- Node trueNode = NodeManager::currentNM()->mkConst<bool>(true);
- pushCurrentAssertion(trueNode);
- pushCurrentDefinition(trueNode);
- registerConvertedClause(clauseId);
- popCurrentAssertion();
- popCurrentDefinition();
- d_cnfStream->ensureLiteral(trueNode);
- d_trueUnitClause = clauseId;
-}
-
-void CnfProof::registerFalseUnitClause(ClauseId clauseId)
-{
- Node falseNode = NodeManager::currentNM()->mkConst<bool>(false).notNode();
- pushCurrentAssertion(falseNode);
- pushCurrentDefinition(falseNode);
- registerConvertedClause(clauseId);
- popCurrentAssertion();
- popCurrentDefinition();
- d_cnfStream->ensureLiteral(falseNode);
- d_falseUnitClause = clauseId;
}
void CnfProof::setClauseAssertion(ClauseId clause, Node expr) {
@@ -145,56 +75,15 @@ void CnfProof::setClauseAssertion(ClauseId clause, Node expr) {
return;
}
- d_clauseToAssertion.insert (clause, expr);
+ d_clauseToAssertion.insert(clause, expr);
}
-void CnfProof::setClauseDefinition(ClauseId clause, Node definition) {
- Debug("proof:cnf") << "CnfProof::setClauseDefinition "
- << clause << " definition " << definition << std::endl;
- // We keep the first definition
- if (d_clauseToDefinition.find(clause) != d_clauseToDefinition.end())
- return;
-
- d_clauseToDefinition.insert(clause, definition);
- d_definitions.insert(definition);
-}
-
-void CnfProof::registerAssertion(Node assertion, ProofRule reason) {
- Debug("proof:cnf") << "CnfProof::registerAssertion "
- << assertion << " reason " << reason << std::endl;
- // We can obtain the assertion from different reasons (e.g. if the
- // assertion is a lemma over shared terms both theories can generate
- // the same lemma) We only need to prove the lemma in one way, so we
- // keep the first reason.
- if (isAssertion(assertion)) {
- return;
- }
- d_assertionToProofRule.insert(assertion, reason);
-}
-
-LemmaProofRecipe CnfProof::getProofRecipe(const std::set<Node> &lemma) {
- Assert(d_lemmaToProofRecipe.find(lemma) != d_lemmaToProofRecipe.end());
- return d_lemmaToProofRecipe[lemma];
-}
-
-bool CnfProof::haveProofRecipe(const std::set<Node> &lemma) {
- return d_lemmaToProofRecipe.find(lemma) != d_lemmaToProofRecipe.end();
-}
-
-void CnfProof::setCnfDependence(Node from, Node to) {
- Debug("proof:cnf") << "CnfProof::setCnfDependence "
- << "from " << from << std::endl
- << " to " << to << std::endl;
-
- Assert(from != to);
- d_cnfDeps.insert(std::make_pair(from, to));
-}
-
-void CnfProof::pushCurrentAssertion(Node assertion) {
+void CnfProof::pushCurrentAssertion(Node assertion, bool isInput)
+{
Debug("proof:cnf") << "CnfProof::pushCurrentAssertion " << assertion
<< std::endl;
- d_currentAssertionStack.push_back(assertion);
+ d_currentAssertionStack.push_back(std::pair<Node, bool>(assertion, isInput));
Debug("proof:cnf") << "CnfProof::pushCurrentAssertion "
<< "new stack size = " << d_currentAssertionStack.size()
@@ -205,7 +94,7 @@ void CnfProof::popCurrentAssertion() {
Assert(d_currentAssertionStack.size());
Debug("proof:cnf") << "CnfProof::popCurrentAssertion "
- << d_currentAssertionStack.back() << std::endl;
+ << d_currentAssertionStack.back().first << std::endl;
d_currentAssertionStack.pop_back();
@@ -216,740 +105,12 @@ void CnfProof::popCurrentAssertion() {
Node CnfProof::getCurrentAssertion() {
Assert(d_currentAssertionStack.size());
- return d_currentAssertionStack.back();
+ return d_currentAssertionStack.back().first;
}
-void CnfProof::setProofRecipe(LemmaProofRecipe* proofRecipe) {
- Assert(proofRecipe);
- Assert(proofRecipe->getNumSteps() > 0);
- d_lemmaToProofRecipe[proofRecipe->getBaseAssertions()] = *proofRecipe;
-}
-
-void CnfProof::pushCurrentDefinition(Node definition) {
- Debug("proof:cnf") << "CnfProof::pushCurrentDefinition "
- << definition << std::endl;
-
- d_currentDefinitionStack.push_back(definition);
-}
-
-void CnfProof::popCurrentDefinition() {
- Assert(d_currentDefinitionStack.size());
-
- Debug("proof:cnf") << "CnfProof::popCurrentDefinition "
- << d_currentDefinitionStack.back() << std::endl;
-
- d_currentDefinitionStack.pop_back();
-}
-
-Node CnfProof::getCurrentDefinition() {
- Assert(d_currentDefinitionStack.size());
- return d_currentDefinitionStack.back();
-}
-
-Node CnfProof::getAtom(prop::SatVariable var) {
- prop::SatLiteral lit (var);
- Node node = d_cnfStream->getNode(lit);
- return node;
-}
-
-void CnfProof::collectAtoms(const prop::SatClause* clause,
- std::set<Node>& atoms) {
- for (unsigned i = 0; i < clause->size(); ++i) {
- prop::SatLiteral lit = clause->operator[](i);
- prop::SatVariable var = lit.getSatVariable();
- TNode atom = getAtom(var);
- if (atoms.find(atom) == atoms.end()) {
- atoms.insert(atom);
- }
- }
-}
-
-prop::SatLiteral CnfProof::getLiteral(TNode atom) {
- return d_cnfStream->getLiteral(atom);
-}
-
-bool CnfProof::hasLiteral(TNode atom) {
- return d_cnfStream->hasLiteral(atom);
-}
-
-void CnfProof::ensureLiteral(TNode atom, bool noPreregistration) {
- d_cnfStream->ensureLiteral(atom, noPreregistration);
-}
-
-void CnfProof::collectAtomsForClauses(const IdToSatClause& clauses,
- std::set<Node>& atoms) {
- IdToSatClause::const_iterator it = clauses.begin();
- for (; it != clauses.end(); ++it) {
- const prop::SatClause* clause = it->second;
- collectAtoms(clause, atoms);
- }
-}
-
-void CnfProof::collectAtomsAndRewritesForLemmas(const IdToSatClause& lemmaClauses,
- std::set<Node>& atoms,
- NodePairSet& rewrites) {
- IdToSatClause::const_iterator it = lemmaClauses.begin();
- for (; it != lemmaClauses.end(); ++it) {
- const prop::SatClause* clause = it->second;
-
- // TODO: just calculate the map from ID to recipe once,
- // instead of redoing this over and over again
- std::vector<Expr> clause_expr;
- std::set<Node> clause_expr_nodes;
- for(unsigned i = 0; i < clause->size(); ++i) {
- prop::SatLiteral lit = (*clause)[i];
- Node node = getAtom(lit.getSatVariable());
- Expr atom = node.toExpr();
- if (atom.isConst()) {
- Assert(atom == utils::mkTrue());
- continue;
- }
- clause_expr_nodes.insert(lit.isNegated() ? node.notNode() : node);
- }
-
- LemmaProofRecipe recipe = getProofRecipe(clause_expr_nodes);
-
- for (unsigned i = 0; i < recipe.getNumSteps(); ++i) {
- const LemmaProofRecipe::ProofStep* proofStep = recipe.getStep(i);
- Node atom = proofStep->getLiteral();
-
- if (atom == Node()) {
- // The last proof step always has the empty node as its target...
- continue;
- }
-
- if (atom.getKind() == kind::NOT) {
- atom = atom[0];
- }
-
- atoms.insert(atom);
- }
-
- LemmaProofRecipe::RewriteIterator rewriteIt;
- for (rewriteIt = recipe.rewriteBegin(); rewriteIt != recipe.rewriteEnd(); ++rewriteIt) {
- rewrites.insert(NodePair(rewriteIt->first, rewriteIt->second));
-
- // The unrewritten terms also need to have literals, so insert them into atoms
- Node rewritten = rewriteIt->first;
- if (rewritten.getKind() == kind::NOT) {
- rewritten = rewritten[0];
- }
- atoms.insert(rewritten);
- }
- }
-}
-
-void CnfProof::collectAssertionsForClauses(const IdToSatClause& clauses,
- NodeSet& assertions) {
- IdToSatClause::const_iterator it = clauses.begin();
- for (; it != clauses.end(); ++it) {
- TNode used_assertion = getAssertionForClause(it->first);
- assertions.insert(used_assertion);
- // it can be the case that a definition for a clause is an assertion
- // but it is not the assertion for the clause
- // e.g. the assertions [(and a b), a]
- TNode used_definition = getDefinitionForClause(it->first);
- if (isAssertion(used_definition)) {
- assertions.insert(used_definition);
- }
- }
-}
-
-// Detects whether a clause has x v ~x for some x
-// If so, returns the positive occurence's idx first, then the negative's
-Maybe<std::pair<size_t, size_t>> CnfProof::detectTrivialTautology(
- const prop::SatClause& clause)
+bool CnfProof::getCurrentAssertionKind()
{
- // a map from a SatVariable to its previous occurence's polarity and location
- std::map<prop::SatVariable, std::pair<bool, size_t>> varsToPolsAndIndices;
- for (size_t i = 0; i < clause.size(); ++i)
- {
- prop::SatLiteral lit = clause[i];
- prop::SatVariable var = lit.getSatVariable();
- bool polarity = !lit.isNegated();
-
- // Check if this var has already occured w/ opposite polarity
- auto iter = varsToPolsAndIndices.find(var);
- if (iter != varsToPolsAndIndices.end() && iter->second.first != polarity)
- {
- if (iter->second.first)
- {
- return Maybe<std::pair<size_t, size_t>>{
- std::make_pair(iter->second.second, i)};
- }
- else
- {
- return Maybe<std::pair<size_t, size_t>>{
- std::make_pair(i, iter->second.second)};
- }
- }
- varsToPolsAndIndices[var] = std::make_pair(polarity, i);
- }
- return Maybe<std::pair<size_t, size_t>>{};
-}
-
-void LFSCCnfProof::printAtomMapping(const std::set<Node>& atoms,
- std::ostream& os,
- std::ostream& paren) {
- std::set<Node>::const_iterator it = atoms.begin();
- std::set<Node>::const_iterator end = atoms.end();
-
- for (;it != end; ++it) {
- os << "(decl_atom ";
- Node atom = *it;
- prop::SatVariable var = getLiteral(atom).getSatVariable();
- //FIXME hideous
- LFSCTheoryProofEngine* pe = (LFSCTheoryProofEngine*)ProofManager::currentPM()->getTheoryProofEngine();
- pe->printLetTerm(atom.toExpr(), os);
-
- os << " (\\ " << ProofManager::getVarName(var, d_name);
- os << " (\\ " << ProofManager::getAtomName(var, d_name) << "\n";
- paren << ")))";
- }
-}
-
-void LFSCCnfProof::printAtomMapping(const std::set<Node>& atoms,
- std::ostream& os,
- std::ostream& paren,
- ProofLetMap &letMap) {
- std::set<Node>::const_iterator it = atoms.begin();
- std::set<Node>::const_iterator end = atoms.end();
-
- for (;it != end; ++it) {
- os << "(decl_atom ";
- Node atom = *it;
- prop::SatVariable var = getLiteral(atom).getSatVariable();
- //FIXME hideous
- LFSCTheoryProofEngine* pe = (LFSCTheoryProofEngine*)ProofManager::currentPM()->getTheoryProofEngine();
- if (pe->printsAsBool(atom.toExpr())) os << "(p_app ";
- pe->printBoundTerm(atom.toExpr(), os, letMap);
- if (pe->printsAsBool(atom.toExpr())) os << ")";
-
- os << " (\\ " << ProofManager::getVarName(var, d_name);
- os << " (\\ " << ProofManager::getAtomName(var, d_name) << "\n";
- paren << ")))";
- }
-}
-
-// maps each expr to the position it had in the clause and the polarity it had
-Node LFSCCnfProof::clauseToNode(const prop::SatClause& clause,
- std::map<Node, unsigned>& childIndex,
- std::map<Node, bool>& childPol ) {
- std::vector< Node > children;
- for (unsigned i = 0; i < clause.size(); ++i) {
- prop::SatLiteral lit = clause[i];
- prop::SatVariable var = lit.getSatVariable();
- Node atom = getAtom(var);
- children.push_back( lit.isNegated() ? atom.negate() : atom );
- childIndex[atom] = i;
- childPol[atom] = !lit.isNegated();
- }
- return children.size()==1 ? children[0] :
- NodeManager::currentNM()->mkNode(kind::OR, children );
-}
-
-void LFSCCnfProof::printCnfProofForClause(ClauseId id,
- const prop::SatClause* clause,
- std::ostream& os,
- std::ostream& paren) {
- Debug("cnf-pf") << std::endl << std::endl << "LFSCCnfProof::printCnfProofForClause( " << id << " ) starting "
- << std::endl;
-
- os << "(satlem _ _ ";
- std::ostringstream clause_paren;
- printClause(*clause, os, clause_paren);
- os << "(clausify_false ";
-
- // FIXMEEEEEEEEEEEE
- // os <<"trust)";
- // os << clause_paren.str()
- // << " (\\ " << ProofManager::getInputClauseName(id, d_name) << "\n";
- // paren << "))";
-
- // return;
-
- Assert(clause->size() > 0);
-
- // If the clause contains x v ~x, it's easy!
- //
- // It's important to check for this case, because our other logic for
- // recording the location of variables in the clause assumes the clause is
- // not tautological
- Maybe<std::pair<size_t, size_t>> isTrivialTaut =
- detectTrivialTautology(*clause);
- if (isTrivialTaut.just())
- {
- size_t posIndexInClause = isTrivialTaut.value().first;
- size_t negIndexInClause = isTrivialTaut.value().second;
- Trace("cnf-pf") << "; Indices " << posIndexInClause << " (+) and "
- << negIndexInClause << " (-) make this clause a tautology"
- << std::endl;
-
- std::string proofOfPos =
- ProofManager::getLitName((*clause)[negIndexInClause], d_name);
- std::string proofOfNeg =
- ProofManager::getLitName((*clause)[posIndexInClause], d_name);
- os << "(contra _ " << proofOfPos << " " << proofOfNeg << ")";
- }
- else
- {
- Node base_assertion = getDefinitionForClause(id);
-
- // get the assertion for the clause id
- std::map<Node, unsigned> childIndex;
- std::map<Node, bool> childPol;
- Node assertion = clauseToNode(*clause, childIndex, childPol);
- // if there is no reason, construct assertion directly. This can happen
- // for unit clauses.
- if (base_assertion.isNull())
- {
- base_assertion = assertion;
- }
- // os_base is proof of base_assertion
- std::stringstream os_base;
-
- // checks if tautological definitional clause or top-level clause
- // and prints the proof of the top-level formula
- bool is_input = printProofTopLevel(base_assertion, os_base);
-
- if (is_input)
- {
- Debug("cnf-pf") << std::endl
- << "; base assertion is input. proof: " << os_base.str()
- << std::endl;
- }
-
- // get base assertion with polarity
- bool base_pol = base_assertion.getKind() != kind::NOT;
- base_assertion = base_assertion.getKind() == kind::NOT ? base_assertion[0]
- : base_assertion;
-
- std::map<Node, unsigned>::iterator itci = childIndex.find(base_assertion);
- bool is_in_clause = itci != childIndex.end();
- unsigned base_index = is_in_clause ? itci->second : 0;
- Trace("cnf-pf") << std::endl;
- Trace("cnf-pf") << "; input = " << is_input
- << ", is_in_clause = " << is_in_clause << ", id = " << id
- << ", assertion = " << assertion
- << ", base assertion = " << base_assertion << std::endl;
- if (!is_input)
- {
- Assert(is_in_clause);
- prop::SatLiteral blit = (*clause)[base_index];
- os_base << ProofManager::getLitName(blit, d_name);
- base_pol = !childPol[base_assertion]; // WHY? if the case is =>
- }
- Trace("cnf-pf") << "; polarity of base assertion = " << base_pol
- << std::endl;
- Trace("cnf-pf") << "; proof of base : " << os_base.str() << std::endl;
-
- bool success = false;
- if (is_input && is_in_clause && childPol[base_assertion] == base_pol)
- {
- // if both in input and in clause, the proof is trivial. this is the case
- // for unit clauses.
- Trace("cnf-pf") << "; trivial" << std::endl;
- os << "(contra _ ";
- success = true;
- prop::SatLiteral lit = (*clause)[itci->second];
- if (base_pol)
- {
- os << os_base.str() << " " << ProofManager::getLitName(lit, d_name);
- }
- else
- {
- os << ProofManager::getLitName(lit, d_name) << " " << os_base.str();
- }
- os << ")";
- } else if ((base_assertion.getKind()==kind::AND && !base_pol) ||
- ((base_assertion.getKind()==kind::OR ||
- base_assertion.getKind()==kind::IMPLIES) && base_pol)) {
- Trace("cnf-pf") << "; and/or case 1" << std::endl;
- success = true;
- std::stringstream os_main;
- std::stringstream os_paren;
- //eliminate each one
- for (int j = base_assertion.getNumChildren()-2; j >= 0; j--) {
- Trace("cnf-pf-debug") << "; base_assertion[" << j << "] is: " << base_assertion[j]
- << ", and its kind is: " << base_assertion[j].getKind() << std::endl ;
-
- Node child_base = base_assertion[j].getKind()==kind::NOT ?
- base_assertion[j][0] : base_assertion[j];
- bool child_pol = base_assertion[j].getKind()!=kind::NOT;
-
- Trace("cnf-pf-debug") << "; child " << j << " "
- << ", child base: " << child_base
- << ", child pol: " << child_pol
- << ", childPol[child_base] "
- << childPol[child_base] << ", base pol: " << base_pol << std::endl;
-
- std::map< Node, unsigned >::iterator itcic = childIndex.find( child_base );
-
- if( itcic!=childIndex.end() ){
- //Assert( child_pol==childPol[child_base] );
- os_main << "(or_elim_1 _ _ ";
- prop::SatLiteral lit = (*clause)[itcic->second];
- // Should be if in the original formula it was negated
- // if( childPol[child_base] && base_pol ){
-
- // Adding the below to catch a specific case where the first child of an IMPLIES is negative,
- // in which case we need not_not introduction.
- if (base_assertion.getKind() == kind::IMPLIES && !child_pol && base_pol) {
- os_main << "(not_not_intro _ " << ProofManager::getLitName(lit, d_name) << ") ";
- } else if (childPol[child_base] && base_pol) {
- os_main << ProofManager::getLitName(lit, d_name) << " ";
- }else{
- os_main << "(not_not_intro _ " << ProofManager::getLitName(lit, d_name) << ") ";
- }
- if( base_assertion.getKind()==kind::AND ){
- os_main << "(not_and_elim _ _ ";
- os_paren << ")";
- }
- os_paren << ")";
- }else{
- success = false;
- }
- }
-
- if( success ){
- if( base_assertion.getKind()==kind::IMPLIES ){
- os_main << "(impl_elim _ _ ";
- }
- os_main << os_base.str();
- if( base_assertion.getKind()==kind::IMPLIES ){
- os_main << ")";
- }
- os_main << os_paren.str();
- int last_index = base_assertion.getNumChildren()-1;
- Node child_base = base_assertion[last_index].getKind()==kind::NOT ? base_assertion[last_index][0] : base_assertion[last_index];
- //bool child_pol = base_assertion[last_index].getKind()!=kind::NOT;
- std::map< Node, unsigned >::iterator itcic = childIndex.find( child_base );
- if( itcic!=childIndex.end() ){
- os << "(contra _ ";
- prop::SatLiteral lit = (*clause)[itcic->second];
- if( childPol[child_base] && base_pol){
- os << os_main.str() << " " << ProofManager::getLitName(lit, d_name);
- }else{
- os << ProofManager::getLitName(lit, d_name) << " " << os_main.str();
- }
- os << ")";
- }else{
- success = false;
- }
- }
- }else if ((base_assertion.getKind()==kind::AND && base_pol) ||
- ((base_assertion.getKind()==kind::OR ||
- base_assertion.getKind()==kind::IMPLIES) && !base_pol)) {
-
- std::stringstream os_main;
-
- Node iatom;
- if (is_in_clause) {
- Assert(assertion.getNumChildren() == 2);
- iatom = assertion[ base_index==0 ? 1 : 0];
- } else {
- Assert(assertion.getNumChildren() == 1);
- iatom = assertion[0];
- }
-
- Trace("cnf-pf") << "; and/or case 2, iatom = " << iatom << std::endl;
- Node e_base = iatom.getKind()==kind::NOT ? iatom[0] : iatom;
- bool e_pol = iatom.getKind()!=kind::NOT;
- std::map< Node, unsigned >::iterator itcic = childIndex.find( e_base );
- if( itcic!=childIndex.end() ){
- prop::SatLiteral lit = (*clause)[itcic->second];
- //eliminate until we find iatom
- for( unsigned j=0; j<base_assertion.getNumChildren(); j++ ){
- Node child_base = base_assertion[j].getKind()==kind::NOT ? base_assertion[j][0] : base_assertion[j];
- bool child_pol = base_assertion[j].getKind()!=kind::NOT;
- if( j==0 && base_assertion.getKind()==kind::IMPLIES ){
- child_pol = !child_pol;
- }
- if( e_base==child_base && (e_pol==child_pol)==(base_assertion.getKind()==kind::AND) ){
- success = true;
- bool elimNn =( ( base_assertion.getKind()==kind::OR || ( base_assertion.getKind()==kind::IMPLIES && j==1 ) ) && e_pol );
- if( elimNn ){
- os_main << "(not_not_elim _ ";
- }
- std::stringstream os_paren;
- if( j+1<base_assertion.getNumChildren() ){
- os_main << "(and_elim_1 _ _ ";
- if( base_assertion.getKind()==kind::OR || base_assertion.getKind()==kind::IMPLIES ){
- os_main << "(not_" << ( base_assertion.getKind()==kind::OR ? "or" : "impl" ) << "_elim _ _ ";
- os_paren << ")";
- }
- os_paren << ")";
- }
- for( unsigned k=0; k<j; k++ ){
- os_main << "(and_elim_2 _ _ ";
- if( base_assertion.getKind()==kind::OR || base_assertion.getKind()==kind::IMPLIES ){
- os_main << "(not_" << ( base_assertion.getKind()==kind::OR ? "or" : "impl" ) << "_elim _ _ ";
- os_paren << ")";
- }
- os_paren << ")";
- }
- os_main << os_base.str() << os_paren.str();
- if( elimNn ){
- os_main << ")";
- }
- break;
- }
- }
- if( success ){
- os << "(contra _ ";
- if( !e_pol ){
- os << ProofManager::getLitName(lit, d_name) << " " << os_main.str();
- }else{
- os << os_main.str() << " " << ProofManager::getLitName(lit, d_name);
- }
- os << ")";
- }
- }
- }else if( base_assertion.getKind()==kind::XOR || ( base_assertion.getKind()==kind::EQUAL && base_assertion[0].getType().isBoolean() ) ){
- //eliminate negation
- int num_nots_2 = 0;
- int num_nots_1 = 0;
- Kind k;
- if( !base_pol ){
- if( base_assertion.getKind()==kind::EQUAL ){
- num_nots_2 = 1;
- }
- k = kind::EQUAL;
- }else{
- k = base_assertion.getKind();
- }
- std::vector< unsigned > indices;
- std::vector< bool > pols;
- success = true;
- int elimNum = 0;
- for( unsigned i=0; i<2; i++ ){
- Node child_base = base_assertion[i].getKind()==kind::NOT ? base_assertion[i][0] : base_assertion[i];
- bool child_pol = base_assertion[i].getKind()!=kind::NOT;
- std::map< Node, unsigned >::iterator itcic = childIndex.find( child_base );
- if( itcic!=childIndex.end() ){
- indices.push_back( itcic->second );
- pols.push_back( childPol[child_base] );
- if( i==0 ){
- //figure out which way to elim
- elimNum = child_pol==childPol[child_base] ? 2 : 1;
- if( (elimNum==2)==(k==kind::EQUAL) ){
- num_nots_2++;
- }
- if( elimNum==1 ){
- num_nots_1++;
- }
- }
- }else{
- success = false;
- break;
- }
- }
- Trace("cnf-pf") << std::endl << "; num nots = " << num_nots_2 << std::endl;
- if( success ){
- os << "(contra _ ";
- std::stringstream os_base_n;
- if( num_nots_2==2 ){
- os_base_n << "(not_not_elim _ ";
- }
- os_base_n << "(or_elim_1 _ _ ";
- prop::SatLiteral lit1 = (*clause)[indices[0]];
- if( !pols[0] || num_nots_1==1 ){
- os_base_n << "(not_not_intro _ " << ProofManager::getLitName(lit1, d_name) << ") ";
- }else{
- Trace("cnf-pf-debug") << "CALLING getlitname" << std::endl;
- os_base_n << ProofManager::getLitName(lit1, d_name) << " ";
- }
- Assert(elimNum != 0);
- os_base_n << "(" << ( k==kind::EQUAL ? "iff" : "xor" ) << "_elim_" << elimNum << " _ _ ";
- if( !base_pol ){
- os_base_n << "(not_" << ( base_assertion.getKind()==kind::EQUAL ? "iff" : "xor" ) << "_elim _ _ " << os_base.str() << ")";
- }else{
- os_base_n << os_base.str();
- }
- os_base_n << "))";
- if( num_nots_2==2 ){
- os_base_n << ")";
- num_nots_2 = 0;
- }
- prop::SatLiteral lit2 = (*clause)[indices[1]];
- if( pols[1]==(num_nots_2==0) ){
- os << os_base_n.str() << " ";
- if( num_nots_2==1 ){
- os << "(not_not_intro _ " << ProofManager::getLitName(lit2, d_name) << ")";
- }else{
- os << ProofManager::getLitName(lit2, d_name);
- }
- }else{
- os << ProofManager::getLitName(lit2, d_name) << " " << os_base_n.str();
- }
- os << ")";
- }
- }else if( base_assertion.getKind()==kind::ITE ){
- std::map< unsigned, unsigned > appears;
- std::map< unsigned, Node > appears_expr;
- unsigned appears_count = 0;
- for( unsigned r=0; r<3; r++ ){
- Node child_base = base_assertion[r].getKind()==kind::NOT ? base_assertion[r][0] : base_assertion[r];
- std::map< Node, unsigned >::iterator itcic = childIndex.find( child_base );
- if( itcic!=childIndex.end() ){
- appears[r] = itcic->second;
- appears_expr[r] = child_base;
- appears_count++;
- }
- }
- if( appears_count==2 ){
- success = true;
- int elimNum = 1;
- unsigned index1 = 0;
- unsigned index2 = 1;
- if( appears.find( 0 )==appears.end() ){
- elimNum = 3;
- index1 = 1;
- index2 = 2;
- }else if( appears.find( 1 )==appears.end() ){
- elimNum = 2;
- index1 = 0;
- index2 = 2;
- }
- std::stringstream os_main;
- os_main << "(or_elim_1 _ _ ";
- prop::SatLiteral lit1 = (*clause)[appears[index1]];
- if( !childPol[appears_expr[index1]] || elimNum==1 || ( elimNum==3 && !base_pol ) ){
- os_main << "(not_not_intro _ " << ProofManager::getLitName(lit1, d_name) << ") ";
- }else{
- os_main << ProofManager::getLitName(lit1, d_name) << " ";
- }
- os_main << "(" << ( base_pol ? "" : "not_" ) << "ite_elim_" << elimNum << " _ _ _ ";
- os_main << os_base.str() << "))";
- os << "(contra _ ";
- prop::SatLiteral lit2 = (*clause)[appears[index2]];
- if( !childPol[appears_expr[index2]] || !base_pol ){
- os << ProofManager::getLitName(lit2, d_name) << " " << os_main.str();
- }else{
- os << os_main.str() << " " << ProofManager::getLitName(lit2, d_name);
- }
- os << ")";
- }
- }else if( base_assertion.isConst() ){
- bool pol = base_assertion==NodeManager::currentNM()->mkConst( true );
- if( pol!=base_pol ){
- success = true;
- if( pol ){
- os << "(contra _ truth " << os_base.str() << ")";
- }else{
- os << os_base.str();
- }
- }
- }
-
- if( !success ){
- Trace("cnf-pf") << std::endl;
- Trace("cnf-pf") << ";!!!!!!!!! CnfProof : Can't process " << assertion << ", base = " << base_assertion << ", id = " << id << std::endl;
- Trace("cnf-pf") << ";!!!!!!!!! Clause is : ";
- for (unsigned i = 0; i < clause->size(); ++i) {
- Trace("cnf-pf") << (*clause)[i] << " ";
- }
- Trace("cnf-pf") << std::endl;
- os << "trust-bad";
- }
- }
-
- os << ")" << clause_paren.str()
- << " (\\ " << ProofManager::getInputClauseName(id, d_name) << "\n";
-
- paren << "))";
-}
-
-void LFSCCnfProof::printClause(const prop::SatClause& clause,
- std::ostream& os,
- std::ostream& paren) {
- for (unsigned i = 0; i < clause.size(); ++i) {
- prop::SatLiteral lit = clause[i];
- prop::SatVariable var = lit.getSatVariable();
- if (lit.isNegated()) {
- os << "(ast _ _ _ " << ProofManager::getAtomName(var, d_name) <<" (\\ " << ProofManager::getLitName(lit, d_name) << " ";
- paren << "))";
- } else {
- os << "(asf _ _ _ " << ProofManager::getAtomName(var, d_name) <<" (\\ " << ProofManager::getLitName(lit, d_name) << " ";
- paren << "))";
- }
- }
-}
-
-// print a proof of the top-level formula e, based on the input assertions
-bool LFSCCnfProof::printProofTopLevel(Node e, std::ostream& out) {
- if (!isAssertion(e)) {
- // check if deduced by CNF
- // dependence on top level fact i.e. a depends on (a and b)
- NodeToNode::const_iterator itd = d_cnfDeps.find(e);
- if (itd != d_cnfDeps.end()) {
- TNode parent = itd->second;
- //check if parent is an input assertion
- std::stringstream out_parent;
- if (printProofTopLevel(parent, out_parent)) {
- if(parent.getKind()==kind::AND ||
- (parent.getKind()==kind::NOT && (parent[0].getKind()==kind::IMPLIES ||
- parent[0].getKind()==kind::OR))) {
- Node parent_base = parent.getKind()==kind::NOT ? parent[0] : parent;
- Node e_base = e.getKind()==kind::NOT ? e[0] : e;
- bool e_pol = e.getKind()!=kind::NOT;
- for( unsigned i=0; i<parent_base.getNumChildren(); i++ ){
- Node child_base = parent_base[i].getKind()==kind::NOT ? parent_base[i][0] : parent_base[i];
- bool child_pol = parent_base[i].getKind()!=kind::NOT;
- if( parent_base.getKind()==kind::IMPLIES && i==0 ){
- child_pol = !child_pol;
- }
- if (e_base==child_base &&
- (e_pol==child_pol)==(parent_base.getKind()==kind::AND)) {
- bool elimNn = ((parent_base.getKind()==kind::OR ||
- (parent_base.getKind()==kind::IMPLIES && i==1)) && e_pol);
- if (elimNn) {
- out << "(not_not_elim _ ";
- }
- std::stringstream out_paren;
- if (i+1 < parent_base.getNumChildren()) {
- out << "(and_elim_1 _ _ ";
- if( parent_base.getKind()==kind::OR ||
- parent_base.getKind()==kind::IMPLIES ){
- out << "(not_" << ( parent_base.getKind()==kind::OR ? "or" : "impl" )
- << "_elim _ _ ";
- out_paren << ")";
- }
- out_paren << ")";
- }
- for( unsigned j=0; j<i; j++ ){
- out << "(and_elim_2 _ _ ";
- if( parent_base.getKind()==kind::OR || parent_base.getKind()==kind::IMPLIES ){
- out << "(not_" << ( parent_base.getKind()==kind::OR ? "or" : "impl" ) << "_elim _ _ ";
- out_paren << ")";
- }
- out_paren << ")";
- }
- out << out_parent.str();
- out << out_paren.str();
- if( elimNn ){
- out << ")";
- }
- return true;
- }
- }
- } else {
- Trace("cnf-pf-debug") << "; isInputAssertion : parent of " << e
- << " is not correct type (" << parent << ")" << std::endl;
- }
- } else {
- Trace("cnf-pf-debug") << "; isInputAssertion : parent of " << e
- << " is not input" << std::endl;
- }
- } else {
- Trace("cnf-pf-debug") << "; isInputAssertion : " << e
- << " has no parent" << std::endl;
- }
- return false;
- } else {
- out << ProofManager::getPreprocessedAssertionName(e);
- return true;
- }
+ return d_currentAssertionStack.back().second;
}
} /* CVC4 namespace */
diff --git a/src/proof/cnf_proof.h b/src/proof/cnf_proof.h
index 56993583e..e437ef722 100644
--- a/src/proof/cnf_proof.h
+++ b/src/proof/cnf_proof.h
@@ -27,10 +27,8 @@
#include "context/cdhashmap.h"
#include "proof/clause_id.h"
-#include "proof/lemma_proof.h"
#include "proof/sat_proof.h"
#include "util/maybe.h"
-#include "util/proof.h"
namespace CVC4 {
namespace prop {
@@ -44,11 +42,11 @@ typedef std::unordered_map<Node, Node, NodeHashFunction> NodeToNode;
typedef std::unordered_set<ClauseId> ClauseIdSet;
typedef context::CDHashMap<ClauseId, Node> ClauseIdToNode;
-typedef context::CDHashMap<Node, ProofRule, NodeHashFunction> NodeToProofRule;
-typedef std::map<std::set<Node>, LemmaProofRecipe> LemmaToRecipe;
typedef std::pair<Node, Node> NodePair;
typedef std::set<NodePair> NodePairSet;
+typedef std::unordered_set<Node, NodeHashFunction> NodeSet;
+
class CnfProof {
protected:
CVC4::prop::CnfStream* d_cnfStream;
@@ -56,23 +54,9 @@ protected:
/** Map from ClauseId to the assertion that lead to adding this clause **/
ClauseIdToNode d_clauseToAssertion;
- /** Map from assertion to reason for adding assertion **/
- NodeToProofRule d_assertionToProofRule;
-
- /** Map from lemma to the recipe for proving it **/
- LemmaToRecipe d_lemmaToProofRecipe;
-
- /** Top of stack is assertion currently being converted to CNF **/
- std::vector<Node> d_currentAssertionStack;
-
- /** Top of stack is top-level fact currently being converted to CNF **/
- std::vector<Node> d_currentDefinitionStack;
-
- /** Map from ClauseId to the top-level fact that lead to adding this clause **/
- ClauseIdToNode d_clauseToDefinition;
-
- /** Top-level facts that follow from assertions during convertAndAssert **/
- NodeSet d_definitions;
+ /** Top of stack is assertion currently being converted to CNF. Also saves
+ * whether it is input (rather than a lemma). **/
+ std::vector<std::pair<Node, bool>> d_currentAssertionStack;
/** Map from top-level fact to facts/assertion that it follows from **/
NodeToNode d_cnfDeps;
@@ -84,132 +68,36 @@ protected:
// The clause ID of the unit clause defining the false SAT literal.
ClauseId d_falseUnitClause;
- bool isDefinition(Node node);
-
- Node getDefinitionForClause(ClauseId clause);
-
std::string d_name;
public:
CnfProof(CVC4::prop::CnfStream* cnfStream,
context::Context* ctx,
const std::string& name);
-
-
- Node getAtom(prop::SatVariable var);
- prop::SatLiteral getLiteral(TNode node);
- bool hasLiteral(TNode node);
- void ensureLiteral(TNode node, bool noPreregistration = false);
-
- void collectAtoms(const prop::SatClause* clause,
- std::set<Node>& atoms);
- void collectAtomsForClauses(const IdToSatClause& clauses,
- std::set<Node>& atoms);
- void collectAtomsAndRewritesForLemmas(const IdToSatClause& lemmaClauses,
- std::set<Node>& atoms,
- NodePairSet& rewrites);
- void collectAssertionsForClauses(const IdToSatClause& clauses,
- NodeSet& assertions);
+ ~CnfProof();
/** Methods for logging what the CnfStream does **/
// map the clause back to the current assertion where it came from
- // if it is an explanation, it does not have a CNF proof since it is
- // already in CNF
- void registerConvertedClause(ClauseId clause, bool explanation=false);
-
- // The CNF proof has a special relationship to true and false.
- // In particular, it need to know the identity of clauses defining
- // canonical true and false literals in the underlying SAT solver.
- void registerTrueUnitClause(ClauseId clauseId);
- void registerFalseUnitClause(ClauseId clauseId);
- inline ClauseId getTrueUnitClause() { return d_trueUnitClause; };
- inline ClauseId getFalseUnitClause() { return d_falseUnitClause; };
-
- /** Clause is one of the clauses defining the node expression*/
- void setClauseDefinition(ClauseId clause, Node node);
+ void registerConvertedClause(ClauseId clause);
/** Clause is one of the clauses defining top-level assertion node*/
void setClauseAssertion(ClauseId clause, Node node);
- void registerAssertion(Node assertion, ProofRule reason);
- void setCnfDependence(Node from, Node to);
-
- void pushCurrentAssertion(Node assertion); // the current assertion being converted
+ /** Current assertion being converted and whether it is an input (rather than
+ * a lemma) */
+ void pushCurrentAssertion(Node assertion, bool isInput = false);
void popCurrentAssertion();
Node getCurrentAssertion();
-
- void pushCurrentDefinition(Node assertion); // the current Tseitin definition being converted
- void popCurrentDefinition();
- Node getCurrentDefinition();
+ bool getCurrentAssertionKind();
/**
* Checks whether the assertion stack is empty.
*/
bool isAssertionStackEmpty() const { return d_currentAssertionStack.empty(); }
- void setProofRecipe(LemmaProofRecipe* proofRecipe);
- LemmaProofRecipe getProofRecipe(const std::set<Node> &lemma);
- bool haveProofRecipe(const std::set<Node> &lemma);
-
// accessors for the leaf assertions that are being converted to CNF
- bool isAssertion(Node node);
- ProofRule getProofRule(Node assertion);
- ProofRule getProofRule(ClauseId clause);
Node getAssertionForClause(ClauseId clause);
-
- /** Virtual methods for printing things **/
- virtual void printAtomMapping(const std::set<Node>& atoms,
- std::ostream& os,
- std::ostream& paren) = 0;
- virtual void printAtomMapping(const std::set<Node>& atoms,
- std::ostream& os,
- std::ostream& paren,
- ProofLetMap &letMap) = 0;
-
- // Detects whether a clause has x v ~x for some x
- // If so, returns the positive occurence's idx first, then the negative's
- static Maybe<std::pair<size_t, size_t>> detectTrivialTautology(
- const prop::SatClause& clause);
- virtual void printClause(const prop::SatClause& clause,
- std::ostream& os,
- std::ostream& paren) = 0;
- virtual void printCnfProofForClause(ClauseId id,
- const prop::SatClause* clause,
- std::ostream& os,
- std::ostream& paren) = 0;
- virtual ~CnfProof();
};/* class CnfProof */
-class LFSCCnfProof : public CnfProof {
- Node clauseToNode( const prop::SatClause& clause,
- std::map<Node, unsigned>& childIndex,
- std::map<Node, bool>& childPol );
- bool printProofTopLevel(Node e, std::ostream& out);
-public:
- LFSCCnfProof(CVC4::prop::CnfStream* cnfStream,
- context::Context* ctx,
- const std::string& name)
- : CnfProof(cnfStream, ctx, name)
- {}
- ~LFSCCnfProof() {}
-
- void printAtomMapping(const std::set<Node>& atoms,
- std::ostream& os,
- std::ostream& paren) override;
-
- void printAtomMapping(const std::set<Node>& atoms,
- std::ostream& os,
- std::ostream& paren,
- ProofLetMap& letMap) override;
-
- void printClause(const prop::SatClause& clause,
- std::ostream& os,
- std::ostream& paren) override;
- void printCnfProofForClause(ClauseId id,
- const prop::SatClause* clause,
- std::ostream& os,
- std::ostream& paren) override;
-};/* class LFSCCnfProof */
-
} /* CVC4 namespace */
#endif /* CVC4__CNF_PROOF_H */
diff --git a/src/proof/dimacs.cpp b/src/proof/dimacs.cpp
deleted file mode 100644
index d9d9f8c1c..000000000
--- a/src/proof/dimacs.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-/********************* */
-/*! \file dimacs.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief DIMACS SAT Problem Format
- **
- ** Defines serialization for SAT problems as DIMACS
- **/
-
-#include "proof/dimacs.h"
-
-#include "base/check.h"
-
-#include <iostream>
-
-namespace CVC4 {
-namespace proof {
-
-// Prints the literal as a (+) or (-) int
-// Not operator<< b/c that represents negation as ~
-std::ostream& textOut(std::ostream& o, const prop::SatLiteral& l)
-{
- if (l.isNegated())
- {
- o << "-";
- }
- return o << l.getSatVariable() + 1;
-}
-
-// Prints the clause as a space-separated list of ints
-// Not operator<< b/c that represents negation as ~
-std::ostream& textOut(std::ostream& o, const prop::SatClause& c)
-{
- for (const auto& l : c)
- {
- textOut(o, l) << " ";
- }
- return o << "0";
-}
-
-void printDimacs(std::ostream& o,
- const std::unordered_map<ClauseId, prop::SatClause>& clauses,
- const std::vector<ClauseId>& usedIndices)
-{
- size_t maxVar = 0;
- for (const ClauseId i : usedIndices)
- {
- const prop::SatClause& c = clauses.at(i);
- for (const auto& l : c)
- {
- if (l.getSatVariable() + 1 > maxVar)
- {
- maxVar = l.getSatVariable() + 1;
- }
- }
- }
- o << "p cnf " << maxVar << " " << usedIndices.size() << '\n';
- for (const ClauseId i : usedIndices)
- {
- const prop::SatClause& c = clauses.at(i);
- for (const auto& l : c)
- {
- if (l.isNegated())
- {
- o << '-';
- }
- o << l.getSatVariable() + 1 << " ";
- }
- o << "0\n";
- }
-}
-
-std::vector<prop::SatClause> parseDimacs(std::istream& in)
-{
- std::string tag;
- uint64_t nVars;
- uint64_t nClauses;
-
- in >> tag;
- Assert(in.good());
- Assert(tag == "p");
-
- in >> tag;
- Assert(in.good());
- Assert(tag == "cnf");
-
- in >> nVars;
- Assert(nVars >= 0);
-
- in >> nClauses;
- Assert(nClauses >= 0);
-
- std::vector<prop::SatClause> cnf;
- for (uint64_t i = 0; i < nClauses; ++i)
- {
- cnf.emplace_back();
- int64_t lit;
- in >> lit;
- Assert(in.good());
- while (lit != 0)
- {
- cnf.back().emplace_back(std::abs(lit) - 1, lit < 0);
- in >> lit;
- Assert(static_cast<uint64_t>(std::abs(lit)) <= nVars);
- Assert(in.good());
- }
- }
-
- return cnf;
-}
-
-} // namespace proof
-} // namespace CVC4
diff --git a/src/proof/dimacs.h b/src/proof/dimacs.h
deleted file mode 100644
index 405b33208..000000000
--- a/src/proof/dimacs.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/********************* */
-/*! \file dimacs.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief DIMACS SAT Problem Format
- **
- ** Defines serialization/deserialization for SAT problems as DIMACS
- **/
-
-#include "cvc4_private.h"
-
-#ifndef CVC4__PROOF__DIMACS_H
-#define CVC4__PROOF__DIMACS_H
-
-#include <iosfwd>
-#include <memory>
-#include <unordered_map>
-
-#include "proof/clause_id.h"
-#include "prop/sat_solver_types.h"
-
-namespace CVC4 {
-namespace proof {
-
-/**
- * Prints the literal as a (+) or (-) int
- * Not operator<< b/c that represents negation as ~
- *
- * @param o where to print
- * @param l the literal to print
- *
- * @return the original stream
- */
-std::ostream& textOut(std::ostream& o, const prop::SatLiteral& l);
-
-/**
- * Prints the clause as a space-separated list of ints
- * Not operator<< b/c that represents literal negation as ~
- *
- * @param o where to print
- * @param c the clause to print
- *
- * @return the original stream
- */
-std::ostream& textOut(std::ostream& o, const prop::SatClause& c);
-
-/**
- * Prints a CNF formula in DIMACS format
- *
- * @param o where to print to
- * @param usedClauses the CNF formula
- */
-void printDimacs(std::ostream& o,
- const std::unordered_map<ClauseId, prop::SatClause>& clauses,
- const std::vector<ClauseId>& usedIndices);
-
-std::vector<prop::SatClause> parseDimacs(std::istream& i);
-
-} // namespace proof
-} // namespace CVC4
-
-#endif // CVC4__PROOF__DIMACS_H
diff --git a/src/proof/drat/drat_proof.cpp b/src/proof/drat/drat_proof.cpp
deleted file mode 100644
index ee9c42d77..000000000
--- a/src/proof/drat/drat_proof.cpp
+++ /dev/null
@@ -1,291 +0,0 @@
-/********************* */
-/*! \file drat_proof.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir, Mathias Preiner
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief DRAT Proof Format
- **
- ** Defines deserialization for DRAT proofs.
- **/
-
-#include "proof/drat/drat_proof.h"
-
-#include <algorithm>
-#include <bitset>
-#include <iostream>
-
-#include "proof/proof_manager.h"
-
-namespace CVC4 {
-namespace proof {
-namespace drat {
-
-// helper functions for parsing the binary DRAT format.
-
-/**
- * Parses a binary literal which starts at `start` and must not go beyond `end`
- *
- * Leaves the iterator one past the last byte that is a part of the clause.
- *
- * If the literal overruns `end`, then raises a `InvalidDratProofException`.
- */
-SatLiteral parse_binary_literal(std::string::const_iterator& start,
- const std::string::const_iterator& proof_end)
-{
- // lit is encoded as uint represented by a variable-length byte sequence
- uint64_t literal_represented_as_uint = 0;
- for (uint8_t shift = 0; start != proof_end; ++start, shift += 7)
- {
- // Check whether shift is so large that we're going to lose some
- // information
- if (shift + 7 >= 64)
- {
- throw InvalidDratProofException(
- "While parsing a DRAT proof, encountered a literal that was too "
- "long");
- }
- unsigned char byte = *start;
- // The MSB of the byte is an indicator of whether the sequence continues
- bool continued = (byte >> 7) & 1;
- uint64_t numeric_part = byte & 0x7f;
- literal_represented_as_uint |= numeric_part << shift;
- if (!continued)
- {
- // LSB of `literal_represented_as_uint` indicates negation.
- bool negated = literal_represented_as_uint & 1;
- // Rest is the literal number
- SatVariable var_number = literal_represented_as_uint >> 1;
- ++start;
- // Internal clauses start at 0, external ones start at 1.
- return SatLiteral(var_number - 1, negated);
- }
- }
- throw InvalidDratProofException(
- "Literal in DRAT proof was not done when "
- "EOF was encountered");
-}
-
-/**
- * Parses a binary clause which starts at `start` and must not go beyond `end`
- *
- * Leaves the iterator one past the last byte that is a part of the clause.
- * That is, one past the null byte.
- *
- * If the clause overruns `end`, then raises a `InvalidDratProofException`.
- */
-SatClause parse_binary_clause(std::string::const_iterator& start,
- const std::string::const_iterator& proof_end)
-{
- SatClause clause;
- // A clause is a 0-terminated sequence of literals
- while (start != proof_end)
- {
- // Is the clause done?
- if (*start == 0)
- {
- ++start;
- return clause;
- }
- else
- {
- // If not, parse another literal
- clause.emplace_back(parse_binary_literal(start, proof_end));
- }
- }
- // We've overrun the end of the byte stream.
- throw InvalidDratProofException(
- "Clause in DRAT proof was not done when "
- "EOF was encountered");
-}
-
-/**
- * Writes this SAT literal in the textual DIMACS format. i.e. as a non-zero
- * integer.
- *
- * Since internally +0 and -0 are valid literals, we add one to each
- * literal's number (SAT variable) when outputtting it.
- *
- * @param os the stream to write to
- * @param l the literal to write
- */
-void outputLiteralAsDimacs(std::ostream& os, SatLiteral l)
-{
- if (l.isNegated())
- {
- os << '-';
- }
- // add 1 to convert between internal literals and their DIMACS
- // representaations.
- os << l.getSatVariable() + 1;
-}
-
-// DratInstruction implementation
-
-DratInstruction::DratInstruction(DratInstructionKind kind, SatClause clause)
- : d_kind(kind), d_clause(clause)
-{
- // All intialized
-}
-
-void DratInstruction::outputAsText(std::ostream& os) const
-{
- switch (d_kind)
- {
- case DratInstructionKind::ADDITION:
- {
- for (const SatLiteral& l : d_clause)
- {
- outputLiteralAsDimacs(os, l);
- os << ' ';
- }
- os << '0' << std::endl;
- break;
- }
- case DratInstructionKind::DELETION:
- {
- os << "d ";
- for (const SatLiteral& l : d_clause)
- {
- outputLiteralAsDimacs(os, l);
- os << ' ';
- }
- os << '0' << std::endl;
- break;
- }
- default:
- {
- Unreachable() << "Unknown DRAT instruction kind";
- }
- }
-}
-
-// DratProof implementation
-
-DratProof::DratProof() : d_instructions() {}
-
-// See the "binary format" section of
-// https://www.cs.utexas.edu/~marijn/drat-trim/
-DratProof DratProof::fromBinary(const std::string& s)
-{
- DratProof proof;
- if (Debug.isOn("pf::drat"))
- {
- Debug("pf::drat") << "Parsing binary DRAT proof" << std::endl;
- Debug("pf::drat") << "proof length: " << s.length() << " bytes"
- << std::endl;
- Debug("pf::drat") << "proof as bytes: ";
- for (char i : s)
- {
- if (i == 'a' || i == 'd')
- {
- Debug("pf::drat") << std::endl << " " << std::bitset<8>(i);
- }
- else
- {
- Debug("pf::drat") << " " << std::bitset<8>(i);
- }
- }
- Debug("pf::drat") << std::endl << "parsing proof..." << std::endl;
- }
-
- // For each instruction
- for (auto i = s.cbegin(), end = s.cend(); i != end;)
- {
- switch (*i)
- {
- case 'a':
- {
- ++i;
- proof.d_instructions.emplace_back(ADDITION,
- parse_binary_clause(i, end));
- break;
- }
- case 'd':
- {
- ++i;
- proof.d_instructions.emplace_back(DELETION,
- parse_binary_clause(i, end));
- break;
- }
- default:
- {
- std::ostringstream errmsg;
- errmsg << "Invalid instruction in Drat proof. Instruction bits: "
- << std::bitset<8>(*i)
- << ". Expected 'a' (01100001) or 'd' "
- "(01100100).";
- throw InvalidDratProofException(errmsg.str());
- }
- }
- }
-
- if (Debug.isOn("pf::drat"))
- {
- Debug("pf::drat") << "Printing out DRAT in textual format:" << std::endl;
- proof.outputAsText(Debug("pf::drat"));
- }
-
- return proof;
-};
-
-const std::vector<DratInstruction>& DratProof::getInstructions() const
-{
- return d_instructions;
-};
-
-void DratProof::outputAsText(std::ostream& os) const
-{
- for (const DratInstruction& instruction : d_instructions)
- {
- instruction.outputAsText(os);
- os << "\n";
- }
-};
-
-void DratProof::outputAsLfsc(std::ostream& os, uint8_t indentation) const
-{
- for (const DratInstruction& i : d_instructions)
- {
- if (indentation > 0)
- {
- std::fill_n(std::ostream_iterator<char>(os), indentation, ' ');
- }
- os << "(";
- switch (i.d_kind)
- {
- case ADDITION:
- {
- os << "DRATProofa ";
- break;
- }
- case DELETION:
- {
- os << "DRATProofd ";
- break;
- }
- default:
- {
- Unreachable() << "Unrecognized DRAT instruction kind";
- }
- }
- for (const SatLiteral& l : i.d_clause)
- {
- os << "(clc (" << (l.isNegated() ? "neg " : "pos ")
- << ProofManager::getVarName(l.getSatVariable(), "bb") << ") ";
- }
- os << "cln";
- std::fill_n(std::ostream_iterator<char>(os), i.d_clause.size(), ')');
- os << "\n";
- }
- os << "DRATProofn";
- std::fill_n(std::ostream_iterator<char>(os), d_instructions.size(), ')');
-}
-} // namespace drat
-} // namespace proof
-} // namespace CVC4
diff --git a/src/proof/drat/drat_proof.h b/src/proof/drat/drat_proof.h
deleted file mode 100644
index 1213c80c7..000000000
--- a/src/proof/drat/drat_proof.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/********************* */
-/*! \file drat_proof.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir, Mathias Preiner
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief DRAT Proof Format
- **
- ** Declares C++ types that represent a DRAT proof.
- ** Defines serialization for these types.
- **
- ** You can find an introduction to DRAT in the drat-trim paper:
- ** http://www.cs.utexas.edu/~marijn/publications/drat-trim.pdf
- **
- **/
-
-#ifndef CVC4__PROOF__DRAT__DRAT_PROOF_H
-#define CVC4__PROOF__DRAT__DRAT_PROOF_H
-
-#include "cvc4_private.h"
-#include "prop/sat_solver.h"
-#include "prop/sat_solver_types.h"
-
-namespace CVC4 {
-namespace proof {
-namespace drat {
-
-using CVC4::prop::SatClause;
-using CVC4::prop::SatLiteral;
-using CVC4::prop::SatVariable;
-
-class CVC4_PUBLIC InvalidDratProofException : public CVC4::Exception
-{
- public:
- InvalidDratProofException() : Exception("Invalid DRAT Proof") {}
-
- InvalidDratProofException(const std::string& msg) : Exception(msg) {}
-
- InvalidDratProofException(const char* msg) : Exception(msg) {}
-}; /* class InvalidDratProofException */
-
-enum DratInstructionKind
-{
- ADDITION,
- DELETION
-};
-
-struct DratInstruction
-{
- DratInstruction(DratInstructionKind kind, SatClause clause);
-
- /**
- * Write the DRAT instruction in textual format.
- * The format is described in:
- * http://www.cs.utexas.edu/~marijn/publications/drat-trim.pdf
- *
- * @param os the stream to write to
- */
- void outputAsText(std::ostream& os) const;
-
- DratInstructionKind d_kind;
- SatClause d_clause;
-};
-
-class DratProof
-{
- public:
- DratProof(const DratProof&) = default;
-
- DratProof(DratProof&&) = default;
-
- ~DratProof() = default;
-
- /**
- * Parses a DRAT proof from the **binary format**.
- * The format is described at:
- * https://www.cs.utexas.edu/~marijn/drat-trim/#contact
- *
- * What do the standard authors mean by the format being "binary"?
- * They just mean that proofs in this format should be understood as
- * sequences of bytes, not sequences of ASCII/Unicode/your favorite character
- * set characters.
- *
- * @param binaryProof a string containing the bytes of the binary proof.
- * Even though the proof isn't text, it's safe to store it in a string
- * because C++ strings don't make any gaurantees about the encoding of
- * their contents. This makes them (effectively) just byte sequences.
- *
- * @return the parsed proof
- */
- static DratProof fromBinary(const std::string& binaryProof);
-
- /**
- * @return The instructions in this proof
- */
- const std::vector<DratInstruction>& getInstructions() const;
-
- /**
- * Write the DRAT proof in textual format.
- * The format is described in:
- * http://www.cs.utexas.edu/~marijn/publications/drat-trim.pdf
- *
- * @param os the stream to write to
- */
- void outputAsText(std::ostream& os) const;
-
- /**
- * Write the DRAT proof as an LFSC value
- * The format is from the LFSC signature drat.plf
- *
- * Reads the current `ProofManager` to determine what the variables should be
- * named.
- *
- * @param os the stream to write to
- * @param indentation the number of spaces to indent each proof instruction
- */
- void outputAsLfsc(std::ostream& os, uint8_t indentation) const;
-
- private:
- /**
- * Create an DRAT proof with no instructions.
- */
- DratProof();
-
- /**
- * The instructions of the DRAT proof.
- */
- std::vector<DratInstruction> d_instructions;
-};
-
-} // namespace drat
-} // namespace proof
-} // namespace CVC4
-
-#endif // CVC4__PROOF__DRAT__DRAT_PROOF_H
diff --git a/src/proof/er/er_proof.cpp b/src/proof/er/er_proof.cpp
deleted file mode 100644
index 54b0fd879..000000000
--- a/src/proof/er/er_proof.cpp
+++ /dev/null
@@ -1,399 +0,0 @@
-/********************* */
-/*! \file er_proof.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir, Andres Noetzli, Mathias Preiner
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief ER Proof Format
- **
- ** Declares C++ types that represent an ER/TRACECHECK proof.
- ** Defines serialization for these types.
- **
- ** You can find details about the way ER is encoded in the TRACECHECK
- ** format at these locations:
- ** https://github.com/benjaminkiesl/drat2er
- ** http://www.cs.utexas.edu/users/marijn/publications/ijcar18.pdf
- **/
-
-#include "proof/er/er_proof.h"
-
-#include <unistd.h>
-#include <algorithm>
-#include <fstream>
-#include <iostream>
-#include <iterator>
-#include <sstream>
-#include <unordered_set>
-
-#include "base/check.h"
-#include "base/map_util.h"
-#include "proof/dimacs.h"
-#include "proof/lfsc_proof_printer.h"
-#include "proof/proof_manager.h"
-
-#if CVC4_USE_DRAT2ER
-#include "drat2er.h"
-#include "drat2er_options.h"
-#endif
-
-namespace CVC4 {
-namespace proof {
-namespace er {
-
-TraceCheckProof TraceCheckProof::fromText(std::istream& in)
-{
- TraceCheckProof pf;
- TraceCheckIdx idx = 0;
- int64_t token = 0;
-
- // For each line of the proof, start with the idx
- // If there is no idx, then you're done!
- in >> idx;
- for (; !in.eof(); in >> idx)
- {
- Assert(in.good());
-
- // Then parse the clause (it's 0-terminated)
- std::vector<prop::SatLiteral> clause;
- in >> token;
- for (; token != 0; in >> token)
- {
- clause.emplace_back(std::abs(token) - 1, token < 0);
- }
-
- // Then parse the chain of literals (it's also 0-terminated)
- std::vector<TraceCheckIdx> chain;
- in >> token;
- for (; token != 0; in >> token)
- {
- Assert(token > 0);
- chain.push_back(token);
- }
-
- // Add the line to the proof
- pf.d_lines.emplace_back(idx, std::move(clause), std::move(chain));
- }
- return pf;
-}
-
-ErProof ErProof::fromBinaryDratProof(
- const std::unordered_map<ClauseId, prop::SatClause>& clauses,
- const std::vector<ClauseId>& usedIds,
- const std::string& dratBinary,
- TimerStat& toolTimer)
-{
- std::string formulaFilename("cvc4-dimacs-XXXXXX");
- std::string dratFilename("cvc4-drat-XXXXXX");
- std::string tracecheckFilename("cvc4-tracecheck-er-XXXXXX");
-
- // Write the formula
- std::unique_ptr<std::fstream> formStream = openTmpFile(&formulaFilename);
- printDimacs(*formStream, clauses, usedIds);
- formStream->close();
-
- // Write the (binary) DRAT proof
- std::unique_ptr<std::fstream> dratStream = openTmpFile(&dratFilename);
- (*dratStream) << dratBinary;
- dratStream->close();
-
- std::unique_ptr<std::fstream> tracecheckStream =
- openTmpFile(&tracecheckFilename);
-
- // Invoke drat2er
- {
- CodeTimer blockTimer{toolTimer};
-#if CVC4_USE_DRAT2ER
- drat2er::TransformDRATToExtendedResolution(formulaFilename,
- dratFilename,
- tracecheckFilename,
- false,
- drat2er::options::QUIET,
- false);
-#else
- Unimplemented()
- << "ER proof production requires drat2er.\n"
- << "Run contrib/get-drat2er, reconfigure with --drat2er, and rebuild";
-#endif
- }
-
- // Parse the resulting TRACECHECK proof into an ER proof.
- TraceCheckProof pf = TraceCheckProof::fromText(*tracecheckStream);
- ErProof proof(clauses, usedIds, std::move(pf));
- tracecheckStream->close();
-
- remove(formulaFilename.c_str());
- remove(dratFilename.c_str());
- remove(tracecheckFilename.c_str());
-
- return proof;
-}
-
-ErProof::ErProof(const std::unordered_map<ClauseId, prop::SatClause>& clauses,
- const std::vector<ClauseId>& usedIds,
- TraceCheckProof&& tracecheck)
- : d_inputClauseIds(), d_definitions(), d_tracecheck(tracecheck)
-{
- // Step zero, save input clause Ids for future printing
- d_inputClauseIds = usedIds;
-
- // Make a list of (idx, clause pairs), the used ones.
- std::vector<std::pair<ClauseId, prop::SatClause>> usedClauses;
- std::transform(
- usedIds.begin(),
- usedIds.end(),
- std::back_inserter(usedClauses),
- [&](const ClauseId& i) { return make_pair(i, clauses.at(i)); });
-
- // Step one, verify the formula starts the proof
- if (Configuration::isAssertionBuild())
- {
- for (size_t i = 0, n = usedClauses.size(); i < n; ++i)
- {
- Assert(d_tracecheck.d_lines[i].d_idx = i + 1);
- Assert(d_tracecheck.d_lines[i].d_chain.size() == 0);
- std::unordered_set<prop::SatLiteral, prop::SatLiteralHashFunction>
- traceCheckClause{d_tracecheck.d_lines[i].d_clause.begin(),
- d_tracecheck.d_lines[i].d_clause.end()};
- std::unordered_set<prop::SatLiteral, prop::SatLiteralHashFunction>
- originalClause{usedClauses[i].second.begin(),
- usedClauses[i].second.end()};
- Assert(traceCheckClause == originalClause);
- }
- }
-
- // Step two, identify definitions. They correspond to lines that follow the
- // input lines, are in bounds, and have no justifying chain.
- for (size_t i = usedClauses.size(), n = d_tracecheck.d_lines.size();
- i < n && d_tracecheck.d_lines[i].d_chain.size() == 0;)
- {
- prop::SatClause c = d_tracecheck.d_lines[i].d_clause;
- Assert(c.size() > 0);
- Assert(!c[0].isNegated());
-
- // Get the new variable of the definition -- the first variable of the
- // first clause
- prop::SatVariable newVar = c[0].getSatVariable();
-
- // The rest of the literals in the clause of the 'other literals' of the def
- std::vector<prop::SatLiteral> otherLiterals{++c.begin(), c.end()};
-
- size_t nLinesForThisDef = 2 + otherLiterals.size();
- // Look at the negation of the second literal in the second clause to get
- // the old literal
- AlwaysAssert(d_tracecheck.d_lines.size() > i + 1)
- << "Malformed definition in TRACECHECK proof from drat2er";
- d_definitions.emplace_back(newVar,
- ~d_tracecheck.d_lines[i + 1].d_clause[1],
- std::move(otherLiterals));
-
- // Advance over the lines for this definition
- i += nLinesForThisDef;
- }
-}
-
-void ErProof::outputAsLfsc(std::ostream& os) const
-{
- // How many parens to close?
- size_t parenCount = 0;
- std::unordered_set<prop::SatVariable> newVariables;
-
- // Print Definitions
- for (const ErDefinition& def : d_definitions)
- {
- os << "\n (decl_definition ("
- << (def.d_oldLiteral.isNegated() ? "neg " : "pos ")
- << ProofManager::getVarName(def.d_oldLiteral.getSatVariable(), "bb")
- << ") ";
- LFSCProofPrinter::printSatClause(def.d_otherLiterals, os, "bb");
- os << " (\\ er.v" << def.d_newVariable << " (\\ er.def"
- << def.d_newVariable;
- newVariables.insert(def.d_newVariable);
- }
- parenCount += 3 * d_definitions.size();
-
- // Clausify Definitions
- TraceCheckIdx firstDefClause = d_inputClauseIds.size() + 1;
- for (const ErDefinition& def : d_definitions)
- {
- os << "\n (clausify_definition _ _ _ "
- << "er.def" << def.d_newVariable << " _ (\\ er.c" << firstDefClause
- << " (\\ er.c" << (firstDefClause + 1) << " (\\ er.cnf"
- << def.d_newVariable;
-
- firstDefClause += 2 + def.d_otherLiterals.size();
- }
- parenCount += 4 * d_definitions.size();
-
- // Unroll proofs of CNF to proofs of clauses
- firstDefClause = d_inputClauseIds.size() + 1;
- for (const ErDefinition& def : d_definitions)
- {
- for (size_t i = 0, n = def.d_otherLiterals.size(); i < n; ++i)
- {
- // Compute the name of the CNF proof we're unrolling in this step
- std::ostringstream previousCnfProof;
- previousCnfProof << "er.cnf" << def.d_newVariable;
- if (i != 0)
- {
- // For all but the first unrolling, the previous CNF has an unrolling
- // number attached
- previousCnfProof << ".u" << i;
- }
-
- // Prove the first clause in the CNF
- os << "\n (@ ";
- os << "er.c" << (firstDefClause + 2 + i);
- os << " (common_tail_cnf_prove_head _ _ _ " << previousCnfProof.str()
- << ")";
-
- // Prove the rest of the CNF
- os << "\n (@ ";
- os << "er.cnf" << def.d_newVariable << ".u" << (i + 1);
- os << " (common_tail_cnf_prove_tail _ _ _ " << previousCnfProof.str()
- << ")";
- }
- parenCount += 2 * def.d_otherLiterals.size();
-
- firstDefClause += 2 + def.d_otherLiterals.size();
- }
-
- // NB: At this point `firstDefClause` points to the first clause resulting
- // from a resolution chain
-
- // Now, elaborate each resolution chain
- for (size_t cId = firstDefClause, nLines = d_tracecheck.d_lines.size();
- cId <= nLines;
- ++cId)
- {
- const std::vector<TraceCheckIdx>& chain =
- d_tracecheck.d_lines[cId - 1].d_chain;
- const std::vector<prop::SatLiteral> pivots = computePivotsForChain(chain);
- Assert(chain.size() > 0);
- Assert(chain.size() == pivots.size() + 1);
-
- os << "\n (satlem_simplify _ _ _ ";
- parenCount += 1;
-
- // Print resolution openings (reverse order)
- for (int64_t i = pivots.size() - 1; i >= 0; --i)
- {
- prop::SatLiteral pivot = pivots[i];
- os << "(" << (pivot.isNegated() ? 'Q' : 'R') << " _ _ ";
- }
-
- // Print resolution start
- writeIdForClauseProof(os, chain[0]);
- os << " ";
-
- // Print resolution closings (forward order)
- for (size_t i = 0, n = pivots.size(); i < n; ++i)
- {
- prop::SatVariable pivotVar = pivots[i].getSatVariable();
- TraceCheckIdx clauseId = chain[i + 1];
- writeIdForClauseProof(os, clauseId);
- os << " ";
- if (ContainsKey(newVariables, pivotVar))
- {
- // This is a defined variable
- os << "er.v" << pivotVar;
- }
- else
- {
- os << ProofManager::getVarName(pivotVar, "bb");
- }
- os << ") ";
- }
- os << "(\\ er.c" << cId;
- parenCount += 1;
- }
-
- // Write proof of bottom
- Assert(d_tracecheck.d_lines.back().d_clause.size() == 0)
- << "The TRACECHECK proof from drat2er did not prove bottom.";
- os << "\n er.c" << d_tracecheck.d_lines.back().d_idx
- << " ; (holds cln)\n";
-
- // Finally, close the parentheses!
- std::fill_n(std::ostream_iterator<char>(os), parenCount, ')');
-}
-
-namespace {
-/**
- * Resolves two clauses
- *
- * @param dest one of the inputs, and the output too. **This is an input and
- * output**
- * @param src the other input
- *
- * @return the unique literal that was resolved on, with the polarization that
- * it originally had in `dest`.
- *
- * For example, if dest = (1 3 -4 5) and src = (1 -3 5), then 3 is returned and
- * after the call dest = (1 -4 5).
- */
-prop::SatLiteral resolveModify(
- std::unordered_set<prop::SatLiteral, prop::SatLiteralHashFunction>& dest,
- const prop::SatClause& src)
-{
- CVC4_UNUSED bool foundPivot = false;
- prop::SatLiteral pivot(0, false);
-
- for (prop::SatLiteral lit : src)
- {
- auto negationLocation = dest.find(~lit);
- if (negationLocation != dest.end())
- {
-#ifdef CVC4_ASSERTIONS
- Assert(!foundPivot);
- foundPivot = true;
-#endif
- dest.erase(negationLocation);
- pivot = ~lit;
- }
- dest.insert(lit);
- }
-
- Assert(foundPivot);
- return pivot;
-}
-} // namespace
-
-std::vector<prop::SatLiteral> ErProof::computePivotsForChain(
- const std::vector<TraceCheckIdx>& chain) const
-{
- std::vector<prop::SatLiteral> pivots;
-
- const prop::SatClause& first = d_tracecheck.d_lines[chain[0] - 1].d_clause;
- std::unordered_set<prop::SatLiteral, prop::SatLiteralHashFunction>
- runningClause{first.begin(), first.end()};
-
- for (auto idx = ++chain.cbegin(), end = chain.cend(); idx != end; ++idx)
- {
- pivots.push_back(
- resolveModify(runningClause, d_tracecheck.d_lines[*idx - 1].d_clause));
- }
- return pivots;
-}
-
-void ErProof::writeIdForClauseProof(std::ostream& o, TraceCheckIdx i) const
-{
- if (i <= d_inputClauseIds.size())
- {
- // This clause is an input clause! Ask the ProofManager for its name
- o << ProofManager::getInputClauseName(d_inputClauseIds[i - 1], "bb");
- }
- else
- {
- // This clause was introduced by a definition or resolution chain
- o << "er.c" << i;
- }
-}
-
-} // namespace er
-} // namespace proof
-} // namespace CVC4
diff --git a/src/proof/er/er_proof.h b/src/proof/er/er_proof.h
deleted file mode 100644
index 6f7239ef2..000000000
--- a/src/proof/er/er_proof.h
+++ /dev/null
@@ -1,218 +0,0 @@
-/********************* */
-/*! \file er_proof.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir, Mathias Preiner
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief ER Proof Format
- **
- ** Declares C++ types that represent an ER/TRACECHECK proof.
- ** Defines serialization for these types.
- **
- ** You can find details about the way ER is encoded in the TRACECHECK
- ** format at these locations:
- ** https://github.com/benjaminkiesl/drat2er
- ** http://www.cs.utexas.edu/users/marijn/publications/ijcar18.pdf
- **
- **/
-
-#include "cvc4_private.h"
-
-#ifndef CVC4__PROOF__ER__ER_PROOF_H
-#define CVC4__PROOF__ER__ER_PROOF_H
-
-#include <memory>
-#include <unordered_map>
-#include <vector>
-
-#include "proof/clause_id.h"
-#include "prop/sat_solver_types.h"
-#include "util/statistics_registry.h"
-
-namespace CVC4 {
-namespace proof {
-namespace er {
-
-/**
- * A definition of the form:
- * newVar <-> p v (~x_1 ^ ~x_2 ^ ... ^ ~x_n)
- */
-struct ErDefinition
-{
- ErDefinition(prop::SatVariable newVariable,
- prop::SatLiteral oldLiteral,
- std::vector<prop::SatLiteral>&& otherLiterals)
- : d_newVariable(newVariable),
- d_oldLiteral(oldLiteral),
- d_otherLiterals(otherLiterals)
- {
- }
-
- // newVar
- prop::SatVariable d_newVariable;
- // p
- prop::SatLiteral d_oldLiteral;
- // A list of the x_i's
- std::vector<prop::SatLiteral> d_otherLiterals;
-};
-
-// For representing a clause's index within a TRACECHECK proof.
-using TraceCheckIdx = size_t;
-
-/**
- * A single line in a TRACECHECK proof.
- *
- * Consists of the index of a new clause, the literals of that clause, and the
- * indices for preceding clauses which can be combined in a resolution chain to
- * produce this new clause.
- */
-struct TraceCheckLine
-{
- TraceCheckLine(TraceCheckIdx idx,
- std::vector<prop::SatLiteral>&& clause,
- std::vector<TraceCheckIdx>&& chain)
- : d_idx(idx), d_clause(clause), d_chain(chain)
- {
- }
-
- // The index of the new clause
- TraceCheckIdx d_idx;
- // The new clause
- std::vector<prop::SatLiteral> d_clause;
- /**
- * Indices of clauses which must be resolved to produce this new clause.
- * While the TRACECHECK format does not specify the order, we require them to
- * be in resolution-order.
- */
- std::vector<TraceCheckIdx> d_chain;
-};
-
-/**
- * A TRACECHECK proof -- just a list of lines
- */
-struct TraceCheckProof
-{
- static TraceCheckProof fromText(std::istream& in);
- TraceCheckProof() : d_lines() {}
-
- // The lines of this proof.
- std::vector<TraceCheckLine> d_lines;
-};
-
-/**
- * An extended resolution proof.
- * It supports resolution, along with extensions of the form
- *
- * newVar <-> p v (~x_1 ^ ~x_2 ^ ... ^ ~x_n)
- */
-class ErProof
-{
- public:
- /**
- * Construct an ER proof from a DRAT proof, using drat2er
- *
- * @param clauses A store of clauses that might be in our formula
- * @param usedIds the ids of clauses that are actually in our formula
- * @param dratBinary The DRAT proof from the SAT solver, as a binary stream
- *
- * @return the Er proof and a timer of the execution of drat2er
- */
- static ErProof fromBinaryDratProof(
- const std::unordered_map<ClauseId, prop::SatClause>& clauses,
- const std::vector<ClauseId>& usedIds,
- const std::string& dratBinary,
- TimerStat& toolTimer
- );
-
- /**
- * Construct an ER proof from a TRACECHECK ER proof
- *
- * This basically just identifies groups of lines which correspond to
- * definitions, and extracts them.
- *
- * @param clauses A store of clauses that might be in our formula
- * @param usedIds the ids of clauses that are actually in our formula
- * @param tracecheck The TRACECHECK proof, as a stream.
- */
- ErProof(const std::unordered_map<ClauseId, prop::SatClause>& clauses,
- const std::vector<ClauseId>& usedIds,
- TraceCheckProof&& tracecheck);
-
- /**
- * Write the ER proof as an LFSC value of type (holds cln).
- * The format is from the LFSC signature er.plf
- *
- * Reads the current `ProofManager` to determine what the variables should be
- * named.
- *
- * @param os the stream to write to
- */
- void outputAsLfsc(std::ostream& os) const;
-
- const std::vector<ClauseId>& getInputClauseIds() const
- {
- return d_inputClauseIds;
- }
-
- const std::vector<ErDefinition>& getDefinitions() const
- {
- return d_definitions;
- }
-
- const TraceCheckProof& getTraceCheckProof() const { return d_tracecheck; }
-
- private:
- /**
- * Creates an empty ErProof.
- */
- ErProof() : d_inputClauseIds(), d_definitions(), d_tracecheck() {}
-
- /**
- * Computes the pivots on the basis of which an in-order resolution chain is
- * resolved.
- *
- * c0 c1
- * \ / Clauses c_i being resolved in a chain around
- * v1 c2 pivots v_i.
- * \ /
- * v2 c3
- * \ /
- * v3 c4
- * \ /
- * v4
- *
- *
- * @param chain the chain, of N clause indices
- *
- * @return a list of N - 1 variables, the list ( v_i ) from i = 1 to N - 1
- */
- std::vector<prop::SatLiteral> computePivotsForChain(
- const std::vector<TraceCheckIdx>& chain) const;
-
- /**
- * Write the LFSC identifier for the proof of a clause
- *
- * @param o where to write to
- * @param i the TRACECHECK index for the clause whose proof identifier to
- * print
- */
- void writeIdForClauseProof(std::ostream& o, TraceCheckIdx i) const;
-
- // A list of the Ids for the input clauses, in order.
- std::vector<ClauseId> d_inputClauseIds;
- // A list of new variable definitions, in order.
- std::vector<ErDefinition> d_definitions;
- // The underlying TRACECHECK proof.
- TraceCheckProof d_tracecheck;
-};
-
-} // namespace er
-} // namespace proof
-} // namespace CVC4
-
-#endif // CVC4__PROOF__ER__ER_PROOF_H
diff --git a/src/proof/lemma_proof.cpp b/src/proof/lemma_proof.cpp
deleted file mode 100644
index bdebb6cfc..000000000
--- a/src/proof/lemma_proof.cpp
+++ /dev/null
@@ -1,254 +0,0 @@
-/********************* */
-/*! \file lemma_proof.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Guy Katz, Alex Ozdemir, Mathias Preiner
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** A class for recoding the steps required in order to prove a theory lemma.
-
-**/
-
-#include "proof/lemma_proof.h"
-#include "theory/rewriter.h"
-
-namespace CVC4 {
-
-LemmaProofRecipe::ProofStep::ProofStep(theory::TheoryId theory, Node literalToProve) :
- d_theory(theory), d_literalToProve(literalToProve) {
-}
-
-theory::TheoryId LemmaProofRecipe::ProofStep::getTheory() const {
- return d_theory;
-}
-
-Node LemmaProofRecipe::ProofStep::getLiteral() const {
- return d_literalToProve;
-}
-
-void LemmaProofRecipe::ProofStep::addAssertion(const Node& assertion) {
- d_assertions.insert(assertion);
-}
-
-std::set<Node> LemmaProofRecipe::ProofStep::getAssertions() const {
- return d_assertions;
-}
-
-void LemmaProofRecipe::addStep(ProofStep& proofStep) {
- d_proofSteps.push_back(proofStep);
-}
-
-std::set<Node> LemmaProofRecipe::getMissingAssertionsForStep(unsigned index) const {
- Assert(index < d_proofSteps.size());
-
- std::set<Node> existingAssertions = getBaseAssertions();
-
- // The literals for all the steps "before" (i.e. behind) the step indicated
- // by the index are considered "existing"
- size_t revIndex = d_proofSteps.size() - 1 - index;
- for (size_t i = d_proofSteps.size() - 1; i != revIndex; --i)
- {
- existingAssertions.insert(d_proofSteps[i].getLiteral().negate());
- }
-
- std::set<Node> neededAssertions = d_proofSteps[revIndex].getAssertions();
-
- std::set<Node> result;
- std::set_difference(neededAssertions.begin(), neededAssertions.end(),
- existingAssertions.begin(), existingAssertions.end(),
- std::inserter(result, result.begin()));
- return result;
-}
-
-void LemmaProofRecipe::dump(const char *tag) const {
-
- if (d_proofSteps.size() == 1) {
- Debug(tag) << std::endl << "[Simple lemma]" << std::endl << std::endl;
- }
-
- if (d_originalLemma != Node()) {
- Debug(tag) << std::endl << "Original lemma: " << d_originalLemma << std::endl << std::endl;
- }
-
- unsigned count = 1;
- Debug(tag) << "Base assertions:" << std::endl;
- for (std::set<Node>::iterator baseIt = d_baseAssertions.begin();
- baseIt != d_baseAssertions.end();
- ++baseIt) {
- Debug(tag) << "\t#" << count << ": " << "\t" << *baseIt << std::endl;
- ++count;
- }
-
- Debug(tag) << std::endl << std::endl << "Proof steps:" << std::endl;
-
- count = 1;
- for (const auto& step : (*this)) {
- Debug(tag) << "\tStep #" << count << ": " << "\t[" << step.getTheory() << "] ";
- if (step.getLiteral() == Node()) {
- Debug(tag) << "Contradiction";
- } else {
- Debug(tag) << step.getLiteral();
- }
-
- Debug(tag) << std::endl;
-
- std::set<Node> missingAssertions = getMissingAssertionsForStep(count - 1);
- for (std::set<Node>::const_iterator it = missingAssertions.begin(); it != missingAssertions.end(); ++it) {
- Debug(tag) << "\t\t\tMissing assertion for step: " << *it << std::endl;
- }
-
- Debug(tag) << std::endl;
- ++count;
- }
-
- if (!d_assertionToExplanation.empty()) {
- Debug(tag) << std::endl << "Rewrites used:" << std::endl;
- count = 1;
- for (std::map<Node, Node>::const_iterator rewrite = d_assertionToExplanation.begin();
- rewrite != d_assertionToExplanation.end();
- ++rewrite) {
- Debug(tag) << "\tRewrite #" << count << ":" << std::endl
- << "\t\t" << rewrite->first
- << std::endl << "\t\trewritten into" << std::endl
- << "\t\t" << rewrite->second
- << std::endl << std::endl;
- ++count;
- }
- }
-}
-
-void LemmaProofRecipe::addBaseAssertion(Node baseAssertion) {
- d_baseAssertions.insert(baseAssertion);
-}
-
-std::set<Node> LemmaProofRecipe::getBaseAssertions() const {
- return d_baseAssertions;
-}
-
-theory::TheoryId LemmaProofRecipe::getTheory() const {
- Assert(d_proofSteps.size() > 0);
- return d_proofSteps.back().getTheory();
-}
-
-void LemmaProofRecipe::addRewriteRule(Node assertion, Node explanation) {
- if (d_assertionToExplanation.find(assertion) != d_assertionToExplanation.end()) {
- Assert(d_assertionToExplanation[assertion] == explanation);
- }
-
- d_assertionToExplanation[assertion] = explanation;
-}
-
-bool LemmaProofRecipe::wasRewritten(Node assertion) const {
- return d_assertionToExplanation.find(assertion) != d_assertionToExplanation.end();
-}
-
-Node LemmaProofRecipe::getExplanation(Node assertion) const {
- Assert(d_assertionToExplanation.find(assertion)
- != d_assertionToExplanation.end());
- return d_assertionToExplanation.find(assertion)->second;
-}
-
-LemmaProofRecipe::RewriteIterator LemmaProofRecipe::rewriteBegin() const {
- return d_assertionToExplanation.begin();
-}
-
-LemmaProofRecipe::RewriteIterator LemmaProofRecipe::rewriteEnd() const {
- return d_assertionToExplanation.end();
-}
-
-LemmaProofRecipe::iterator LemmaProofRecipe::begin() {
- return d_proofSteps.rbegin();
-}
-
-LemmaProofRecipe::iterator LemmaProofRecipe::end() {
- return d_proofSteps.rend();
-}
-
-LemmaProofRecipe::const_iterator LemmaProofRecipe::begin() const {
- return d_proofSteps.crbegin();
-}
-
-LemmaProofRecipe::const_iterator LemmaProofRecipe::end() const {
- return d_proofSteps.crend();
-}
-
-bool LemmaProofRecipe::operator<(const LemmaProofRecipe& other) const {
- return d_baseAssertions < other.d_baseAssertions;
- }
-
-bool LemmaProofRecipe::simpleLemma() const {
- return d_proofSteps.size() == 1;
-}
-
-bool LemmaProofRecipe::compositeLemma() const {
- return !simpleLemma();
-}
-
-const LemmaProofRecipe::ProofStep* LemmaProofRecipe::getStep(unsigned index) const {
- Assert(index < d_proofSteps.size());
-
- size_t revIndex = d_proofSteps.size() - 1 - index;
-
- return &d_proofSteps[revIndex];
-}
-
-LemmaProofRecipe::ProofStep* LemmaProofRecipe::getStep(unsigned index) {
- Assert(index < d_proofSteps.size());
-
- size_t revIndex = d_proofSteps.size() - 1 - index;
-
- return &d_proofSteps[revIndex];
-}
-
-unsigned LemmaProofRecipe::getNumSteps() const {
- return d_proofSteps.size();
-}
-
-void LemmaProofRecipe::setOriginalLemma(Node lemma) {
- d_originalLemma = lemma;
-}
-
-Node LemmaProofRecipe::getOriginalLemma() const {
- return d_originalLemma;
-}
-
-std::ostream& operator<<(std::ostream& out,
- const LemmaProofRecipe::ProofStep& step)
-{
- out << "Proof Step(";
- out << " lit = " << step.getLiteral() << ",";
- out << " assertions = " << step.getAssertions() << ",";
- out << " theory = " << step.getTheory();
- out << " )";
- return out;
-}
-
-std::ostream& operator<<(std::ostream& out, const LemmaProofRecipe& recipe)
-{
- out << "LemmaProofRecipe(";
- out << "\n original lemma = " << recipe.getOriginalLemma();
- out << "\n actual clause = " << recipe.getBaseAssertions();
- out << "\n theory = " << recipe.getTheory();
- out << "\n steps = ";
- for (const auto& step : recipe)
- {
- out << "\n " << step;
- }
- out << "\n rewrites = ";
- for (LemmaProofRecipe::RewriteIterator i = recipe.rewriteBegin(),
- end = recipe.rewriteEnd();
- i != end;
- ++i)
- {
- out << "\n Rewrite(" << i->first << ", explanation = " << i->second
- << ")";
- }
- out << "\n)";
- return out;
-}
-
-} /* namespace CVC4 */
diff --git a/src/proof/lemma_proof.h b/src/proof/lemma_proof.h
deleted file mode 100644
index ffc6655a6..000000000
--- a/src/proof/lemma_proof.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/********************* */
-/*! \file lemma_proof.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Guy Katz, Alex Ozdemir, Mathias Preiner
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** A class for recoding the steps required in order to prove a theory lemma.
-
-**/
-
-#include "cvc4_private.h"
-
-#ifndef CVC4__LEMMA_PROOF_H
-#define CVC4__LEMMA_PROOF_H
-
-#include "expr/expr.h"
-#include "proof/clause_id.h"
-#include "prop/sat_solver_types.h"
-#include "util/proof.h"
-#include "expr/node.h"
-#include <iosfwd>
-
-namespace CVC4 {
-
-class LemmaProofRecipe {
-public:
- class ProofStep {
- public:
- ProofStep(theory::TheoryId theory, Node literalToProve);
- theory::TheoryId getTheory() const;
- Node getLiteral() const;
- void addAssertion(const Node& assertion);
- std::set<Node> getAssertions() const;
-
- private:
- theory::TheoryId d_theory;
- Node d_literalToProve;
- std::set<Node> d_assertions;
- };
-
- //* The lemma assertions and owner */
- void addBaseAssertion(Node baseAssertion);
- std::set<Node> getBaseAssertions() const;
- theory::TheoryId getTheory() const;
-
- //* Rewrite rules */
- using RewriteIterator = std::map<Node, Node>::const_iterator;
- RewriteIterator rewriteBegin() const;
- RewriteIterator rewriteEnd() const;
-
- // Steps iterator
- // The default iterator for a LemmaProofRecipe
- using iterator = std::vector<ProofStep>::reverse_iterator;
- std::vector<ProofStep>::reverse_iterator begin();
- std::vector<ProofStep>::reverse_iterator end();
-
- using const_iterator = std::vector<ProofStep>::const_reverse_iterator;
- std::vector<ProofStep>::const_reverse_iterator begin() const;
- std::vector<ProofStep>::const_reverse_iterator end() const;
-
- using difference_type = ptrdiff_t;
- using size_type = size_t;
- using value_type = ProofStep;
- using pointer = ProofStep *;
- using const_pointer = const ProofStep *;
- using reference = ProofStep &;
- using const_reference = const ProofStep &;
-
- void addRewriteRule(Node assertion, Node explanation);
- bool wasRewritten(Node assertion) const;
- Node getExplanation(Node assertion) const;
-
- //* Original lemma */
- void setOriginalLemma(Node lemma);
- Node getOriginalLemma() const;
-
- //* Proof Steps */
- void addStep(ProofStep& proofStep);
- const ProofStep* getStep(unsigned index) const;
- ProofStep* getStep(unsigned index);
- unsigned getNumSteps() const;
- std::set<Node> getMissingAssertionsForStep(unsigned index) const;
- bool simpleLemma() const;
- bool compositeLemma() const;
-
- void dump(const char *tag) const;
- bool operator<(const LemmaProofRecipe& other) const;
-
-private:
- //* The list of assertions for this lemma */
- std::set<Node> d_baseAssertions;
-
- //* The various steps needed to derive the empty clause */
- // The "first" step is actually at the back.
- std::vector<ProofStep> d_proofSteps;
-
- //* A map from assertions to their rewritten explanations (toAssert --> toExplain) */
- std::map<Node, Node> d_assertionToExplanation;
-
- //* The original lemma, as asserted by the owner theory solver */
- Node d_originalLemma;
-};
-
-std::ostream& operator<<(std::ostream & out, const LemmaProofRecipe::ProofStep & step);
-
-std::ostream& operator<<(std::ostream & out, const LemmaProofRecipe & recipe);
-
-} /* CVC4 namespace */
-
-#endif /* CVC4__LEMMA_PROOF_H */
diff --git a/src/proof/lfsc_proof_printer.cpp b/src/proof/lfsc_proof_printer.cpp
deleted file mode 100644
index 464083841..000000000
--- a/src/proof/lfsc_proof_printer.cpp
+++ /dev/null
@@ -1,217 +0,0 @@
-/********************* */
-/*! \file lfsc_proof_printer.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Andres Noetzli, Alex Ozdemir, Liana Hadarean
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief Prints proofs in the LFSC format
- **
- ** Prints proofs in the LFSC format.
- **/
-
-#include "proof/lfsc_proof_printer.h"
-
-#include <algorithm>
-#include <iostream>
-#include <iterator>
-
-#include "prop/bvminisat/core/Solver.h"
-#include "prop/minisat/core/Solver.h"
-
-namespace CVC4 {
-namespace proof {
-
-template <class Solver>
-std::string LFSCProofPrinter::clauseName(TSatProof<Solver>* satProof,
- ClauseId id)
-{
- std::ostringstream os;
- if (satProof->isInputClause(id))
- {
- os << ProofManager::getInputClauseName(id, satProof->getName());
- }
- else if (satProof->isLemmaClause(id))
- {
- os << ProofManager::getLemmaClauseName(id, satProof->getName());
- }
- else
- {
- os << ProofManager::getLearntClauseName(id, satProof->getName());
- }
- return os.str();
-}
-
-template <class Solver>
-void LFSCProofPrinter::printResolution(TSatProof<Solver>* satProof,
- ClauseId id,
- std::ostream& out,
- std::ostream& paren)
-{
- out << "(satlem_simplify _ _ _";
- paren << ")";
-
- const ResChain<Solver>& res = satProof->getResolutionChain(id);
- const typename ResChain<Solver>::ResSteps& steps = res.getSteps();
-
- for (int i = steps.size() - 1; i >= 0; i--)
- {
- out << " (";
- out << (steps[i].sign ? "R" : "Q") << " _ _";
- }
-
- ClauseId start_id = res.getStart();
- out << " " << clauseName(satProof, start_id);
-
- for (unsigned i = 0; i < steps.size(); i++)
- {
- prop::SatVariable v =
- prop::MinisatSatSolver::toSatVariable(var(steps[i].lit));
- out << " " << clauseName(satProof, steps[i].id) << " "
- << ProofManager::getVarName(v, satProof->getName()) << ")";
- }
-
- if (id == satProof->getEmptyClauseId())
- {
- out << " (\\ empty empty)";
- return;
- }
-
- out << " (\\ " << clauseName(satProof, id) << "\n"; // bind to lemma name
- paren << ")";
-}
-
-template <class Solver>
-void LFSCProofPrinter::printAssumptionsResolution(TSatProof<Solver>* satProof,
- ClauseId id,
- std::ostream& out,
- std::ostream& paren)
-{
- Assert(satProof->isAssumptionConflict(id));
- // print the resolution proving the assumption conflict
- printResolution(satProof, id, out, paren);
- // resolve out assumptions to prove empty clause
- out << "(satlem_simplify _ _ _ ";
- const std::vector<typename Solver::TLit>& confl =
- *(satProof->getAssumptionConflicts().at(id));
-
- Assert(confl.size());
-
- for (unsigned i = 0; i < confl.size(); ++i)
- {
- prop::SatLiteral lit = toSatLiteral<Solver>(confl[i]);
- out << "(";
- out << (lit.isNegated() ? "Q" : "R") << " _ _ ";
- }
-
- out << clauseName(satProof, id) << " ";
- for (int i = confl.size() - 1; i >= 0; --i)
- {
- prop::SatLiteral lit = toSatLiteral<Solver>(confl[i]);
- prop::SatVariable v = lit.getSatVariable();
- out << "unit" << v << " ";
- out << ProofManager::getVarName(v, satProof->getName()) << ")";
- }
- out << "(\\ e e)\n";
- paren << ")";
-}
-
-template <class Solver>
-void LFSCProofPrinter::printResolutions(TSatProof<Solver>* satProof,
- std::ostream& out,
- std::ostream& paren)
-{
- Debug("bv-proof") << "; print resolutions" << std::endl;
- std::set<ClauseId>::iterator it = satProof->getSeenLearnt().begin();
- for (; it != satProof->getSeenLearnt().end(); ++it)
- {
- if (*it != satProof->getEmptyClauseId())
- {
- Debug("bv-proof") << "; print resolution for " << *it << std::endl;
- printResolution(satProof, *it, out, paren);
- }
- }
- Debug("bv-proof") << "; done print resolutions" << std::endl;
-}
-
-template <class Solver>
-void LFSCProofPrinter::printResolutionEmptyClause(TSatProof<Solver>* satProof,
- std::ostream& out,
- std::ostream& paren)
-{
- printResolution(satProof, satProof->getEmptyClauseId(), out, paren);
-}
-
-void LFSCProofPrinter::printSatInputProof(const std::vector<ClauseId>& clauses,
- std::ostream& out,
- const std::string& namingPrefix)
-{
- for (auto i = clauses.begin(), end = clauses.end(); i != end; ++i)
- {
- out << "\n (cnfc_proof _ _ _ "
- << ProofManager::getInputClauseName(*i, namingPrefix) << " ";
- }
- out << "cnfn_proof";
- std::fill_n(std::ostream_iterator<char>(out), clauses.size(), ')');
-}
-
-void LFSCProofPrinter::printCMapProof(const std::vector<ClauseId>& clauses,
- std::ostream& out,
- const std::string& namingPrefix)
-{
- for (size_t i = 0, n = clauses.size(); i < n; ++i)
- {
- out << "\n (CMapc_proof " << (i + 1) << " _ _ _ "
- << ProofManager::getInputClauseName(clauses[i], namingPrefix) << " ";
- }
- out << "CMapn_proof";
- std::fill_n(std::ostream_iterator<char>(out), clauses.size(), ')');
-}
-
-void LFSCProofPrinter::printSatClause(const prop::SatClause& clause,
- std::ostream& out,
- const std::string& namingPrefix)
-{
- for (auto i = clause.cbegin(); i != clause.cend(); ++i)
- {
- out << "(clc " << (i->isNegated() ? "(neg " : "(pos ")
- << ProofManager::getVarName(i->getSatVariable(), namingPrefix) << ") ";
- }
- out << "cln";
- std::fill_n(std::ostream_iterator<char>(out), clause.size(), ')');
-}
-
-// Template specializations
-template void LFSCProofPrinter::printAssumptionsResolution(
- TSatProof<CVC4::Minisat::Solver>* satProof,
- ClauseId id,
- std::ostream& out,
- std::ostream& paren);
-template void LFSCProofPrinter::printResolutions(
- TSatProof<CVC4::Minisat::Solver>* satProof,
- std::ostream& out,
- std::ostream& paren);
-template void LFSCProofPrinter::printResolutionEmptyClause(
- TSatProof<CVC4::Minisat::Solver>* satProof,
- std::ostream& out,
- std::ostream& paren);
-
-template void LFSCProofPrinter::printAssumptionsResolution(
- TSatProof<CVC4::BVMinisat::Solver>* satProof,
- ClauseId id,
- std::ostream& out,
- std::ostream& paren);
-template void LFSCProofPrinter::printResolutions(
- TSatProof<CVC4::BVMinisat::Solver>* satProof,
- std::ostream& out,
- std::ostream& paren);
-template void LFSCProofPrinter::printResolutionEmptyClause(
- TSatProof<CVC4::BVMinisat::Solver>* satProof,
- std::ostream& out,
- std::ostream& paren);
-} // namespace proof
-} // namespace CVC4
diff --git a/src/proof/lfsc_proof_printer.h b/src/proof/lfsc_proof_printer.h
deleted file mode 100644
index 62547676f..000000000
--- a/src/proof/lfsc_proof_printer.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/********************* */
-/*! \file lfsc_proof_printer.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Andres Noetzli, Alex Ozdemir, Mathias Preiner
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief Prints proofs in the LFSC format
- **
- ** Prints proofs in the LFSC format.
- **/
-
-#include "cvc4_private.h"
-
-#ifndef CVC4__PROOF__LFSC_PROOF_PRINTER_H
-#define CVC4__PROOF__LFSC_PROOF_PRINTER_H
-
-#include <iosfwd>
-#include <string>
-#include <vector>
-
-#include "proof/clause_id.h"
-#include "proof/proof_manager.h"
-#include "proof/sat_proof.h"
-#include "proof/sat_proof_implementation.h"
-#include "util/proof.h"
-
-namespace CVC4 {
-namespace proof {
-
-class LFSCProofPrinter
-{
- public:
- /**
- * Prints the resolution proof for an assumption conflict.
- *
- * @param satProof The record of the reasoning done by the SAT solver
- * @param id The clause to print a proof for
- * @param out The stream to print to
- * @param paren A stream for the closing parentheses
- */
- template <class Solver>
- static void printAssumptionsResolution(TSatProof<Solver>* satProof,
- ClauseId id,
- std::ostream& out,
- std::ostream& paren);
-
- /**
- * Prints the resolution proofs for learned clauses that have been used to
- * deduce unsat.
- *
- * @param satProof The record of the reasoning done by the SAT solver
- * @param out The stream to print to
- * @param paren A stream for the closing parentheses
- */
- template <class Solver>
- static void printResolutions(TSatProof<Solver>* satProof,
- std::ostream& out,
- std::ostream& paren);
-
- /**
- * Prints the resolution proof for the empty clause.
- *
- * @param satProof The record of the reasoning done by the SAT solver
- * @param out The stream to print to
- * @param paren A stream for the closing parentheses
- */
- template <class Solver>
- static void printResolutionEmptyClause(TSatProof<Solver>* satProof,
- std::ostream& out,
- std::ostream& paren);
-
- /**
- * The SAT solver is given a list of clauses.
- * Assuming that each clause has alreay been individually proven,
- * defines a proof of the input to the SAT solver.
- *
- * Prints an LFSC value corresponding to the proof, i.e. a value of type
- * (cnf_holds ...)
- *
- * @param clauses The clauses to print a proof of
- * @param out The stream to print to
- * @param namingPrefix The prefix for LFSC names
- */
- static void printSatInputProof(const std::vector<ClauseId>& clauses,
- std::ostream& out,
- const std::string& namingPrefix);
-
- /**
- * The LRAT proof signature uses the concept of a _clause map_ (CMap), which
- * represents an indexed collection of (conjoined) clauses.
- *
- * Specifically, the signatures rely on a proof that a CMap containing the
- * clauses given to the SAT solver hold.
- *
- * Assuming that the individual clauses already have proofs, this function
- * prints a proof of the CMap mapping 1 to the first clause, 2 to the second,
- * and so on.
- *
- * That is, it prints a value of type (CMap_holds ...)
- *
- * @param clauses The clauses to print a proof of
- * @param out The stream to print to
- * @param namingPrefix The prefix for LFSC names
- */
- static void printCMapProof(const std::vector<ClauseId>& clauses,
- std::ostream& out,
- const std::string& namingPrefix);
-
- /**
- * Prints a clause
- *
- * @param clause The clause to print
- * @param out The stream to print to
- * @param namingPrefix The prefix for LFSC names
- */
- static void printSatClause(const prop::SatClause& clause,
- std::ostream& out,
- const std::string& namingPrefix);
-
- private:
-
- /**
- * Maps a clause id to a string identifier used in the LFSC proof.
- *
- * @param satProof The record of the reasoning done by the SAT solver
- * @param id The clause to map to a string
- */
- template <class Solver>
- static std::string clauseName(TSatProof<Solver>* satProof, ClauseId id);
-
- /**
- * Prints the resolution proof for a given clause.
- *
- * @param satProof The record of the reasoning done by the SAT solver
- * @param id The clause to print a proof for
- * @param out The stream to print to
- * @param paren A stream for the closing parentheses
- */
- template <class Solver>
- static void printResolution(TSatProof<Solver>* satProof,
- ClauseId id,
- std::ostream& out,
- std::ostream& paren);
-};
-
-} // namespace proof
-} // namespace CVC4
-
-#endif /* CVC4__PROOF__LFSC_PROOF_PRINTER_H */
diff --git a/src/proof/lrat/lrat_proof.cpp b/src/proof/lrat/lrat_proof.cpp
deleted file mode 100644
index 69ffa623a..000000000
--- a/src/proof/lrat/lrat_proof.cpp
+++ /dev/null
@@ -1,343 +0,0 @@
-/********************* */
-/*! \file lrat_proof.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir, Andres Noetzli, Mathias Preiner
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief DRAT Proof Format
- **
- ** Defines deserialization for DRAT proofs.
- **/
-
-#include "proof/lrat/lrat_proof.h"
-
-#include <algorithm>
-#include <cstdlib>
-#include <fstream>
-#include <iostream>
-#include <memory>
-#include <sstream>
-#include <unordered_map>
-
-#include "base/check.h"
-#include "base/output.h"
-#include "proof/dimacs.h"
-#include "proof/lfsc_proof_printer.h"
-#include "util/utility.h"
-
-#if CVC4_USE_DRAT2ER
-#include "drat2er_options.h"
-#include "drat_trim_interface.h"
-#endif
-
-namespace CVC4 {
-namespace proof {
-namespace lrat {
-
-using prop::SatClause;
-using prop::SatLiteral;
-using prop::SatVariable;
-
-namespace {
-
-// Prints the trace as a space-separated list of (+) ints with a space at the
-// end.
-std::ostream& operator<<(std::ostream& o, const LratUPTrace& trace)
-{
- for (const auto& i : trace)
- {
- o << i << " ";
- }
- return o;
-}
-
-/**
- * Print a list of clause indices to go to while doing UP.
- *
- * i.e. a value of type Trace
- *
- * @param o where to print to
- * @param trace the trace (list of clauses) to print
- */
-void printTrace(std::ostream& o, const LratUPTrace& trace)
-{
- for (ClauseIdx idx : trace)
- {
- o << "(Tracec " << idx << " ";
- }
- o << "Tracen";
- std::fill_n(std::ostream_iterator<char>(o), trace.size(), ')');
-}
-
-/**
- * Print the RAT hints for a clause addition.
- *
- * i.e. prints an LFSC value of type RATHints
- *
- * @param o where to print to
- * @param hints the RAT hints to print
- */
-void printHints(std::ostream& o,
- const std::vector<std::pair<ClauseIdx, LratUPTrace>>& hints)
-{
- for (auto& hint : hints)
- {
- o << "\n (RATHintsc " << hint.first << " ";
- printTrace(o, hint.second);
- o << " ";
- }
- o << "RATHintsn";
- std::fill_n(std::ostream_iterator<char>(o), hints.size(), ')');
-}
-
-/**
- * Print an index list
- *
- * i.e. prints an LFSC value of type CIList
- *
- * @param o where to print to
- * @param indices the list of indices to print
- */
-void printIndices(std::ostream& o, const std::vector<ClauseIdx>& indices)
-{
- Assert(indices.size() > 0);
- // Verify that the indices are sorted!
- for (size_t i = 0, n = indices.size() - 1; i < n; ++i)
- {
- Assert(indices[i] < indices[i + 1]);
- }
-
- for (ClauseIdx idx : indices)
- {
- o << "(CIListc " << idx << " ";
- }
- o << "CIListn";
- std::fill_n(std::ostream_iterator<char>(o), indices.size(), ')');
-}
-
-} // namespace
-
-// Prints the LRAT addition line in textual format
-
-LratProof LratProof::fromDratProof(
- const std::unordered_map<ClauseId, prop::SatClause>& clauses,
- const std::vector<ClauseId> usedIds,
- const std::string& dratBinary,
- TimerStat& toolTimer)
-{
- std::ostringstream cmd;
- std::string formulaFilename("cvc4-dimacs-XXXXXX");
- std::string dratFilename("cvc4-drat-XXXXXX");
- std::string lratFilename("cvc4-lrat-XXXXXX");
-
- std::unique_ptr<std::fstream> formStream = openTmpFile(&formulaFilename);
- printDimacs(*formStream, clauses, usedIds);
- formStream->close();
-
- std::unique_ptr<std::fstream> dratStream = openTmpFile(&dratFilename);
- (*dratStream) << dratBinary;
- dratStream->close();
-
- std::unique_ptr<std::fstream> lratStream = openTmpFile(&lratFilename);
-
- {
- CodeTimer blockTimer{toolTimer};
-#if CVC4_USE_DRAT2ER
- drat2er::drat_trim::CheckAndConvertToLRAT(
- formulaFilename, dratFilename, lratFilename, drat2er::options::QUIET);
-#else
- Unimplemented()
- << "LRAT proof production requires drat2er.\n"
- << "Run contrib/get-drat2er, reconfigure with --drat2er, and rebuild";
-#endif
- }
-
- LratProof lrat(*lratStream);
- remove(formulaFilename.c_str());
- remove(dratFilename.c_str());
- remove(lratFilename.c_str());
- return lrat;
-}
-
-std::istream& operator>>(std::istream& in, SatLiteral& l)
-{
- int64_t i;
- in >> i;
- l = SatLiteral(std::abs(i), i < 0);
- return in;
-}
-
-// This parser is implemented to parse the textual RAT format found in
-// "Efficient Certified RAT Verification", by Cruz-Filipe et. All
-LratProof::LratProof(std::istream& textualProof)
-{
- for (size_t line = 0;; ++line)
- {
- // Read beginning of instruction. EOF indicates that we're done.
- size_t clauseIdx;
- textualProof >> clauseIdx;
- if (textualProof.eof())
- {
- return;
- }
-
- // Read the first word of the instruction. A 'd' indicates deletion.
- std::string first;
- textualProof >> first;
- Trace("pf::lrat") << "First word: " << first << std::endl;
- Assert(textualProof.good());
- if (first == "d")
- {
- std::vector<ClauseIdx> clauses;
- while (true)
- {
- ClauseIdx di;
- textualProof >> di;
- Assert(textualProof.good());
- if (di == 0)
- {
- break;
- }
- clauses.push_back(di);
- }
- if (clauses.size() > 0)
- {
- std::sort(clauses.begin(), clauses.end());
- std::unique_ptr<LratInstruction> instr(
- new LratDeletion(clauseIdx, std::move(clauses)));
- d_instructions.push_back(std::move(instr));
- }
- }
- else
- {
- // We need to reparse the first word as a literal to read the clause
- // we're parsing. It ends with a 0;
- std::istringstream firstS(first);
- SatLiteral lit;
- firstS >> lit;
- Trace("pf::lrat") << "First lit: " << lit << std::endl;
- Assert(!firstS.fail())
- << "Couldn't parse first literal from addition line";
-
- SatClause clause;
- for (; lit != 0; textualProof >> lit)
- {
- Assert(textualProof.good());
- clause.emplace_back(lit.getSatVariable() - 1, lit.isNegated());
- }
-
- // Now we read the AT UP trace. It ends at the first non-(+) #
- std::vector<ClauseIdx> atTrace;
- int64_t i;
- textualProof >> i;
- for (; i > 0; textualProof >> i)
- {
- Assert(textualProof.good());
- atTrace.push_back(i);
- }
-
- // For each RAT hint... (each RAT hint starts with a (-)).
- std::vector<std::pair<ClauseIdx, LratUPTrace>> resolvants;
- for (; i<0; textualProof>> i)
- {
- Assert(textualProof.good());
- // Create an entry in the RAT hint list
- resolvants.emplace_back(-i, std::vector<ClauseIdx>());
-
- // Record the UP trace. It ends with a (-) or 0.
- textualProof >> i;
- for (; i > 0; textualProof >> i)
- {
- resolvants.back().second.push_back(i);
- }
- }
- // Pairs compare based on the first element, so this sorts by the
- // resolution target index
- std::sort(resolvants.begin(), resolvants.end());
- std::unique_ptr<LratInstruction> instr(
- new LratAddition(clauseIdx,
- std::move(clause),
- std::move(atTrace),
- std::move(resolvants)));
- d_instructions.push_back(std::move(instr));
- }
- }
-}
-
-void LratProof::outputAsLfsc(std::ostream& o) const
-{
- std::ostringstream closeParen;
- for (const auto& i : d_instructions)
- {
- i->outputAsLfsc(o, closeParen);
- }
- o << "LRATProofn";
- o << closeParen.str();
-}
-
-void LratAddition::outputAsText(std::ostream& o) const
-{
- o << d_idxOfClause << " ";
- textOut(o, d_clause) << " ";
- o << d_atTrace; // Inludes a space at the end.
- for (const auto& rat : d_resolvants)
- {
- o << "-" << rat.first << " ";
- o << rat.second; // Includes a space at the end.
- }
- o << "0\n";
-}
-
-void LratAddition::outputAsLfsc(std::ostream& o, std::ostream& closeParen) const
-{
- o << "\n (LRATProofa " << d_idxOfClause << " ";
- closeParen << ")";
- LFSCProofPrinter::printSatClause(d_clause, o, "bb");
- o << " ";
- printTrace(o, d_atTrace);
- o << " ";
- printHints(o, d_resolvants);
- o << " ";
-}
-
-void LratDeletion::outputAsText(std::ostream& o) const
-{
- o << d_idxOfClause << " d ";
- for (const auto& idx : d_clauses)
- {
- o << idx << " ";
- }
- o << "0\n";
-}
-
-void LratDeletion::outputAsLfsc(std::ostream& o, std::ostream& closeParen) const
-{
- o << "\n (LRATProofd ";
- closeParen << ")";
- printIndices(o, d_clauses);
- o << " ";
-}
-
-std::ostream& operator<<(std::ostream& o, const LratProof& p)
-{
- for (const auto& instr : p.getInstructions())
- {
- o << *instr;
- }
- return o;
-}
-
-std::ostream& operator<<(std::ostream& o, const LratInstruction& i)
-{
- i.outputAsText(o);
- return o;
-}
-
-} // namespace lrat
-} // namespace proof
-} // namespace CVC4
diff --git a/src/proof/lrat/lrat_proof.h b/src/proof/lrat/lrat_proof.h
deleted file mode 100644
index 1c065a08e..000000000
--- a/src/proof/lrat/lrat_proof.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/********************* */
-/*! \file lrat_proof.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir, Mathias Preiner
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief LRAT Proof Format
- **
- ** Declares C++ types that represent a LRAT proof.
- ** Defines serialization for these types.
- **
- ** Represents an **abstract** LRAT proof.
- ** Does **not** represent an LFSC LRAT proof, or an LRAT proof being used to
- ** prove things about bit-vectors.
- **
- ** Paper on LRAT: https://www.cs.utexas.edu/~marijn/publications/lrat.pdf
- **/
-
-#include "cvc4_private.h"
-
-#ifndef CVC4__PROOF__LRAT__LRAT_PROOF_H
-#define CVC4__PROOF__LRAT__LRAT_PROOF_H
-
-#include <iosfwd>
-#include <string>
-#include <unordered_map>
-#include <utility>
-#include <vector>
-
-#include "proof/clause_id.h"
-// Included because we need operator<< for the SAT types
-#include "prop/sat_solver.h"
-#include "util/statistics_registry.h"
-
-namespace CVC4 {
-namespace proof {
-namespace lrat {
-
-// Refers to clause position within an LRAT proof
-using ClauseIdx = size_t;
-
-// This is conceptually an Either<Addition,Deletion>
-class LratInstruction
-{
- public:
- /**
- * Write this LRAT instruction in textual format
- *
- * @param out the stream to write to
- */
- virtual void outputAsText(std::ostream& out) const = 0;
- /**
- * Write this LRAT instruction as an LFSC value
- *
- * @param out the stream to write to
- * @param closeParen the stream to write any closing parentheses to
- *
- */
- virtual void outputAsLfsc(std::ostream& o,
- std::ostream& closeParen) const = 0;
- virtual ~LratInstruction() = default;
-};
-
-class LratDeletion : public LratInstruction
-{
- public:
- LratDeletion(ClauseIdx idxOfClause, std::vector<ClauseIdx>&& clauses)
- : d_idxOfClause(idxOfClause), d_clauses(clauses)
- {
- // Nothing left to do
- }
-
- LratDeletion() = default;
-
- void outputAsText(std::ostream& out) const override;
- void outputAsLfsc(std::ostream& o, std::ostream& closeParen) const override;
-
- private:
- // This idx doesn't really matter, but it's in the format anyway, so we parse
- // it.
- ClauseIdx d_idxOfClause;
-
- // Clauses to delete
- std::vector<ClauseIdx> d_clauses;
-};
-
-// A sequence of locations that will contain unit clauses during unit
-// propegation
-using LratUPTrace = std::vector<ClauseIdx>;
-
-class LratAddition : public LratInstruction
-{
- public:
- LratAddition(ClauseIdx idxOfClause,
- prop::SatClause&& clause,
- LratUPTrace&& atTrace,
- std::vector<std::pair<ClauseIdx, LratUPTrace>> resolvants)
- : d_idxOfClause(idxOfClause),
- d_clause(clause),
- d_atTrace(atTrace),
- d_resolvants(resolvants)
- {
- // Nothing left to do
- }
-
- void outputAsText(std::ostream& out) const override;
- void outputAsLfsc(std::ostream& o, std::ostream& closeParen) const override;
-
- private:
- // The idx for the new clause
- ClauseIdx d_idxOfClause;
- // The new clause
- prop::SatClause d_clause;
- // UP trace based on the negation of that clause
- LratUPTrace d_atTrace;
-
- // Clauses that can resolve with `clause` on its first variable,
- // together with a UP trace after that resolution.
- // Used for RAT checks.
- std::vector<std::pair<ClauseIdx, LratUPTrace>> d_resolvants;
-};
-
-class LratProof
-{
- public:
- /**
- * @brief Construct an LRAT proof from a DRAT proof, using drat-trim
- *
- * @param clauses A store of clauses that might be in our formula
- * @param usedIds the ids of clauses that are actually in our formula
- * @param dratBinary The DRAT proof from the SAT solver, as a binary stream.
- *
- * @return an LRAT proof an a timer for how long it took to run drat-trim
- */
- static LratProof fromDratProof(
- const std::unordered_map<ClauseId, prop::SatClause>& clauses,
- const std::vector<ClauseId> usedIds,
- const std::string& dratBinary,
- TimerStat& toolTimer);
- /**
- * @brief Construct an LRAT proof from its textual representation
- *
- * @param textualProof the textual encoding of the LRAT proof. See the paper
- * in the file's header comment.
- */
- LratProof(std::istream& textualProof);
-
- /**
- * Construct a LRAT proof from an explicit instruction list
- *
- * @param instructions
- */
- LratProof(std::vector<std::unique_ptr<LratInstruction>>&& instructions)
- : d_instructions(std::move(instructions))
- {
- // Nothing else
- }
-
- const std::vector<std::unique_ptr<LratInstruction>>& getInstructions() const
- {
- return d_instructions;
- }
-
- void outputAsLfsc(std::ostream& o) const;
-
- private:
- // The instructions in the proof. Each is a deletion or addition.
- std::vector<std::unique_ptr<LratInstruction>> d_instructions;
-};
-
-// Prints the LRAT proof in textual format
-std::ostream& operator<<(std::ostream& o, const LratProof& p);
-std::ostream& operator<<(std::ostream& o, const LratInstruction& i);
-
-} // namespace lrat
-} // namespace proof
-} // namespace CVC4
-
-#endif
diff --git a/src/proof/proof.h b/src/proof/proof.h
deleted file mode 100644
index be5af32db..000000000
--- a/src/proof/proof.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/********************* */
-/*! \file proof.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Tim King, Liana Hadarean, Mathias Preiner
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief Proof macros
- **
- ** Proof macros
- **/
-
-#include "cvc4_private.h"
-
-#ifndef CVC4__PROOF__PROOF_H
-#define CVC4__PROOF__PROOF_H
-
-#include "options/smt_options.h"
-
-
-/* Do NOT use #ifdef CVC4_PROOF to check if proofs are enabled.
- * We cannot assume users will use -DCVC4_PROOFS if they have a proofs build.
- * The preferred way of checking that proofs are enabled is to use:
- * #if IS_PROOFS_BUILD
- * ...
- * #endif
- *
- * The macro IS_PROOFS_BUILD is defined in base/configuration_private.h
- *
- * This has the effect of forcing that location to have included this header
- * *before* performing this test. This includes C preprocessing expansion.
- * This forces the inclusion of "cvc4_private.h". This is intentional!
- *
- * See bug 688 for more details:
- * https://github.com/CVC4/CVC4/issues/907
- *
- * If you want to check CVC4_PROOF, you should have a very good reason
- * and should list the exceptions here:
- * - Makefile.am
- * - proof/proofs.h
- * - base/configuration_private.h
- */
-
-#ifdef CVC4_PROOF
-# define PROOF(x) if(CVC4::options::proof() || CVC4::options::unsatCores()) { x; }
-# define NULLPROOF(x) (CVC4::options::proof() || CVC4::options::unsatCores()) ? x : NULL
-# define PROOF_ON() (CVC4::options::proof() || CVC4::options::unsatCores())
-# define THEORY_PROOF(x) if(CVC4::options::proof()) { x; }
-# define THEORY_NULLPROOF(x) CVC4::options::proof() ? x : NULL
-# define THEORY_PROOF_ON() CVC4::options::proof()
-#else /* CVC4_PROOF */
-# define PROOF(x)
-# define NULLPROOF(x) NULL
-# define PROOF_ON() false
-# define THEORY_PROOF(x)
-# define THEORY_NULLPROOF(x) NULL
-# define THEORY_PROOF_ON() false
-#endif /* CVC4_PROOF */
-
-#ifdef CVC4_PROOF_STATS /* CVC4_PROOF_STATS */
-# define PSTATS(x) { x; }
-#else
-# define PSTATS(x)
-#endif /* CVC4_PROOF_STATS */
-
-#endif /* CVC4__PROOF__PROOF_H */
diff --git a/src/proof/proof_manager.cpp b/src/proof/proof_manager.cpp
index 99e3010b4..3e6cc9c69 100644
--- a/src/proof/proof_manager.cpp
+++ b/src/proof/proof_manager.cpp
@@ -21,14 +21,10 @@
#include "context/context.h"
#include "expr/node_visitor.h"
#include "options/bv_options.h"
-#include "options/proof_options.h"
+#include "options/smt_options.h"
#include "proof/clause_id.h"
#include "proof/cnf_proof.h"
-#include "proof/lfsc_proof_printer.h"
-#include "proof/proof_utils.h"
-#include "proof/resolution_bitvector_proof.h"
#include "proof/sat_proof_implementation.h"
-#include "proof/theory_proof.h"
#include "smt/smt_engine.h"
#include "smt/smt_engine_scope.h"
#include "smt/smt_statistics_registry.h"
@@ -39,36 +35,16 @@
#include "theory/uf/theory_uf.h"
#include "theory/valuation.h"
#include "util/hash.h"
-#include "util/proof.h"
namespace CVC4 {
-std::string nodeSetToString(const std::set<Node>& nodes) {
- std::ostringstream os;
- std::set<Node>::const_iterator it;
- for (it = nodes.begin(); it != nodes.end(); ++it) {
- os << *it << " ";
- }
- return os.str();
-}
-
-std::string append(const std::string& str, uint64_t num) {
- std::ostringstream os;
- os << str << num;
- return os.str();
-}
-
-ProofManager::ProofManager(context::Context* context, ProofFormat format)
+ProofManager::ProofManager(context::Context* context)
: d_context(context),
d_satProof(nullptr),
d_cnfProof(nullptr),
- d_theoryProof(nullptr),
- d_inputFormulas(),
d_inputCoreFormulas(context),
d_outputCoreFormulas(context),
d_nextId(0),
- d_fullProof(),
- d_format(format),
d_deps(context)
{
}
@@ -78,19 +54,6 @@ ProofManager::~ProofManager() {}
ProofManager* ProofManager::currentPM() {
return smt::currentProofManager();
}
-const Proof& ProofManager::getProof(SmtEngine* smt)
-{
- if (!currentPM()->d_fullProof)
- {
- Assert(currentPM()->d_format == LFSC);
- currentPM()->d_fullProof.reset(new LFSCProof(
- smt,
- getSatProof(),
- static_cast<LFSCCnfProof*>(getCnfProof()),
- static_cast<LFSCTheoryProofEngine*>(getTheoryProofEngine())));
- }
- return *(currentPM()->d_fullProof);
-}
CoreSatProof* ProofManager::getSatProof()
{
@@ -104,45 +67,8 @@ CnfProof* ProofManager::getCnfProof()
return currentPM()->d_cnfProof.get();
}
-TheoryProofEngine* ProofManager::getTheoryProofEngine()
-{
- Assert(currentPM()->d_theoryProof != NULL);
- return currentPM()->d_theoryProof.get();
-}
-
-UFProof* ProofManager::getUfProof() {
- Assert(options::proof());
- TheoryProof* pf = getTheoryProofEngine()->getTheoryProof(theory::THEORY_UF);
- return (UFProof*)pf;
-}
-
-proof::ResolutionBitVectorProof* ProofManager::getBitVectorProof()
-{
- Assert(options::proof());
- TheoryProof* pf = getTheoryProofEngine()->getTheoryProof(theory::THEORY_BV);
- return static_cast<proof::ResolutionBitVectorProof*>(pf);
-}
-
-ArrayProof* ProofManager::getArrayProof() {
- Assert(options::proof());
- TheoryProof* pf = getTheoryProofEngine()->getTheoryProof(theory::THEORY_ARRAYS);
- return (ArrayProof*)pf;
-}
-
-ArithProof* ProofManager::getArithProof() {
- Assert(options::proof());
- TheoryProof* pf = getTheoryProofEngine()->getTheoryProof(theory::THEORY_ARITH);
- return (ArithProof*)pf;
-}
-
-SkolemizationManager* ProofManager::getSkolemizationManager() {
- Assert(options::proof() || options::unsatCores());
- return &(currentPM()->d_skolemizationManager);
-}
-
void ProofManager::initSatProof(Minisat::Solver* solver)
{
- Assert(d_format == LFSC);
// Destroy old instance before initializing new one to avoid issues with
// registering stats
d_satProof.reset();
@@ -153,150 +79,22 @@ void ProofManager::initCnfProof(prop::CnfStream* cnfStream,
context::Context* ctx)
{
Assert(d_satProof != nullptr);
- Assert(d_format == LFSC);
- d_cnfProof.reset(new LFSCCnfProof(cnfStream, ctx, ""));
+ d_cnfProof.reset(new CnfProof(cnfStream, ctx, ""));
// true and false have to be setup in a special way
Node true_node = NodeManager::currentNM()->mkConst<bool>(true);
Node false_node = NodeManager::currentNM()->mkConst<bool>(false).notNode();
d_cnfProof->pushCurrentAssertion(true_node);
- d_cnfProof->pushCurrentDefinition(true_node);
d_cnfProof->registerConvertedClause(d_satProof->getTrueUnit());
d_cnfProof->popCurrentAssertion();
- d_cnfProof->popCurrentDefinition();
d_cnfProof->pushCurrentAssertion(false_node);
- d_cnfProof->pushCurrentDefinition(false_node);
d_cnfProof->registerConvertedClause(d_satProof->getFalseUnit());
d_cnfProof->popCurrentAssertion();
- d_cnfProof->popCurrentDefinition();
-}
-
-void ProofManager::initTheoryProofEngine()
-{
- Assert(d_theoryProof == NULL);
- Assert(d_format == LFSC);
- d_theoryProof.reset(new LFSCTheoryProofEngine());
-}
-
-std::string ProofManager::getInputClauseName(ClauseId id,
- const std::string& prefix) {
- return append(prefix+".pb", id);
-}
-
-std::string ProofManager::getLemmaClauseName(ClauseId id,
- const std::string& prefix) {
- return append(prefix+".lemc", id);
}
-std::string ProofManager::getLemmaName(ClauseId id, const std::string& prefix) {
- return append(prefix+"lem", id);
-}
-
-std::string ProofManager::getLearntClauseName(ClauseId id,
- const std::string& prefix) {
- return append(prefix+".cl", id);
-}
-std::string ProofManager::getVarName(prop::SatVariable var,
- const std::string& prefix) {
- return append(prefix+".v", var);
-}
-std::string ProofManager::getAtomName(prop::SatVariable var,
- const std::string& prefix) {
- return append(prefix+".a", var);
-}
-std::string ProofManager::getLitName(prop::SatLiteral lit,
- const std::string& prefix) {
- return append(prefix+".l", lit.toInt());
-}
-
-std::string ProofManager::getPreprocessedAssertionName(Node node,
- const std::string& prefix) {
- if (currentPM()->d_assertionFilters.find(node) != currentPM()->d_assertionFilters.end()) {
- return currentPM()->d_assertionFilters[node];
- }
-
- node = node.getKind() == kind::BITVECTOR_EAGER_ATOM ? node[0] : node;
- return append(prefix+".PA", node.getId());
-}
-std::string ProofManager::getAssertionName(Node node,
- const std::string& prefix) {
- return append(prefix+".A", node.getId());
-}
-std::string ProofManager::getInputFormulaName(const Expr& expr) {
- return currentPM()->d_inputFormulaToName[expr];
-}
-
-std::string ProofManager::getAtomName(TNode atom,
- const std::string& prefix) {
- prop::SatLiteral lit = currentPM()->d_cnfProof->getLiteral(atom);
- Assert(!lit.isNegated());
- return getAtomName(lit.getSatVariable(), prefix);
-}
-
-std::string ProofManager::getLitName(TNode lit,
- const std::string& prefix) {
- std::string litName = getLitName(currentPM()->d_cnfProof->getLiteral(lit), prefix);
- if (currentPM()->d_rewriteFilters.find(litName) != currentPM()->d_rewriteFilters.end()) {
- return currentPM()->d_rewriteFilters[litName];
- }
-
- return litName;
-}
-
-bool ProofManager::hasLitName(TNode lit) {
- return currentPM()->d_cnfProof->hasLiteral(lit);
-}
-
-std::string ProofManager::sanitize(TNode node) {
- Assert(node.isVar() || node.isConst());
-
- std::string name = node.toString();
- if (node.isVar()) {
- std::replace(name.begin(), name.end(), ' ', '_');
- } else if (node.isConst()) {
- name.erase(std::remove(name.begin(), name.end(), '('), name.end());
- name.erase(std::remove(name.begin(), name.end(), ')'), name.end());
- name.erase(std::remove(name.begin(), name.end(), ' '), name.end());
- name = "const" + name;
- }
-
- return name;
-}
-
-void ProofManager::traceDeps(TNode n, ExprSet* coreAssertions) {
- Debug("cores") << "trace deps " << n << std::endl;
- if ((n.isConst() && n == NodeManager::currentNM()->mkConst<bool>(true)) ||
- (n.getKind() == kind::NOT && n[0] == NodeManager::currentNM()->mkConst<bool>(false))) {
- return;
- }
- if(d_inputCoreFormulas.find(n.toExpr()) != d_inputCoreFormulas.end()) {
- // originating formula was in core set
- Debug("cores") << " -- IN INPUT CORE LIST!" << std::endl;
- coreAssertions->insert(n.toExpr());
- } else {
- Debug("cores") << " -- NOT IN INPUT CORE LIST!" << std::endl;
- if(d_deps.find(n) == d_deps.end()) {
- if (options::allowEmptyDependencies()) {
- Debug("cores") << " -- Could not track cause assertion. Failing silently." << std::endl;
- return;
- }
- InternalError()
- << "Cannot trace dependence information back to input assertion:\n`"
- << n << "'";
- }
- Assert(d_deps.find(n) != d_deps.end());
- std::vector<Node> deps = (*d_deps.find(n)).second;
- for(std::vector<Node>::const_iterator i = deps.begin(); i != deps.end(); ++i) {
- Debug("cores") << " + tracing deps: " << n << " -deps-on- " << *i << std::endl;
- if( !(*i).isNull() ){
- traceDeps(*i, coreAssertions);
- }
- }
- }
-}
void ProofManager::traceDeps(TNode n, CDExprSet* coreAssertions) {
Debug("cores") << "trace deps " << n << std::endl;
@@ -311,10 +109,6 @@ void ProofManager::traceDeps(TNode n, CDExprSet* coreAssertions) {
} else {
Debug("cores") << " -- NOT IN INPUT CORE LIST!" << std::endl;
if(d_deps.find(n) == d_deps.end()) {
- if (options::allowEmptyDependencies()) {
- Debug("cores") << " -- Could not track cause assertion. Failing silently." << std::endl;
- return;
- }
InternalError()
<< "Cannot trace dependence information back to input assertion:\n`"
<< n << "'";
@@ -345,16 +139,11 @@ void ProofManager::traceUnsatCore() {
IdToSatClause::const_iterator it = used_inputs.begin();
for(; it != used_inputs.end(); ++it) {
Node node = d_cnfProof->getAssertionForClause(it->first);
- ProofRule rule = d_cnfProof->getProofRule(node);
- Debug("cores") << "core input assertion " << node << std::endl;
- Debug("cores") << "with proof rule " << rule << std::endl;
- if (rule == RULE_TSEITIN ||
- rule == RULE_GIVEN) {
- // trace dependences back to actual assertions
- // (this adds them to the unsat core)
- traceDeps(node, &d_outputCoreFormulas);
- }
+ Debug("cores") << "core input assertion " << node << "\n";
+ // trace dependences back to actual assertions
+ // (this adds them to the unsat core)
+ traceDeps(node, &d_outputCoreFormulas);
}
}
@@ -373,150 +162,32 @@ std::vector<Expr> ProofManager::extractUnsatCore() {
return result;
}
-void ProofManager::constructSatProof() {
- if (!d_satProof->proofConstructed()) {
+void ProofManager::constructSatProof()
+{
+ if (!d_satProof->proofConstructed())
+ {
d_satProof->constructProof();
}
}
-void ProofManager::getLemmasInUnsatCore(theory::TheoryId theory, std::vector<Node> &lemmas) {
- Assert(PROOF_ON()) << "Cannot compute unsat core when proofs are off";
- Assert(unsatCoreAvailable())
- << "Cannot get unsat core at this time. Mabye the input is SAT?";
-
- constructSatProof();
-
- IdToSatClause used_lemmas;
- IdToSatClause used_inputs;
- d_satProof->collectClausesUsed(used_inputs, used_lemmas);
-
- IdToSatClause::const_iterator it;
- std::set<Node> seen;
-
- Debug("pf::lemmasUnsatCore") << "Dumping all lemmas in unsat core" << std::endl;
- for (it = used_lemmas.begin(); it != used_lemmas.end(); ++it) {
- std::set<Node> lemma = satClauseToNodeSet(it->second);
- Debug("pf::lemmasUnsatCore") << nodeSetToString(lemma);
-
- // TODO: we should be able to drop the "haveProofRecipe" check.
- // however, there are some rewrite issues with the arith solver, resulting
- // in non-registered recipes. For now we assume no one is requesting arith lemmas.
- LemmaProofRecipe recipe;
- if (!getCnfProof()->haveProofRecipe(lemma)) {
- Debug("pf::lemmasUnsatCore") << "\t[no recipe]" << std::endl;
- continue;
- }
-
- recipe = getCnfProof()->getProofRecipe(lemma);
- Debug("pf::lemmasUnsatCore") << "\t[owner = " << recipe.getTheory()
- << ", original = " << recipe.getOriginalLemma() << "]" << std::endl;
- if (recipe.simpleLemma() && recipe.getTheory() == theory && seen.find(recipe.getOriginalLemma()) == seen.end()) {
- lemmas.push_back(recipe.getOriginalLemma());
- seen.insert(recipe.getOriginalLemma());
- }
- }
-}
-
-std::set<Node> ProofManager::satClauseToNodeSet(prop::SatClause* clause) {
- std::set<Node> result;
- for (unsigned i = 0; i < clause->size(); ++i) {
- prop::SatLiteral lit = (*clause)[i];
- Node node = getCnfProof()->getAtom(lit.getSatVariable());
- Expr atom = node.toExpr();
- if (atom != utils::mkTrue())
- result.insert(lit.isNegated() ? node.notNode() : node);
- }
-
- return result;
-}
-
-Node ProofManager::getWeakestImplicantInUnsatCore(Node lemma) {
- Assert(PROOF_ON()) << "Cannot compute unsat core when proofs are off";
+void ProofManager::getLemmasInUnsatCore(std::vector<Node>& lemmas)
+{
+ Assert(options::unsatCores())
+ << "Cannot compute unsat core when proofs are off";
Assert(unsatCoreAvailable())
<< "Cannot get unsat core at this time. Mabye the input is SAT?";
-
- // If we're doing aggressive minimization, work on all lemmas, not just conjunctions.
- if (!options::aggressiveCoreMin() && (lemma.getKind() != kind::AND))
- return lemma;
-
constructSatProof();
-
- NodeBuilder<> builder(kind::AND);
-
IdToSatClause used_lemmas;
IdToSatClause used_inputs;
d_satProof->collectClausesUsed(used_inputs, used_lemmas);
-
+ Debug("pf::lemmasUnsatCore") << "Retrieving all lemmas in unsat core\n";
IdToSatClause::const_iterator it;
- std::set<Node>::iterator lemmaIt;
-
- if (!options::aggressiveCoreMin()) {
- for (it = used_lemmas.begin(); it != used_lemmas.end(); ++it) {
- std::set<Node> currentLemma = satClauseToNodeSet(it->second);
-
- // TODO: we should be able to drop the "haveProofRecipe" check.
- // however, there are some rewrite issues with the arith solver, resulting
- // in non-registered recipes. For now we assume no one is requesting arith lemmas.
- LemmaProofRecipe recipe;
- if (!getCnfProof()->haveProofRecipe(currentLemma))
- continue;
-
- recipe = getCnfProof()->getProofRecipe(currentLemma);
- if (recipe.getOriginalLemma() == lemma) {
- for (lemmaIt = currentLemma.begin(); lemmaIt != currentLemma.end(); ++lemmaIt) {
- builder << *lemmaIt;
-
- // Check that each conjunct appears in the original lemma.
- bool found = false;
- for (unsigned i = 0; i < lemma.getNumChildren(); ++i) {
- if (lemma[i] == *lemmaIt)
- found = true;
- }
-
- if (!found)
- return lemma;
- }
- }
- }
- } else {
- // Aggressive mode
- for (it = used_lemmas.begin(); it != used_lemmas.end(); ++it) {
- std::set<Node> currentLemma = satClauseToNodeSet(it->second);
-
- // TODO: we should be able to drop the "haveProofRecipe" check.
- // however, there are some rewrite issues with the arith solver, resulting
- // in non-registered recipes. For now we assume no one is requesting arith lemmas.
- LemmaProofRecipe recipe;
- if (!getCnfProof()->haveProofRecipe(currentLemma))
- continue;
-
- recipe = getCnfProof()->getProofRecipe(currentLemma);
- if (recipe.getOriginalLemma() == lemma) {
- NodeBuilder<> disjunction(kind::OR);
- for (lemmaIt = currentLemma.begin(); lemmaIt != currentLemma.end(); ++lemmaIt) {
- disjunction << *lemmaIt;
- }
-
- Node conjunct = (disjunction.getNumChildren() == 1) ? disjunction[0] : disjunction;
- builder << conjunct;
- }
- }
+ for (it = used_lemmas.begin(); it != used_lemmas.end(); ++it)
+ {
+ Node lemma = d_cnfProof->getAssertionForClause(it->first);
+ Debug("pf::lemmasUnsatCore") << "Retrieved lemma " << lemma << "\n";
+ lemmas.push_back(lemma);
}
-
- AlwaysAssert(builder.getNumChildren() != 0);
-
- if (builder.getNumChildren() == 1)
- return builder[0];
-
- return builder;
-}
-
-void ProofManager::addAssertion(Expr formula) {
- Debug("proof:pm") << "assert: " << formula << std::endl;
- d_inputFormulas.insert(formula);
- std::ostringstream name;
- name << "A" << d_inputFormulaToName.size();
- d_inputFormulaToName[formula] = name.str();
}
void ProofManager::addCoreAssertion(Expr formula) {
@@ -542,665 +213,4 @@ void ProofManager::addUnsatCore(Expr formula) {
d_outputCoreFormulas.insert(formula);
}
-void ProofManager::addAssertionFilter(const Node& node, const std::string& rewritten) {
- d_assertionFilters[node] = rewritten;
-}
-
-void ProofManager::setLogic(const LogicInfo& logic) {
- d_logic = logic;
-}
-
-LFSCProof::LFSCProof(SmtEngine* smtEngine,
- CoreSatProof* sat,
- LFSCCnfProof* cnf,
- LFSCTheoryProofEngine* theory)
- : d_satProof(sat),
- d_cnfProof(cnf),
- d_theoryProof(theory),
- d_smtEngine(smtEngine)
-{}
-
-void LFSCProof::toStream(std::ostream& out, const ProofLetMap& map) const
-{
- Unreachable();
-}
-
-void collectAtoms(TNode node, std::set<Node>& seen, CnfProof* cnfProof)
-{
- Debug("pf::pm::atoms") << "collectAtoms: Colleting atoms from " << node
- << "\n";
- if (seen.find(node) != seen.end())
- {
- Debug("pf::pm::atoms") << "collectAtoms:\t already seen\n";
- return;
- }
- // if I have a SAT literal for a node, save it, unless this node is a
- // negation, in which case its underlying will be collected downstream
- if (cnfProof->hasLiteral(node) && node.getKind() != kind::NOT)
- {
- Debug("pf::pm::atoms") << "collectAtoms: has SAT literal, save\n";
- seen.insert(node);
- }
- for (unsigned i = 0; i < node.getNumChildren(); ++i)
- {
- Debug("pf::pm::atoms") << push;
- collectAtoms(node[i], seen, cnfProof);
- Debug("pf::pm::atoms") << pop;
- }
-}
-
-void LFSCProof::toStream(std::ostream& out) const
-{
- TimerStat::CodeTimer proofProductionTimer(
- ProofManager::currentPM()->getStats().d_proofProductionTime);
-
- IdToSatClause used_lemmas;
- IdToSatClause used_inputs;
- std::set<Node> atoms;
- NodePairSet rewrites;
- NodeSet used_assertions;
-
- {
- CodeTimer skeletonProofTimer{
- ProofManager::currentPM()->getStats().d_skeletonProofTraceTime};
- Assert(!d_satProof->proofConstructed());
-
- // Here we give our SAT solver a chance to flesh out the resolution proof.
- // It proves bottom from a set of clauses.
- d_satProof->constructProof();
-
- // We ask the SAT solver which clauses are used in that proof.
- // For a resolution proof, these are the leaves of the tree.
- d_satProof->collectClausesUsed(used_inputs, used_lemmas);
-
- IdToSatClause::iterator it2;
- Debug("pf::pm") << std::endl << "Used inputs: " << std::endl;
- for (it2 = used_inputs.begin(); it2 != used_inputs.end(); ++it2)
- {
- Debug("pf::pm") << "\t input = " << *(it2->second) << std::endl;
- }
- Debug("pf::pm") << std::endl;
-
- Debug("pf::pm") << std::endl << "Used lemmas: " << std::endl;
- for (it2 = used_lemmas.begin(); it2 != used_lemmas.end(); ++it2)
- {
- std::vector<Expr> clause_expr;
- for (unsigned i = 0; i < it2->second->size(); ++i)
- {
- prop::SatLiteral lit = (*(it2->second))[i];
- Expr atom = d_cnfProof->getAtom(lit.getSatVariable()).toExpr();
- if (atom.isConst())
- {
- Assert(atom == utils::mkTrue());
- continue;
- }
- Expr expr_lit = lit.isNegated() ? atom.notExpr() : atom;
- clause_expr.push_back(expr_lit);
- }
-
- Debug("pf::pm") << "\t lemma " << it2->first << " = " << *(it2->second)
- << std::endl;
- Debug("pf::pm") << "\t";
- for (unsigned i = 0; i < clause_expr.size(); ++i)
- {
- Debug("pf::pm") << clause_expr[i] << " ";
- }
- Debug("pf::pm") << std::endl;
- }
- Debug("pf::pm") << std::endl;
-
- // collecting assertions that lead to the clauses being asserted
- d_cnfProof->collectAssertionsForClauses(used_inputs, used_assertions);
-
- NodeSet::iterator it3;
- Debug("pf::pm") << std::endl << "Used assertions: " << std::endl;
- for (it3 = used_assertions.begin(); it3 != used_assertions.end(); ++it3)
- Debug("pf::pm") << "\t assertion = " << *it3 << std::endl;
-
- // collects the atoms in the clauses
- d_cnfProof->collectAtomsAndRewritesForLemmas(used_lemmas, atoms, rewrites);
-
- if (!rewrites.empty())
- {
- Debug("pf::pm") << std::endl << "Rewrites used in lemmas: " << std::endl;
- NodePairSet::const_iterator rewriteIt;
- for (rewriteIt = rewrites.begin(); rewriteIt != rewrites.end();
- ++rewriteIt)
- {
- Debug("pf::pm") << "\t" << rewriteIt->first << " --> "
- << rewriteIt->second << std::endl;
- }
- Debug("pf::pm") << std::endl << "Rewrite printing done" << std::endl;
- }
- else
- {
- Debug("pf::pm") << "No rewrites in lemmas found" << std::endl;
- }
-
- // The derived/unrewritten atoms may not have CNF literals required later
- // on. If they don't, add them.
- std::set<Node>::const_iterator it;
- for (it = atoms.begin(); it != atoms.end(); ++it)
- {
- Debug("pf::pm") << "Ensure literal for atom: " << *it << std::endl;
- if (!d_cnfProof->hasLiteral(*it))
- {
- // For arithmetic: these literals are not normalized, causing an error
- // in Arith.
- if (theory::Theory::theoryOf(*it) == theory::THEORY_ARITH)
- {
- d_cnfProof->ensureLiteral(
- *it,
- true); // This disables preregistration with the theory solver.
- }
- else
- {
- d_cnfProof->ensureLiteral(
- *it); // Normal method, with theory solver preregisteration.
- }
- }
- }
-
- // From the clauses, compute the atoms (atomic theory predicates in
- // assertions and lemmas).
- d_cnfProof->collectAtomsForClauses(used_inputs, atoms);
- d_cnfProof->collectAtomsForClauses(used_lemmas, atoms);
-
- // collects the atoms in the assertions
- Debug("pf::pm") << std::endl
- << "LFSCProof::toStream: Colleting atoms from assertions "
- << used_assertions << "\n"
- << push;
- for (TNode used_assertion : used_assertions)
- {
- collectAtoms(used_assertion, atoms, d_cnfProof);
- }
- Debug("pf::pm") << pop;
-
- std::set<Node>::iterator atomIt;
- Debug("pf::pm") << std::endl
- << "Dumping atoms from lemmas, inputs and assertions: "
- << std::endl
- << std::endl;
- for (atomIt = atoms.begin(); atomIt != atoms.end(); ++atomIt)
- {
- Debug("pf::pm") << "\tAtom: " << *atomIt << std::endl;
- }
- }
-
- smt::SmtScope scope(d_smtEngine);
- ProofLetMap globalLetMap;
- std::ostringstream paren;
- {
- CodeTimer declTimer{
- ProofManager::currentPM()->getStats().d_proofDeclarationsTime};
- out << "(check\n";
- paren << ")";
- out << " ;; Declarations\n";
-
- // declare the theory atoms
- Debug("pf::pm") << "LFSCProof::toStream: registering terms:" << std::endl;
- for (std::set<Node>::const_iterator it = atoms.begin(); it != atoms.end(); ++it)
- {
- Debug("pf::pm") << "\tTerm: " << (*it).toExpr() << std::endl;
- d_theoryProof->registerTerm((*it).toExpr());
- }
-
- Debug("pf::pm") << std::endl
- << "Term registration done!" << std::endl
- << std::endl;
-
- Debug("pf::pm") << std::endl
- << "LFSCProof::toStream: starting to print assertions"
- << std::endl;
-
- // print out all the original assertions
- d_theoryProof->registerTermsFromAssertions();
- d_theoryProof->printSortDeclarations(out, paren);
- d_theoryProof->printTermDeclarations(out, paren);
- d_theoryProof->printAssertions(out, paren);
-
- Debug("pf::pm") << std::endl
- << "LFSCProof::toStream: print assertions DONE"
- << std::endl;
-
- out << "(: (holds cln)\n\n";
- paren << ")";
-
- // Have the theory proofs print deferred declarations, e.g. for skolem
- // variables.
- out << " ;; Printing deferred declarations \n\n";
- d_theoryProof->printDeferredDeclarations(out, paren);
-
- out << "\n ;; Printing the global let map";
- d_theoryProof->finalizeBvConflicts(used_lemmas, out);
- ProofManager::getBitVectorProof()->calculateAtomsInBitblastingProof();
- if (options::lfscLetification())
- {
- ProofManager::currentPM()->printGlobalLetMap(
- atoms, globalLetMap, out, paren);
- }
-
- out << " ;; Printing aliasing declarations \n\n";
- d_theoryProof->printAliasingDeclarations(out, paren, globalLetMap);
-
- out << " ;; Rewrites for Lemmas \n";
- d_theoryProof->printLemmaRewrites(rewrites, out, paren);
-
- // print trust that input assertions are their preprocessed form
- printPreprocessedAssertions(used_assertions, out, paren, globalLetMap);
- }
-
- {
- CodeTimer cnfProofTimer{
- ProofManager::currentPM()->getStats().d_cnfProofTime};
- // print mapping between theory atoms and internal SAT variables
- out << ";; Printing mapping from preprocessed assertions into atoms \n";
- d_cnfProof->printAtomMapping(atoms, out, paren, globalLetMap);
-
- Debug("pf::pm") << std::endl
- << "Printing cnf proof for clauses" << std::endl;
-
- IdToSatClause::const_iterator cl_it = used_inputs.begin();
- // print CNF conversion proof for each clause
- for (; cl_it != used_inputs.end(); ++cl_it)
- {
- d_cnfProof->printCnfProofForClause(
- cl_it->first, cl_it->second, out, paren);
- }
- }
-
- {
- CodeTimer theoryLemmaTimer{
- ProofManager::currentPM()->getStats().d_theoryLemmaTime};
- Debug("pf::pm") << std::endl
- << "Printing cnf proof for clauses DONE" << std::endl;
-
- Debug("pf::pm") << "Proof manager: printing theory lemmas" << std::endl;
- d_theoryProof->printTheoryLemmas(used_lemmas, out, paren, globalLetMap);
- Debug("pf::pm") << "Proof manager: printing theory lemmas DONE!"
- << std::endl;
- }
-
- {
- CodeTimer finalProofTimer{
- ProofManager::currentPM()->getStats().d_finalProofTime};
- out << ";; Printing final unsat proof \n";
- if (options::bitblastMode() == options::BitblastMode::EAGER
- && ProofManager::getBitVectorProof())
- {
- ProofManager::getBitVectorProof()->printEmptyClauseProof(out, paren);
- }
- else
- {
- // print actual resolution proof
- proof::LFSCProofPrinter::printResolutions(d_satProof, out, paren);
- proof::LFSCProofPrinter::printResolutionEmptyClause(
- d_satProof, out, paren);
- }
- }
-
- out << paren.str();
- out << "\n;;\n";
-}
-
-void LFSCProof::printPreprocessedAssertions(const NodeSet& assertions,
- std::ostream& os,
- std::ostream& paren,
- ProofLetMap& globalLetMap) const
-{
- os << "\n ;; In the preprocessor we trust \n";
- NodeSet::const_iterator it = assertions.begin();
- NodeSet::const_iterator end = assertions.end();
-
- Debug("pf::pm") << "LFSCProof::printPreprocessedAssertions starting" << std::endl;
-
- if (options::fewerPreprocessingHoles()) {
- // Check for assertions that did not get rewritten, and update the printing filter.
- checkUnrewrittenAssertion(assertions);
-
- // For the remaining assertions, bind them to input assertions.
- for (; it != end; ++it) {
- // Rewrite preprocessing step if it cannot be eliminated
- if (!ProofManager::currentPM()->have_input_assertion((*it).toExpr())) {
- os << "(th_let_pf _ (trust_f (iff ";
-
- Expr inputAssertion;
-
- if (((*it).isConst() && *it == NodeManager::currentNM()->mkConst<bool>(true)) ||
- ((*it).getKind() == kind::NOT && (*it)[0] == NodeManager::currentNM()->mkConst<bool>(false))) {
- inputAssertion = NodeManager::currentNM()->mkConst<bool>(true).toExpr();
- } else {
- // Figure out which input assertion led to this assertion
- ExprSet inputAssertions;
- ProofManager::currentPM()->traceDeps(*it, &inputAssertions);
-
- Debug("pf::pm") << "Original assertions for " << *it << " are: " << std::endl;
-
- ProofManager::assertions_iterator assertionIt;
- for (assertionIt = inputAssertions.begin(); assertionIt != inputAssertions.end(); ++assertionIt) {
- Debug("pf::pm") << "\t" << *assertionIt << std::endl;
- }
-
- if (inputAssertions.size() == 0) {
- Debug("pf::pm") << "LFSCProof::printPreprocessedAssertions: Count NOT find the assertion that caused this PA. Picking an arbitrary one..." << std::endl;
- // For now just use the first assertion...
- inputAssertion = *(ProofManager::currentPM()->begin_assertions());
- } else {
- if (inputAssertions.size() != 1) {
- Debug("pf::pm") << "LFSCProof::printPreprocessedAssertions: Attention: more than one original assertion was found. Picking just one." << std::endl;
- }
- inputAssertion = *inputAssertions.begin();
- }
- }
-
- if (!ProofManager::currentPM()->have_input_assertion(inputAssertion)) {
- // The thing returned by traceDeps does not appear in the input assertions...
- Debug("pf::pm") << "LFSCProof::printPreprocessedAssertions: Count NOT find the assertion that caused this PA. Picking an arbitrary one..." << std::endl;
- // For now just use the first assertion...
- inputAssertion = *(ProofManager::currentPM()->begin_assertions());
- }
-
- Debug("pf::pm") << "Original assertion for " << *it
- << " is: "
- << inputAssertion
- << ", AKA "
- << ProofManager::currentPM()->getInputFormulaName(inputAssertion)
- << std::endl;
-
- ProofManager::currentPM()->getTheoryProofEngine()->printTheoryTerm(inputAssertion, os, globalLetMap);
- os << " ";
- ProofManager::currentPM()->printTrustedTerm(*it, os, globalLetMap);
- os << "))";
- os << "(\\ "<< ProofManager::getPreprocessedAssertionName(*it, "") << "\n";
- paren << "))";
-
- std::ostringstream rewritten;
-
- rewritten << "(or_elim_1 _ _ ";
- rewritten << "(not_not_intro _ ";
- rewritten << ProofManager::currentPM()->getInputFormulaName(inputAssertion);
- rewritten << ") (iff_elim_1 _ _ ";
- rewritten << ProofManager::getPreprocessedAssertionName(*it, "");
- rewritten << "))";
-
- ProofManager::currentPM()->addAssertionFilter(*it, rewritten.str());
- }
- }
- } else {
- for (; it != end; ++it) {
- os << "(th_let_pf _ ";
-
- //TODO
- os << "(trust_f ";
- ProofManager::currentPM()->printTrustedTerm(*it, os, globalLetMap);
- os << ") ";
-
- os << "(\\ "<< ProofManager::getPreprocessedAssertionName(*it, "") << "\n";
- paren << "))";
- }
- }
-
- os << "\n";
-}
-
-void LFSCProof::checkUnrewrittenAssertion(const NodeSet& rewrites) const
-{
- Debug("pf::pm") << "LFSCProof::checkUnrewrittenAssertion starting" << std::endl;
-
- NodeSet::const_iterator rewrite;
- for (rewrite = rewrites.begin(); rewrite != rewrites.end(); ++rewrite) {
- Debug("pf::pm") << "LFSCProof::checkUnrewrittenAssertion: handling " << *rewrite << std::endl;
- if (ProofManager::currentPM()->have_input_assertion((*rewrite).toExpr())) {
- Assert(
- ProofManager::currentPM()->have_input_assertion((*rewrite).toExpr()));
- Debug("pf::pm") << "LFSCProof::checkUnrewrittenAssertion: this assertion was NOT rewritten!" << std::endl
- << "\tAdding filter: "
- << ProofManager::getPreprocessedAssertionName(*rewrite, "")
- << " --> "
- << ProofManager::currentPM()->getInputFormulaName((*rewrite).toExpr())
- << std::endl;
- ProofManager::currentPM()->addAssertionFilter(*rewrite,
- ProofManager::currentPM()->getInputFormulaName((*rewrite).toExpr()));
- } else {
- Debug("pf::pm") << "LFSCProof::checkUnrewrittenAssertion: this assertion WAS rewritten! " << *rewrite << std::endl;
- }
- }
-}
-
-//---from Morgan---
-
-bool ProofManager::hasOp(TNode n) const {
- return d_bops.find(n) != d_bops.end();
-}
-
-Node ProofManager::lookupOp(TNode n) const {
- std::map<Node, Node>::const_iterator i = d_bops.find(n);
- Assert(i != d_bops.end());
- return (*i).second;
-}
-
-Node ProofManager::mkOp(TNode n) {
- Trace("mgd-pm-mkop") << "MkOp : " << n << " " << n.getKind() << std::endl;
- if(n.getKind() != kind::BUILTIN) {
- return n;
- }
-
- Node& op = d_ops[n];
- if(op.isNull()) {
- Assert((n.getConst<Kind>() == kind::SELECT)
- || (n.getConst<Kind>() == kind::STORE));
-
- Debug("mgd-pm-mkop") << "making an op for " << n << "\n";
-
- std::stringstream ss;
- ss << n;
- std::string s = ss.str();
- Debug("mgd-pm-mkop") << " : " << s << std::endl;
- std::vector<TypeNode> v;
- v.push_back(NodeManager::currentNM()->integerType());
- if(n.getConst<Kind>() == kind::SELECT) {
- v.push_back(NodeManager::currentNM()->integerType());
- v.push_back(NodeManager::currentNM()->integerType());
- } else if(n.getConst<Kind>() == kind::STORE) {
- v.push_back(NodeManager::currentNM()->integerType());
- v.push_back(NodeManager::currentNM()->integerType());
- v.push_back(NodeManager::currentNM()->integerType());
- }
- TypeNode type = NodeManager::currentNM()->mkFunctionType(v);
- Debug("mgd-pm-mkop") << "typenode is: " << type << "\n";
- op = NodeManager::currentNM()->mkSkolem(s, type, " ignore", NodeManager::SKOLEM_NO_NOTIFY);
- d_bops[op] = n;
- }
- Debug("mgd-pm-mkop") << "returning the op: " << op << "\n";
- return op;
-}
-//---end from Morgan---
-
-bool ProofManager::wasPrinted(const Type& type) const {
- return d_printedTypes.find(type) != d_printedTypes.end();
-}
-
-void ProofManager::markPrinted(const Type& type) {
- d_printedTypes.insert(type);
-}
-
-void ProofManager::addRewriteFilter(const std::string &original, const std::string &substitute) {
- d_rewriteFilters[original] = substitute;
-}
-
-bool ProofManager::haveRewriteFilter(TNode lit) {
- std::string litName = getLitName(currentPM()->d_cnfProof->getLiteral(lit));
- return d_rewriteFilters.find(litName) != d_rewriteFilters.end();
-}
-
-void ProofManager::clearRewriteFilters() {
- d_rewriteFilters.clear();
-}
-
-std::ostream& operator<<(std::ostream& out, CVC4::ProofRule k) {
- switch(k) {
- case RULE_GIVEN:
- out << "RULE_GIVEN";
- break;
- case RULE_DERIVED:
- out << "RULE_DERIVED";
- break;
- case RULE_RECONSTRUCT:
- out << "RULE_RECONSTRUCT";
- break;
- case RULE_TRUST:
- out << "RULE_TRUST";
- break;
- case RULE_INVALID:
- out << "RULE_INVALID";
- break;
- case RULE_CONFLICT:
- out << "RULE_CONFLICT";
- break;
- case RULE_TSEITIN:
- out << "RULE_TSEITIN";
- break;
- case RULE_SPLIT:
- out << "RULE_SPLIT";
- break;
- case RULE_ARRAYS_EXT:
- out << "RULE_ARRAYS";
- break;
- case RULE_ARRAYS_ROW:
- out << "RULE_ARRAYS";
- break;
- default:
- out << "ProofRule Unknown! [" << unsigned(k) << "]";
- }
-
- return out;
-}
-
-void ProofManager::registerRewrite(unsigned ruleId, Node original, Node result){
- Assert(currentPM()->d_theoryProof != NULL);
- currentPM()->d_rewriteLog.push_back(RewriteLogEntry(ruleId, original, result));
-}
-
-void ProofManager::clearRewriteLog() {
- Assert(currentPM()->d_theoryProof != NULL);
- currentPM()->d_rewriteLog.clear();
-}
-
-std::vector<RewriteLogEntry> ProofManager::getRewriteLog() {
- return currentPM()->d_rewriteLog;
-}
-
-void ProofManager::dumpRewriteLog() const {
- Debug("pf::rr") << "Dumpign rewrite log:" << std::endl;
-
- for (unsigned i = 0; i < d_rewriteLog.size(); ++i) {
- Debug("pf::rr") << "\tRule " << d_rewriteLog[i].getRuleId()
- << ": "
- << d_rewriteLog[i].getOriginal()
- << " --> "
- << d_rewriteLog[i].getResult() << std::endl;
- }
-}
-
-void bind(Expr term, ProofLetMap& map, Bindings& letOrder) {
- ProofLetMap::iterator it = map.find(term);
- if (it != map.end())
- return;
-
- for (unsigned i = 0; i < term.getNumChildren(); ++i)
- bind(term[i], map, letOrder);
-
- // Special case: chain operators. If we have and(a,b,c), it will be prineted as and(a,and(b,c)).
- // The subterm and(b,c) may repeat elsewhere, so we need to bind it, too.
- Kind k = term.getKind();
- if (((k == kind::OR) || (k == kind::AND)) && term.getNumChildren() > 2) {
- Node currentExpression = term[term.getNumChildren() - 1];
- for (int i = term.getNumChildren() - 2; i >= 0; --i) {
- NodeBuilder<> builder(k);
- builder << term[i];
- builder << currentExpression.toExpr();
- currentExpression = builder;
- bind(currentExpression.toExpr(), map, letOrder);
- }
- } else {
- unsigned newId = ProofLetCount::newId();
- ProofLetCount letCount(newId);
- map[term] = letCount;
- letOrder.push_back(LetOrderElement(term, newId));
- }
-}
-
-void ProofManager::printGlobalLetMap(std::set<Node>& atoms,
- ProofLetMap& letMap,
- std::ostream& out,
- std::ostringstream& paren) {
- Bindings letOrder;
- std::set<Node>::const_iterator atom;
- for (atom = atoms.begin(); atom != atoms.end(); ++atom) {
- bind(atom->toExpr(), letMap, letOrder);
- }
-
- // TODO: give each theory a chance to add atoms. For now, just query BV directly...
- const std::set<Node>* additionalAtoms = ProofManager::getBitVectorProof()->getAtomsInBitblastingProof();
- for (atom = additionalAtoms->begin(); atom != additionalAtoms->end(); ++atom) {
- bind(atom->toExpr(), letMap, letOrder);
- }
-
- for (unsigned i = 0; i < letOrder.size(); ++i) {
- Expr currentExpr = letOrder[i].expr;
- unsigned letId = letOrder[i].id;
- ProofLetMap::iterator it = letMap.find(currentExpr);
- Assert(it != letMap.end());
- out << "\n(@ let" << letId << " ";
- d_theoryProof->printBoundTerm(currentExpr, out, letMap);
- paren << ")";
- it->second.increment();
- }
-
- out << std::endl << std::endl;
-}
-
-void ProofManager::ensureLiteral(Node node) {
- d_cnfProof->ensureLiteral(node);
-}
-void ProofManager::printTrustedTerm(Node term,
- std::ostream& os,
- ProofLetMap& globalLetMap)
-{
- TheoryProofEngine* tpe = ProofManager::currentPM()->getTheoryProofEngine();
- if (tpe->printsAsBool(term)) os << "(p_app ";
- tpe->printTheoryTerm(term.toExpr(), os, globalLetMap);
- if (tpe->printsAsBool(term)) os << ")";
-}
-
-ProofManager::ProofManagerStatistics::ProofManagerStatistics()
- : d_proofProductionTime("proof::ProofManager::proofProductionTime"),
- d_theoryLemmaTime(
- "proof::ProofManager::proofProduction::theoryLemmaTime"),
- d_skeletonProofTraceTime(
- "proof::ProofManager::proofProduction::skeletonProofTraceTime"),
- d_proofDeclarationsTime(
- "proof::ProofManager::proofProduction::proofDeclarationsTime"),
- d_cnfProofTime("proof::ProofManager::proofProduction::cnfProofTime"),
- d_finalProofTime("proof::ProofManager::proofProduction::finalProofTime")
-{
- smtStatisticsRegistry()->registerStat(&d_proofProductionTime);
- smtStatisticsRegistry()->registerStat(&d_theoryLemmaTime);
- smtStatisticsRegistry()->registerStat(&d_skeletonProofTraceTime);
- smtStatisticsRegistry()->registerStat(&d_proofDeclarationsTime);
- smtStatisticsRegistry()->registerStat(&d_cnfProofTime);
- smtStatisticsRegistry()->registerStat(&d_finalProofTime);
-}
-
-ProofManager::ProofManagerStatistics::~ProofManagerStatistics()
-{
- smtStatisticsRegistry()->unregisterStat(&d_proofProductionTime);
- smtStatisticsRegistry()->unregisterStat(&d_theoryLemmaTime);
- smtStatisticsRegistry()->unregisterStat(&d_skeletonProofTraceTime);
- smtStatisticsRegistry()->unregisterStat(&d_proofDeclarationsTime);
- smtStatisticsRegistry()->unregisterStat(&d_cnfProofTime);
- smtStatisticsRegistry()->unregisterStat(&d_finalProofTime);
-}
-
} /* CVC4 namespace */
diff --git a/src/proof/proof_manager.h b/src/proof/proof_manager.h
index 45bde4dcb..3013c9b55 100644
--- a/src/proof/proof_manager.h
+++ b/src/proof/proof_manager.h
@@ -28,59 +28,27 @@
#include "context/cdhashset.h"
#include "expr/node.h"
#include "proof/clause_id.h"
-#include "proof/proof.h"
-#include "proof/proof_utils.h"
-#include "proof/skolemization_manager.h"
-#include "theory/logic_info.h"
-#include "theory/substitutions.h"
-#include "util/proof.h"
#include "util/statistics_registry.h"
namespace CVC4 {
-class SmtGlobals;
-
// forward declarations
namespace Minisat {
class Solver;
}/* Minisat namespace */
-namespace BVMinisat {
- class Solver;
-}/* BVMinisat namespace */
-
namespace prop {
class CnfStream;
}/* CVC4::prop namespace */
class SmtEngine;
-const ClauseId ClauseIdEmpty(-1);
-const ClauseId ClauseIdUndef(-2);
-const ClauseId ClauseIdError(-3);
-
template <class Solver> class TSatProof;
typedef TSatProof< CVC4::Minisat::Solver> CoreSatProof;
class CnfProof;
-class RewriterProof;
-class TheoryProofEngine;
-class TheoryProof;
-class UFProof;
-class ArithProof;
-class ArrayProof;
-
-namespace proof {
-class ResolutionBitVectorProof;
-}
-
-template <class Solver> class LFSCSatProof;
-typedef TSatProof<CVC4::Minisat::Solver> CoreSatProof;
-class LFSCCnfProof;
-class LFSCTheoryProofEngine;
-class LFSCUFProof;
-class LFSCRewriterProof;
+typedef TSatProof<CVC4::Minisat::Solver> CoreSatProof;
namespace prop {
typedef uint64_t SatVariable;
@@ -88,291 +56,72 @@ namespace prop {
typedef std::vector<SatLiteral> SatClause;
}/* CVC4::prop namespace */
-// different proof modes
-enum ProofFormat {
- LFSC,
- NATIVE
-};/* enum ProofFormat */
-
-std::string append(const std::string& str, uint64_t num);
-
typedef std::unordered_map<ClauseId, prop::SatClause*> IdToSatClause;
typedef context::CDHashSet<Expr, ExprHashFunction> CDExprSet;
-typedef std::unordered_map<Node, std::vector<Node>, NodeHashFunction> NodeToNodes;
typedef context::CDHashMap<Node, std::vector<Node>, NodeHashFunction> CDNodeToNodes;
typedef std::unordered_set<ClauseId> IdHashSet;
-enum ProofRule {
- RULE_GIVEN, /* input assertion */
- RULE_DERIVED, /* a "macro" rule */
- RULE_RECONSTRUCT, /* prove equivalence using another method */
- RULE_TRUST, /* trust without evidence (escape hatch until proofs are fully supported) */
- RULE_INVALID, /* assert-fail if this is ever needed in proof; use e.g. for split lemmas */
- RULE_CONFLICT, /* re-construct as a conflict */
- RULE_TSEITIN, /* Tseitin CNF transformation */
- RULE_SPLIT, /* A splitting lemma of the form a v ~ a*/
-
- RULE_ARRAYS_EXT, /* arrays, extensional */
- RULE_ARRAYS_ROW, /* arrays, read-over-write */
-};/* enum ProofRules */
-
-class RewriteLogEntry {
-public:
- RewriteLogEntry(unsigned ruleId, Node original, Node result)
- : d_ruleId(ruleId), d_original(original), d_result(result) {
- }
-
- unsigned getRuleId() const {
- return d_ruleId;
- }
-
- Node getOriginal() const {
- return d_original;
- }
-
- Node getResult() const {
- return d_result;
- }
-
-private:
- unsigned d_ruleId;
- Node d_original;
- Node d_result;
-};
-
class ProofManager {
context::Context* d_context;
std::unique_ptr<CoreSatProof> d_satProof;
std::unique_ptr<CnfProof> d_cnfProof;
- std::unique_ptr<TheoryProofEngine> d_theoryProof;
// information that will need to be shared across proofs
- ExprSet d_inputFormulas;
- std::map<Expr, std::string> d_inputFormulaToName;
CDExprSet d_inputCoreFormulas;
CDExprSet d_outputCoreFormulas;
- SkolemizationManager d_skolemizationManager;
-
int d_nextId;
- std::unique_ptr<Proof> d_fullProof;
- ProofFormat d_format; // used for now only in debug builds
-
CDNodeToNodes d_deps;
- std::set<Type> d_printedTypes;
-
- std::map<std::string, std::string> d_rewriteFilters;
- std::map<Node, std::string> d_assertionFilters;
-
- std::vector<RewriteLogEntry> d_rewriteLog;
-
-protected:
- LogicInfo d_logic;
-
public:
- ProofManager(context::Context* context, ProofFormat format = LFSC);
- ~ProofManager();
-
- static ProofManager* currentPM();
-
- // initialization
- void initSatProof(Minisat::Solver* solver);
- void initCnfProof(CVC4::prop::CnfStream* cnfStream, context::Context* ctx);
- void initTheoryProofEngine();
-
- // getting various proofs
- static const Proof& getProof(SmtEngine* smt);
- static CoreSatProof* getSatProof();
- static CnfProof* getCnfProof();
- static TheoryProofEngine* getTheoryProofEngine();
- static TheoryProof* getTheoryProof( theory::TheoryId id );
- static UFProof* getUfProof();
- static proof::ResolutionBitVectorProof* getBitVectorProof();
- static ArrayProof* getArrayProof();
- static ArithProof* getArithProof();
-
- static SkolemizationManager *getSkolemizationManager();
-
- // iterators over data shared by proofs
- typedef ExprSet::const_iterator assertions_iterator;
-
- // iterate over the assertions (these are arbitrary boolean formulas)
- assertions_iterator begin_assertions() const {
- return d_inputFormulas.begin();
- }
- assertions_iterator end_assertions() const { return d_inputFormulas.end(); }
- size_t num_assertions() const { return d_inputFormulas.size(); }
- bool have_input_assertion(const Expr& assertion) {
- return d_inputFormulas.find(assertion) != d_inputFormulas.end();
- }
-
- void ensureLiteral(Node node);
-
-//---from Morgan---
- Node mkOp(TNode n);
- Node lookupOp(TNode n) const;
- bool hasOp(TNode n) const;
-
- std::map<Node, Node> d_ops;
- std::map<Node, Node> d_bops;
-//---end from Morgan---
-
-
- // variable prefixes
- static std::string getInputClauseName(ClauseId id, const std::string& prefix = "");
- static std::string getLemmaClauseName(ClauseId id, const std::string& prefix = "");
- static std::string getLemmaName(ClauseId id, const std::string& prefix = "");
- static std::string getLearntClauseName(ClauseId id, const std::string& prefix = "");
- static std::string getPreprocessedAssertionName(Node node, const std::string& prefix = "");
- static std::string getAssertionName(Node node, const std::string& prefix = "");
- static std::string getInputFormulaName(const Expr& expr);
-
- static std::string getVarName(prop::SatVariable var, const std::string& prefix = "");
- static std::string getAtomName(prop::SatVariable var, const std::string& prefix = "");
- static std::string getAtomName(TNode atom, const std::string& prefix = "");
- static std::string getLitName(prop::SatLiteral lit, const std::string& prefix = "");
- static std::string getLitName(TNode lit, const std::string& prefix = "");
- static bool hasLitName(TNode lit);
-
- // for SMT variable names that have spaces and other things
- static std::string sanitize(TNode var);
-
- // wrap term with (p_app ... ) if the term is printed as a boolean, and print
- // used for "trust" assertions
- static void printTrustedTerm(Node term,
- std::ostream& os,
- ProofLetMap& globalLetMap);
-
- /** Add proof assertion - unlike addCoreAssertion this is post definition expansion **/
- void addAssertion(Expr formula);
-
- /** Public unsat core methods **/
- void addCoreAssertion(Expr formula);
-
- void addDependence(TNode n, TNode dep);
- void addUnsatCore(Expr formula);
-
- // trace dependences back to unsat core
- void traceDeps(TNode n, ExprSet* coreAssertions);
- void traceDeps(TNode n, CDExprSet* coreAssertions);
- void traceUnsatCore();
-
- typedef CDExprSet::const_iterator output_core_iterator;
-
- output_core_iterator begin_unsat_core() const { return d_outputCoreFormulas.begin(); }
- output_core_iterator end_unsat_core() const { return d_outputCoreFormulas.end(); }
- size_t size_unsat_core() const { return d_outputCoreFormulas.size(); }
- std::vector<Expr> extractUnsatCore();
-
- bool unsatCoreAvailable() const;
- void getLemmasInUnsatCore(theory::TheoryId theory, std::vector<Node> &lemmas);
- Node getWeakestImplicantInUnsatCore(Node lemma);
-
- int nextId() { return d_nextId++; }
-
- void setLogic(const LogicInfo& logic);
- const std::string getLogic() const { return d_logic.getLogicString(); }
- LogicInfo & getLogicInfo() { return d_logic; }
-
- void markPrinted(const Type& type);
- bool wasPrinted(const Type& type) const;
-
- void addRewriteFilter(const std::string &original, const std::string &substitute);
- void clearRewriteFilters();
- bool haveRewriteFilter(TNode lit);
-
- void addAssertionFilter(const Node& node, const std::string& rewritten);
-
- static void registerRewrite(unsigned ruleId, Node original, Node result);
- static void clearRewriteLog();
-
- std::vector<RewriteLogEntry> getRewriteLog();
- void dumpRewriteLog() const;
+ ProofManager(context::Context* context);
+ ~ProofManager();
- void printGlobalLetMap(std::set<Node>& atoms,
- ProofLetMap& letMap,
- std::ostream& out,
- std::ostringstream& paren);
-
- struct ProofManagerStatistics
- {
- ProofManagerStatistics();
- ~ProofManagerStatistics();
+ static ProofManager* currentPM();
- /**
- * Time spent producing proofs (i.e. generating the proof from the logging
- * information)
- */
- TimerStat d_proofProductionTime;
+ // initialization
+ void initSatProof(Minisat::Solver* solver);
+ void initCnfProof(CVC4::prop::CnfStream* cnfStream, context::Context* ctx);
- /**
- * Time spent printing proofs of theory lemmas
- */
- TimerStat d_theoryLemmaTime;
+ // getting various proofs
+ static CoreSatProof* getSatProof();
+ static CnfProof* getCnfProof();
- /**
- * Time spent tracing the proof of the boolean skeleton
- * (e.g. figuring out which assertions are needed, etc.)
- */
- TimerStat d_skeletonProofTraceTime;
+ /** Public unsat core methods **/
+ void addCoreAssertion(Expr formula);
- /**
- * Time spent processing and printing declarations in the proof
- */
- TimerStat d_proofDeclarationsTime;
+ void addDependence(TNode n, TNode dep);
+ void addUnsatCore(Expr formula);
- /**
- * Time spent printing the CNF proof
- */
- TimerStat d_cnfProofTime;
+ // trace dependences back to unsat core
+ void traceDeps(TNode n, CDExprSet* coreAssertions);
+ void traceUnsatCore();
- /**
- * Time spent printing the final proof of UNSAT
- */
- TimerStat d_finalProofTime;
+ typedef CDExprSet::const_iterator output_core_iterator;
- }; /* struct ProofManagerStatistics */
+ output_core_iterator begin_unsat_core() const
+ {
+ return d_outputCoreFormulas.begin();
+ }
+ output_core_iterator end_unsat_core() const
+ {
+ return d_outputCoreFormulas.end();
+ }
+ size_t size_unsat_core() const { return d_outputCoreFormulas.size(); }
+ std::vector<Expr> extractUnsatCore();
- ProofManagerStatistics& getStats() { return d_stats; }
+ bool unsatCoreAvailable() const;
+ void getLemmasInUnsatCore(std::vector<Node>& lemmas);
- private:
- void constructSatProof();
- std::set<Node> satClauseToNodeSet(prop::SatClause* clause);
+ int nextId() { return d_nextId++; }
- ProofManagerStatistics d_stats;
+private:
+ void constructSatProof();
};/* class ProofManager */
-class LFSCProof : public Proof
-{
- public:
- LFSCProof(SmtEngine* smtEngine,
- CoreSatProof* sat,
- LFSCCnfProof* cnf,
- LFSCTheoryProofEngine* theory);
- ~LFSCProof() override {}
- void toStream(std::ostream& out) const override;
- void toStream(std::ostream& out, const ProofLetMap& map) const override;
-
- private:
- // FIXME: hack until we get preprocessing
- void printPreprocessedAssertions(const NodeSet& assertions,
- std::ostream& os,
- std::ostream& paren,
- ProofLetMap& globalLetMap) const;
-
- void checkUnrewrittenAssertion(const NodeSet& assertions) const;
-
- CoreSatProof* d_satProof;
- LFSCCnfProof* d_cnfProof;
- LFSCTheoryProofEngine* d_theoryProof;
- SmtEngine* d_smtEngine;
-}; /* class LFSCProof */
-
-std::ostream& operator<<(std::ostream& out, CVC4::ProofRule k);
}/* CVC4 namespace */
diff --git a/src/proof/proof_output_channel.cpp b/src/proof/proof_output_channel.cpp
deleted file mode 100644
index 88467aea6..000000000
--- a/src/proof/proof_output_channel.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-/********************* */
-/*! \file proof_output_channel.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Guy Katz, Tim King, Liana Hadarean
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** [[ Add lengthier description here ]]
-
- ** \todo document this file
-
-**/
-
-#include "proof/proof_output_channel.h"
-
-#include "base/check.h"
-#include "theory/term_registration_visitor.h"
-#include "theory/valuation.h"
-
-namespace CVC4 {
-
-ProofOutputChannel::ProofOutputChannel() : d_conflict(), d_proof(nullptr) {}
-const Proof& ProofOutputChannel::getConflictProof() const
-{
- Assert(hasConflict());
- return *d_proof;
-}
-
-void ProofOutputChannel::conflict(TNode n, std::unique_ptr<Proof> pf)
-{
- Trace("pf::tp") << "ProofOutputChannel: CONFLICT: " << n << std::endl;
- Assert(!hasConflict());
- Assert(!d_proof);
- d_conflict = n;
- d_proof = std::move(pf);
- Assert(hasConflict());
- Assert(d_proof);
-}
-
-bool ProofOutputChannel::propagate(TNode x) {
- Trace("pf::tp") << "ProofOutputChannel: got a propagation: " << x
- << std::endl;
- d_propagations.insert(x);
- return true;
-}
-
-theory::LemmaStatus ProofOutputChannel::lemma(TNode n,
- ProofRule rule,
- theory::LemmaProperty p)
-{
- Trace("pf::tp") << "ProofOutputChannel: new lemma: " << n << std::endl;
- // TODO(#1231): We should transition to supporting multiple lemmas. The
- // following assertion cannot be enabled due to
- // "test/regress/regress0/arrays/swap_t1_np_nf_ai_00005_007.cvc.smt".
- // Assert(
- // d_lemma.isNull()) <<
- // "Multiple calls to ProofOutputChannel::lemma() are not supported.";
- d_lemma = n;
- return theory::LemmaStatus(TNode::null(), 0);
-}
-
-theory::LemmaStatus ProofOutputChannel::splitLemma(TNode, bool) {
- AlwaysAssert(false);
- return theory::LemmaStatus(TNode::null(), 0);
-}
-
-void ProofOutputChannel::requirePhase(TNode n, bool b) {
- Debug("pf::tp") << "ProofOutputChannel::requirePhase called" << std::endl;
- Trace("pf::tp") << "requirePhase " << n << " " << b << std::endl;
-}
-
-void ProofOutputChannel::setIncomplete() {
- Debug("pf::tp") << "ProofOutputChannel::setIncomplete called" << std::endl;
- AlwaysAssert(false);
-}
-
-
-MyPreRegisterVisitor::MyPreRegisterVisitor(theory::Theory* theory)
- : d_theory(theory)
- , d_visited() {
-}
-
-bool MyPreRegisterVisitor::alreadyVisited(TNode current, TNode parent) {
- return d_visited.find(current) != d_visited.end();
-}
-
-void MyPreRegisterVisitor::visit(TNode current, TNode parent) {
- d_theory->preRegisterTerm(current);
- d_visited.insert(current);
-}
-
-void MyPreRegisterVisitor::start(TNode node) {
-}
-
-void MyPreRegisterVisitor::done(TNode node) {
-}
-
-} /* namespace CVC4 */
diff --git a/src/proof/proof_output_channel.h b/src/proof/proof_output_channel.h
deleted file mode 100644
index b68abd44b..000000000
--- a/src/proof/proof_output_channel.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/********************* */
-/*! \file proof_output_channel.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Tim King, Guy Katz, Liana Hadarean
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- **/
-
-#include "cvc4_private.h"
-
-#ifndef CVC4__PROOF_OUTPUT_CHANNEL_H
-#define CVC4__PROOF_OUTPUT_CHANNEL_H
-
-#include <memory>
-#include <set>
-#include <unordered_set>
-
-#include "expr/node.h"
-#include "theory/output_channel.h"
-#include "theory/theory.h"
-#include "util/proof.h"
-
-namespace CVC4 {
-
-class ProofOutputChannel : public theory::OutputChannel {
- public:
- ProofOutputChannel();
- ~ProofOutputChannel() override {}
-
- /**
- * This may be called at most once per ProofOutputChannel.
- * Requires that `n` and `pf` are non-null.
- */
- void conflict(TNode n, std::unique_ptr<Proof> pf) override;
- bool propagate(TNode x) override;
- theory::LemmaStatus lemma(TNode n,
- ProofRule rule,
- theory::LemmaProperty p) override;
- theory::LemmaStatus splitLemma(TNode, bool) override;
- void requirePhase(TNode n, bool b) override;
- void setIncomplete() override;
-
- /** Has conflict() has been called? */
- bool hasConflict() const { return !d_conflict.isNull(); }
-
- /**
- * Returns the proof passed into the conflict() call.
- * Requires hasConflict() to hold.
- */
- const Proof& getConflictProof() const;
- Node getLastLemma() const { return d_lemma; }
-
- private:
- Node d_conflict;
- std::unique_ptr<Proof> d_proof;
- Node d_lemma;
- std::set<Node> d_propagations;
-}; /* class ProofOutputChannel */
-
-class MyPreRegisterVisitor {
- theory::Theory* d_theory;
- std::unordered_set<TNode, TNodeHashFunction> d_visited;
-public:
- typedef void return_type;
- MyPreRegisterVisitor(theory::Theory* theory);
- bool alreadyVisited(TNode current, TNode parent);
- void visit(TNode current, TNode parent);
- void start(TNode node);
- void done(TNode node);
-}; /* class MyPreRegisterVisitor */
-
-} /* CVC4 namespace */
-
-#endif /* CVC4__PROOF_OUTPUT_CHANNEL_H */
diff --git a/src/proof/proof_utils.cpp b/src/proof/proof_utils.cpp
deleted file mode 100644
index cad56db6a..000000000
--- a/src/proof/proof_utils.cpp
+++ /dev/null
@@ -1,126 +0,0 @@
-/********************* */
-/*! \file proof_utils.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Liana Hadarean, Andrew Reynolds, Guy Katz
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** [[ Add lengthier description here ]]
-
- ** \todo document this file
-
-**/
-
-#include "proof/proof_utils.h"
-#include "theory/theory.h"
-
-namespace CVC4 {
-namespace utils {
-
-std::string toLFSCKind(Kind kind) {
- switch(kind) {
- // core kinds
- case kind::OR : return "or";
- case kind::AND: return "and";
- case kind::XOR: return "xor";
- case kind::EQUAL: return "=";
- case kind::IMPLIES: return "impl";
- case kind::NOT: return "not";
-
- // bit-vector kinds
- case kind::BITVECTOR_AND :
- return "bvand";
- case kind::BITVECTOR_OR :
- return "bvor";
- case kind::BITVECTOR_XOR :
- return "bvxor";
- case kind::BITVECTOR_NAND :
- return "bvnand";
- case kind::BITVECTOR_NOR :
- return "bvnor";
- case kind::BITVECTOR_XNOR :
- return "bvxnor";
- case kind::BITVECTOR_COMP :
- return "bvcomp";
- case kind::BITVECTOR_MULT :
- return "bvmul";
- case kind::BITVECTOR_PLUS :
- return "bvadd";
- case kind::BITVECTOR_SUB :
- return "bvsub";
- case kind::BITVECTOR_UDIV :
- case kind::BITVECTOR_UDIV_TOTAL :
- return "bvudiv";
- case kind::BITVECTOR_UREM :
- case kind::BITVECTOR_UREM_TOTAL :
- return "bvurem";
- case kind::BITVECTOR_SDIV :
- return "bvsdiv";
- case kind::BITVECTOR_SREM :
- return "bvsrem";
- case kind::BITVECTOR_SMOD :
- return "bvsmod";
- case kind::BITVECTOR_SHL :
- return "bvshl";
- case kind::BITVECTOR_LSHR :
- return "bvlshr";
- case kind::BITVECTOR_ASHR :
- return "bvashr";
- case kind::BITVECTOR_CONCAT :
- return "concat";
- case kind::BITVECTOR_NEG :
- return "bvneg";
- case kind::BITVECTOR_NOT :
- return "bvnot";
- case kind::BITVECTOR_ROTATE_LEFT :
- return "rotate_left";
- case kind::BITVECTOR_ROTATE_RIGHT :
- return "rotate_right";
- case kind::BITVECTOR_ULT :
- return "bvult";
- case kind::BITVECTOR_ULE :
- return "bvule";
- case kind::BITVECTOR_UGT :
- return "bvugt";
- case kind::BITVECTOR_UGE :
- return "bvuge";
- case kind::BITVECTOR_SLT :
- return "bvslt";
- case kind::BITVECTOR_SLE :
- return "bvsle";
- case kind::BITVECTOR_SGT :
- return "bvsgt";
- case kind::BITVECTOR_SGE :
- return "bvsge";
- case kind::BITVECTOR_EXTRACT :
- return "extract";
- case kind::BITVECTOR_REPEAT :
- return "repeat";
- case kind::BITVECTOR_ZERO_EXTEND :
- return "zero_extend";
- case kind::BITVECTOR_SIGN_EXTEND :
- return "sign_extend";
- default:
- Unreachable();
- }
-}
-
-std::string toLFSCKindTerm(Expr node) {
- Kind k = node.getKind();
- if( k==kind::EQUAL ){
- if( node[0].getType().isBoolean() ){
- return "iff";
- }else{
- return "=";
- }
- }else{
- return toLFSCKind( k );
- }
-}
-
-} /* namespace CVC4::utils */
-} /* namespace CVC4 */
diff --git a/src/proof/proof_utils.h b/src/proof/proof_utils.h
deleted file mode 100644
index e54edd8b7..000000000
--- a/src/proof/proof_utils.h
+++ /dev/null
@@ -1,229 +0,0 @@
-/********************* */
-/*! \file proof_utils.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Liana Hadarean, Guy Katz, Dejan Jovanovic
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** [[ Add lengthier description here ]]
-
- ** \todo document this file
-
-**/
-
-#include "cvc4_private.h"
-
-#pragma once
-
-#include <set>
-#include <sstream>
-#include <unordered_set>
-#include <vector>
-
-#include "expr/node_manager.h"
-
-namespace CVC4 {
-
-typedef std::unordered_set<Expr, ExprHashFunction> ExprSet;
-typedef std::unordered_set<Node, NodeHashFunction> NodeSet;
-
-typedef std::pair<Node, Node> NodePair;
-typedef std::set<NodePair> NodePairSet;
-
-
-class ProofLetCount {
-public:
- static unsigned counter;
- static void resetCounter() { counter = 0; }
- static unsigned newId() { return ++counter; }
-
- unsigned count;
- unsigned id;
- ProofLetCount()
- : count(0)
- , id(-1)
- {}
-
- void increment() { ++count; }
- ProofLetCount(unsigned i)
- : count(1)
- , id(i)
- {}
-
- ProofLetCount(const ProofLetCount& other)
- : count(other.count)
- , id (other.id)
- {}
-
- bool operator==(const ProofLetCount &other) const {
- return other.id == id && other.count == count;
- }
-
- ProofLetCount& operator=(const ProofLetCount &rhs) {
- if (&rhs == this) return *this;
- id = rhs.id;
- count = rhs.count;
- return *this;
- }
-};
-
-struct LetOrderElement {
- Expr expr;
- unsigned id;
- LetOrderElement(Expr e, unsigned i)
- : expr(e)
- , id(i)
- {}
-
- LetOrderElement()
- : expr()
- , id(-1)
- {}
-};
-
-typedef std::vector<LetOrderElement> Bindings;
-
-namespace utils {
-
-std::string toLFSCKind(Kind kind);
-std::string toLFSCKindTerm(Expr node);
-
-inline unsigned getExtractHigh(Expr node) {
- return node.getOperator().getConst<BitVectorExtract>().d_high;
-}
-
-inline unsigned getExtractLow(Expr node) {
- return node.getOperator().getConst<BitVectorExtract>().d_low;
-}
-
-inline unsigned getSize(Type type) {
- BitVectorType bv(type);
- return bv.getSize();
-}
-
-
-inline unsigned getSize(Expr node) {
- Assert(node.getType().isBitVector());
- return getSize(node.getType());
-}
-
-inline Expr mkTrue() {
- return NodeManager::currentNM()->toExprManager()->mkConst<bool>(true);
-}
-
-inline Expr mkFalse() {
- return NodeManager::currentNM()->toExprManager()->mkConst<bool>(false);
-}
-
-inline Expr mkExpr(Kind k , Expr expr) {
- return NodeManager::currentNM()->toExprManager()->mkExpr(k, expr);
-}
-inline Expr mkExpr(Kind k , Expr e1, Expr e2) {
- return NodeManager::currentNM()->toExprManager()->mkExpr(k, e1, e2);
-}
-inline Expr mkExpr(Kind k , std::vector<Expr>& children) {
- return NodeManager::currentNM()->toExprManager()->mkExpr(k, children);
-}
-
-
-inline Expr mkOnes(unsigned size) {
- BitVector val = BitVector::mkOnes(size);
- return NodeManager::currentNM()->toExprManager()->mkConst<BitVector>(val);
-}
-
-inline Expr mkConst(unsigned size, unsigned int value) {
- BitVector val(size, value);
- return NodeManager::currentNM()->toExprManager()->mkConst<BitVector>(val);
-}
-
-inline Expr mkConst(const BitVector& value) {
- return NodeManager::currentNM()->toExprManager()->mkConst<BitVector>(value);
-}
-
-inline Expr mkOr(const std::vector<Expr>& nodes) {
- std::set<Expr> all;
- all.insert(nodes.begin(), nodes.end());
- Assert(all.size() != 0);
-
- if (all.size() == 1) {
- // All the same, or just one
- return nodes[0];
- }
-
-
- NodeBuilder<> disjunction(kind::OR);
- std::set<Expr>::const_iterator it = all.begin();
- std::set<Expr>::const_iterator it_end = all.end();
- while (it != it_end) {
- disjunction << Node::fromExpr(*it);
- ++ it;
- }
-
- Node res = disjunction;
- return res.toExpr();
-}/* mkOr() */
-
-
-inline Expr mkAnd(const std::vector<Expr>& conjunctions) {
- std::set<Expr> all;
- all.insert(conjunctions.begin(), conjunctions.end());
-
- if (all.size() == 0) {
- return mkTrue();
- }
-
- if (all.size() == 1) {
- // All the same, or just one
- return conjunctions[0];
- }
-
-
- NodeBuilder<> conjunction(kind::AND);
- std::set<Expr>::const_iterator it = all.begin();
- std::set<Expr>::const_iterator it_end = all.end();
- while (it != it_end) {
- conjunction << Node::fromExpr(*it);
- ++ it;
- }
-
- Node res = conjunction;
- return res.toExpr();
-}/* mkAnd() */
-
-inline Expr mkSortedExpr(Kind kind, const std::vector<Expr>& children) {
- std::set<Expr> all;
- all.insert(children.begin(), children.end());
-
- if (all.size() == 0) {
- return mkTrue();
- }
-
- if (all.size() == 1) {
- // All the same, or just one
- return children[0];
- }
-
-
- NodeBuilder<> res(kind);
- std::set<Expr>::const_iterator it = all.begin();
- std::set<Expr>::const_iterator it_end = all.end();
- while (it != it_end) {
- res << Node::fromExpr(*it);
- ++ it;
- }
-
- return ((Node)res).toExpr();
-}/* mkSortedNode() */
-
-inline const bool getBit(Expr expr, unsigned i) {
- Assert(i < utils::getSize(expr) && expr.isConst());
- Integer bit = expr.getConst<BitVector>().extract(i, i).getValue();
- return (bit == 1u);
-}
-
-}
-}
diff --git a/src/proof/resolution_bitvector_proof.cpp b/src/proof/resolution_bitvector_proof.cpp
deleted file mode 100644
index d48789f71..000000000
--- a/src/proof/resolution_bitvector_proof.cpp
+++ /dev/null
@@ -1,523 +0,0 @@
-/********************* */
-/*! \file resolution_bitvector_proof.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir, Liana Hadarean, Guy Katz
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** [[ Add lengthier description here ]]
-
- ** \todo document this file
-
-**/
-
-#include "proof/resolution_bitvector_proof.h"
-#include "options/bv_options.h"
-#include "options/proof_options.h"
-#include "proof/array_proof.h"
-#include "proof/bitvector_proof.h"
-#include "proof/clause_id.h"
-#include "proof/lfsc_proof_printer.h"
-#include "proof/proof_output_channel.h"
-#include "proof/proof_utils.h"
-#include "proof/sat_proof_implementation.h"
-#include "prop/bvminisat/bvminisat.h"
-#include "prop/sat_solver_types.h"
-#include "theory/bv/bitblast/bitblaster.h"
-#include "theory/bv/theory_bv.h"
-#include "theory/bv/theory_bv_rewrite_rules.h"
-
-#include <iostream>
-#include <sstream>
-
-using namespace CVC4::theory;
-using namespace CVC4::theory::bv;
-
-namespace CVC4 {
-
-namespace proof {
-
-ResolutionBitVectorProof::ResolutionBitVectorProof(
- theory::bv::TheoryBV* bv, TheoryProofEngine* proofEngine)
- : BitVectorProof(bv, proofEngine),
- d_resolutionProof(),
- d_isAssumptionConflict(false)
-{
-}
-
-void ResolutionBitVectorProof::initSatProof(CVC4::BVMinisat::Solver* solver)
-{
- Assert(d_resolutionProof == NULL);
- d_resolutionProof.reset(new BVSatProof(solver, &d_fakeContext, "bb", true));
-}
-
-void ResolutionBitVectorProof::initCnfProof(prop::CnfStream* cnfStream,
- context::Context* cnf,
- prop::SatVariable trueVar,
- prop::SatVariable falseVar)
-{
- Assert(d_resolutionProof != NULL);
- Assert(d_cnfProof == nullptr);
- d_cnfProof.reset(new LFSCCnfProof(cnfStream, cnf, "bb"));
-
- d_cnfProof->registerTrueUnitClause(d_resolutionProof->getTrueUnit());
- d_cnfProof->registerFalseUnitClause(d_resolutionProof->getFalseUnit());
-}
-
-void ResolutionBitVectorProof::attachToSatSolver(prop::SatSolver& sat_solver)
-{
- sat_solver.setResolutionProofLog(this);
-}
-
-BVSatProof* ResolutionBitVectorProof::getSatProof()
-{
- Assert(d_resolutionProof != NULL);
- return d_resolutionProof.get();
-}
-
-void ResolutionBitVectorProof::startBVConflict(
- CVC4::BVMinisat::Solver::TCRef cr)
-{
- d_resolutionProof->startResChain(cr);
-}
-
-void ResolutionBitVectorProof::startBVConflict(
- CVC4::BVMinisat::Solver::TLit lit)
-{
- d_resolutionProof->startResChain(lit);
-}
-
-void ResolutionBitVectorProof::endBVConflict(
- const CVC4::BVMinisat::Solver::TLitVec& confl)
-{
- Debug("pf::bv") << "ResolutionBitVectorProof::endBVConflict called"
- << std::endl;
-
- std::vector<Expr> expr_confl;
- for (int i = 0; i < confl.size(); ++i)
- {
- prop::SatLiteral lit = prop::BVMinisatSatSolver::toSatLiteral(confl[i]);
- Expr atom = d_cnfProof->getAtom(lit.getSatVariable()).toExpr();
- Expr expr_lit = lit.isNegated() ? atom.notExpr() : atom;
- expr_confl.push_back(expr_lit);
- }
-
- Expr conflict = utils::mkSortedExpr(kind::OR, expr_confl);
- Debug("pf::bv") << "Make conflict for " << conflict << std::endl;
-
- if (d_bbConflictMap.find(conflict) != d_bbConflictMap.end())
- {
- Debug("pf::bv") << "Abort...already conflict for " << conflict << std::endl;
- // This can only happen when we have eager explanations in the bv solver
- // if we don't get to propagate p before ~p is already asserted
- d_resolutionProof->cancelResChain();
- return;
- }
-
- // we don't need to check for uniqueness in the sat solver then
- ClauseId clause_id = d_resolutionProof->registerAssumptionConflict(confl);
- d_bbConflictMap[conflict] = clause_id;
- d_resolutionProof->endResChain(clause_id);
- Debug("pf::bv") << "ResolutionBitVectorProof::endBVConflict id" << clause_id
- << " => " << conflict << "\n";
- d_isAssumptionConflict = false;
-}
-
-void ResolutionBitVectorProof::finalizeConflicts(std::vector<Expr>& conflicts)
-{
- if (options::bitblastMode() == options::BitblastMode::EAGER)
- {
- Debug("pf::bv") << "Construct full proof." << std::endl;
- d_resolutionProof->constructProof();
- return;
- }
-
- for (unsigned i = 0; i < conflicts.size(); ++i)
- {
- Expr confl = conflicts[i];
- Debug("pf::bv") << "Finalize conflict #" << i << ": " << confl << std::endl;
-
- // Special case: if the conflict has a (true) or a (not false) in it, it is
- // trivial...
- bool ignoreConflict = false;
- if ((confl.isConst() && confl.getConst<bool>())
- || (confl.getKind() == kind::NOT && confl[0].isConst()
- && !confl[0].getConst<bool>()))
- {
- ignoreConflict = true;
- }
- else if (confl.getKind() == kind::OR)
- {
- for (unsigned k = 0; k < confl.getNumChildren(); ++k)
- {
- if ((confl[k].isConst() && confl[k].getConst<bool>())
- || (confl[k].getKind() == kind::NOT && confl[k][0].isConst()
- && !confl[k][0].getConst<bool>()))
- {
- ignoreConflict = true;
- }
- }
- }
- if (ignoreConflict)
- {
- Debug("pf::bv") << "Ignoring conflict due to (true) or (not false)"
- << std::endl;
- continue;
- }
-
- if (d_bbConflictMap.find(confl) != d_bbConflictMap.end())
- {
- ClauseId id = d_bbConflictMap[confl];
- d_resolutionProof->collectClauses(id);
- }
- else
- {
- // There is no exact match for our conflict, but maybe it is a subset of
- // another conflict
- ExprToClauseId::const_iterator it;
- bool matchFound = false;
- for (it = d_bbConflictMap.begin(); it != d_bbConflictMap.end(); ++it)
- {
- Expr possibleMatch = it->first;
- if (possibleMatch.getKind() != kind::OR)
- {
- // This is a single-node conflict. If this node is in the conflict
- // we're trying to prove, we have a match.
- for (unsigned k = 0; k < confl.getNumChildren(); ++k)
- {
- if (confl[k] == possibleMatch)
- {
- matchFound = true;
- d_resolutionProof->collectClauses(it->second);
- break;
- }
- }
- }
- else
- {
- if (possibleMatch.getNumChildren() > confl.getNumChildren()) continue;
-
- unsigned k = 0;
- bool matching = true;
- for (unsigned j = 0; j < possibleMatch.getNumChildren(); ++j)
- {
- // j is the index in possibleMatch
- // k is the index in confl
- while (k < confl.getNumChildren() && confl[k] != possibleMatch[j])
- {
- ++k;
- }
- if (k == confl.getNumChildren())
- {
- // We couldn't find a match for possibleMatch[j], so not a match
- matching = false;
- break;
- }
- }
-
- if (matching)
- {
- Debug("pf::bv")
- << "Collecting info from a sub-conflict" << std::endl;
- d_resolutionProof->collectClauses(it->second);
- matchFound = true;
- break;
- }
- }
- }
-
- if (!matchFound)
- {
- Debug("pf::bv") << "Do not collect clauses for " << confl << std::endl
- << "Dumping existing conflicts:" << std::endl;
-
- i = 0;
- for (it = d_bbConflictMap.begin(); it != d_bbConflictMap.end(); ++it)
- {
- ++i;
- Debug("pf::bv") << "\tConflict #" << i << ": " << it->first
- << std::endl;
- }
-
- Unreachable();
- }
- }
- }
-}
-
-void LfscResolutionBitVectorProof::printTheoryLemmaProof(
- std::vector<Expr>& lemma,
- std::ostream& os,
- std::ostream& paren,
- const ProofLetMap& map)
-{
- Debug("pf::bv")
- << "(pf::bv) LfscResolutionBitVectorProof::printTheoryLemmaProof called"
- << std::endl;
- Expr conflict = utils::mkSortedExpr(kind::OR, lemma);
- Debug("pf::bv") << "\tconflict = " << conflict << std::endl;
-
- if (d_bbConflictMap.find(conflict) != d_bbConflictMap.end())
- {
- std::ostringstream lemma_paren;
- for (unsigned i = 0; i < lemma.size(); ++i)
- {
- Expr lit = lemma[i];
-
- if (lit.getKind() == kind::NOT)
- {
- os << "(intro_assump_t _ _ _ ";
- }
- else
- {
- os << "(intro_assump_f _ _ _ ";
- }
- lemma_paren << ")";
- // print corresponding literal in main sat solver
- ProofManager* pm = ProofManager::currentPM();
- CnfProof* cnf = pm->getCnfProof();
- prop::SatLiteral main_lit = cnf->getLiteral(lit);
- os << pm->getLitName(main_lit);
- os << " ";
- // print corresponding literal in bv sat solver
- prop::SatVariable bb_var = d_cnfProof->getLiteral(lit).getSatVariable();
- os << pm->getAtomName(bb_var, "bb");
- os << "(\\ unit" << bb_var << "\n";
- lemma_paren << ")";
- }
- Expr lem = utils::mkOr(lemma);
- Assert(d_bbConflictMap.find(lem) != d_bbConflictMap.end());
- ClauseId lemma_id = d_bbConflictMap[lem];
- proof::LFSCProofPrinter::printAssumptionsResolution(
- d_resolutionProof.get(), lemma_id, os, lemma_paren);
- os << lemma_paren.str();
- }
- else
- {
- Debug("pf::bv") << "Found a non-recorded conflict. Looking for a matching "
- "sub-conflict..."
- << std::endl;
-
- bool matching;
-
- ExprToClauseId::const_iterator it;
- unsigned i = 0;
- for (it = d_bbConflictMap.begin(); it != d_bbConflictMap.end(); ++it)
- {
- // Our conflict is sorted, and the records are also sorted.
- ++i;
- Expr possibleMatch = it->first;
-
- if (possibleMatch.getKind() != kind::OR)
- {
- // This is a single-node conflict. If this node is in the conflict we're
- // trying to prove, we have a match.
- matching = false;
-
- for (unsigned k = 0; k < conflict.getNumChildren(); ++k)
- {
- if (conflict[k] == possibleMatch)
- {
- matching = true;
- break;
- }
- }
- }
- else
- {
- if (possibleMatch.getNumChildren() > conflict.getNumChildren())
- continue;
-
- unsigned k = 0;
-
- matching = true;
- for (unsigned j = 0; j < possibleMatch.getNumChildren(); ++j)
- {
- // j is the index in possibleMatch
- // k is the index in conflict
- while (k < conflict.getNumChildren()
- && conflict[k] != possibleMatch[j])
- {
- ++k;
- }
- if (k == conflict.getNumChildren())
- {
- // We couldn't find a match for possibleMatch[j], so not a match
- matching = false;
- break;
- }
- }
- }
-
- if (matching)
- {
- Debug("pf::bv") << "Found a match with conflict #" << i << ": "
- << std::endl
- << possibleMatch << std::endl;
- // The rest is just a copy of the usual handling, if a precise match is
- // found. We only use the literals that appear in the matching conflict,
- // though, and not in the original lemma - as these may not have even
- // been bit blasted!
- std::ostringstream lemma_paren;
-
- if (possibleMatch.getKind() == kind::OR)
- {
- for (const Expr& lit : possibleMatch)
- {
- if (lit.getKind() == kind::NOT)
- {
- os << "(intro_assump_t _ _ _ ";
- }
- else
- {
- os << "(intro_assump_f _ _ _ ";
- }
- lemma_paren << ")";
- // print corresponding literal in main sat solver
- ProofManager* pm = ProofManager::currentPM();
- CnfProof* cnf = pm->getCnfProof();
- prop::SatLiteral main_lit = cnf->getLiteral(lit);
- os << pm->getLitName(main_lit);
- os << " ";
- // print corresponding literal in bv sat solver
- prop::SatVariable bb_var =
- d_cnfProof->getLiteral(lit).getSatVariable();
- os << pm->getAtomName(bb_var, "bb");
- os << "(\\ unit" << bb_var << "\n";
- lemma_paren << ")";
- }
- }
- else
- {
- // The conflict only consists of one node, either positive or
- // negative.
- Expr lit = possibleMatch;
- if (lit.getKind() == kind::NOT)
- {
- os << "(intro_assump_t _ _ _ ";
- }
- else
- {
- os << "(intro_assump_f _ _ _ ";
- }
- lemma_paren << ")";
- // print corresponding literal in main sat solver
- ProofManager* pm = ProofManager::currentPM();
- CnfProof* cnf = pm->getCnfProof();
- prop::SatLiteral main_lit = cnf->getLiteral(lit);
- os << pm->getLitName(main_lit);
- os << " ";
- // print corresponding literal in bv sat solver
- prop::SatVariable bb_var =
- d_cnfProof->getLiteral(lit).getSatVariable();
- os << pm->getAtomName(bb_var, "bb");
- os << "(\\ unit" << bb_var << "\n";
- lemma_paren << ")";
- }
-
- ClauseId lemma_id = it->second;
- proof::LFSCProofPrinter::printAssumptionsResolution(
- d_resolutionProof.get(), lemma_id, os, lemma_paren);
- os << lemma_paren.str();
-
- return;
- }
- }
-
- // We failed to find a matching sub conflict. The last hope is that the
- // conflict has a FALSE assertion in it; this can happen in some corner
- // cases, where the FALSE is the result of a rewrite.
-
- for (const Expr& lit : lemma)
- {
- if (lit.getKind() == kind::NOT && lit[0] == utils::mkFalse())
- {
- Debug("pf::bv") << "Lemma has a (not false) literal" << std::endl;
- os << "(clausify_false ";
- os << ProofManager::getLitName(lit);
- os << ")";
- return;
- }
- }
-
- Debug("pf::bv") << "Failed to find a matching sub-conflict..." << std::endl
- << "Dumping existing conflicts:" << std::endl;
-
- i = 0;
- for (it = d_bbConflictMap.begin(); it != d_bbConflictMap.end(); ++it)
- {
- ++i;
- Debug("pf::bv") << "\tConflict #" << i << ": " << it->first << std::endl;
- }
-
- Unreachable();
- }
-}
-
-void LfscResolutionBitVectorProof::calculateAtomsInBitblastingProof()
-{
- // Collect the input clauses used
- IdToSatClause used_lemmas;
- IdToSatClause used_inputs;
- d_resolutionProof->collectClausesUsed(used_inputs, used_lemmas);
- d_cnfProof->collectAtomsForClauses(used_inputs, d_atomsInBitblastingProof);
- Assert(used_lemmas.empty());
-}
-
-void LfscResolutionBitVectorProof::printBBDeclarationAndCnf(std::ostream& os,
- std::ostream& paren,
- ProofLetMap& letMap)
-{
- // print mapping between theory atoms and internal SAT variables
- os << std::endl << ";; BB atom mapping\n" << std::endl;
-
- std::set<Node>::iterator atomIt;
- Debug("pf::bv") << std::endl
- << "BV Dumping atoms from inputs: " << std::endl
- << std::endl;
- for (atomIt = d_atomsInBitblastingProof.begin();
- atomIt != d_atomsInBitblastingProof.end();
- ++atomIt)
- {
- Debug("pf::bv") << "\tAtom: " << *atomIt << std::endl;
- }
- Debug("pf::bv") << std::endl;
-
- // first print bit-blasting
- printBitblasting(os, paren);
-
- // print CNF conversion proof for bit-blasted facts
- IdToSatClause used_lemmas;
- IdToSatClause used_inputs;
- d_resolutionProof->collectClausesUsed(used_inputs, used_lemmas);
-
- d_cnfProof->printAtomMapping(d_atomsInBitblastingProof, os, paren, letMap);
- os << std::endl << ";; Bit-blasting definitional clauses \n" << std::endl;
- for (IdToSatClause::iterator it = used_inputs.begin();
- it != used_inputs.end();
- ++it)
- {
- d_cnfProof->printCnfProofForClause(it->first, it->second, os, paren);
- }
-
- os << std::endl << " ;; Bit-blasting learned clauses \n" << std::endl;
- proof::LFSCProofPrinter::printResolutions(d_resolutionProof.get(), os, paren);
-}
-
-void LfscResolutionBitVectorProof::printEmptyClauseProof(std::ostream& os,
- std::ostream& paren)
-{
- Assert(options::bitblastMode() == options::BitblastMode::EAGER)
- << "the BV theory should only be proving bottom directly in the eager "
- "bitblasting mode";
- proof::LFSCProofPrinter::printResolutionEmptyClause(
- d_resolutionProof.get(), os, paren);
-}
-
-} // namespace proof
-
-} /* namespace CVC4 */
diff --git a/src/proof/resolution_bitvector_proof.h b/src/proof/resolution_bitvector_proof.h
deleted file mode 100644
index a1b0b0d59..000000000
--- a/src/proof/resolution_bitvector_proof.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/********************* */
-/*! \file resolution_bitvector_proof.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir, Mathias Preiner, Liana Hadarean
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief Bitvector proof
- **
- ** Bitvector proof
- **/
-
-#include "cvc4_private.h"
-
-#ifndef CVC4__PROOF__RESOLUTION_BITVECTOR_PROOF_H
-#define CVC4__PROOF__RESOLUTION_BITVECTOR_PROOF_H
-
-#include <iosfwd>
-
-#include "context/context.h"
-#include "expr/expr.h"
-#include "proof/bitvector_proof.h"
-#include "proof/sat_proof.h"
-#include "proof/theory_proof.h"
-#include "prop/bvminisat/core/Solver.h"
-#include "prop/cnf_stream.h"
-#include "prop/sat_solver_types.h"
-#include "theory/bv/bitblast/bitblaster.h"
-#include "theory/bv/theory_bv.h"
-
-namespace CVC4 {
-
-typedef TSatProof<CVC4::BVMinisat::Solver> BVSatProof;
-
-namespace proof {
-
-/**
- * Represents a bitvector proof which is backed by
- * (a) bitblasting and
- * (b) a resolution unsat proof.
- *
- * Contains tools for constructing BV conflicts
- */
-class ResolutionBitVectorProof : public BitVectorProof
-{
- public:
- ResolutionBitVectorProof(theory::bv::TheoryBV* bv,
- TheoryProofEngine* proofEngine);
-
- /**
- * Create an (internal) SAT proof object
- * Must be invoked before manipulating BV conflicts,
- * or initializing a BNF proof
- */
- void initSatProof(CVC4::BVMinisat::Solver* solver);
-
- BVSatProof* getSatProof();
-
- void finalizeConflicts(std::vector<Expr>& conflicts) override;
-
- void startBVConflict(CVC4::BVMinisat::Solver::TCRef cr);
- void startBVConflict(CVC4::BVMinisat::Solver::TLit lit);
- void endBVConflict(const BVMinisat::Solver::TLitVec& confl);
-
- void markAssumptionConflict() { d_isAssumptionConflict = true; }
- bool isAssumptionConflict() const { return d_isAssumptionConflict; }
-
- void initCnfProof(prop::CnfStream* cnfStream,
- context::Context* cnf,
- prop::SatVariable trueVar,
- prop::SatVariable falseVar) override;
-
- protected:
- void attachToSatSolver(prop::SatSolver& sat_solver) override;
-
- context::Context d_fakeContext;
-
- // The CNF formula that results from bit-blasting will need a proof.
- // This is that proof.
- std::unique_ptr<BVSatProof> d_resolutionProof;
-
- bool d_isAssumptionConflict;
-
-};
-
-class LfscResolutionBitVectorProof : public ResolutionBitVectorProof
-{
- public:
- LfscResolutionBitVectorProof(theory::bv::TheoryBV* bv,
- TheoryProofEngine* proofEngine)
- : ResolutionBitVectorProof(bv, proofEngine)
- {
- }
- void printTheoryLemmaProof(std::vector<Expr>& lemma,
- std::ostream& os,
- std::ostream& paren,
- const ProofLetMap& map) override;
- void printBBDeclarationAndCnf(std::ostream& os,
- std::ostream& paren,
- ProofLetMap& letMap) override;
- void printEmptyClauseProof(std::ostream& os, std::ostream& paren) override;
- void calculateAtomsInBitblastingProof() override;
-};
-
-} // namespace proof
-
-} // namespace CVC4
-
-#endif /* CVC4__PROOF__RESOLUTIONBITVECTORPROOF_H */
diff --git a/src/proof/sat_proof.h b/src/proof/sat_proof.h
index 83e4d3930..38aea0673 100644
--- a/src/proof/sat_proof.h
+++ b/src/proof/sat_proof.h
@@ -32,7 +32,6 @@
#include "expr/expr.h"
#include "proof/clause_id.h"
#include "proof/proof_manager.h"
-#include "util/proof.h"
#include "util/statistics_registry.h"
// Forward declarations.
diff --git a/src/proof/sat_proof_implementation.h b/src/proof/sat_proof_implementation.h
index 897a5c452..7ce18ae4a 100644
--- a/src/proof/sat_proof_implementation.h
+++ b/src/proof/sat_proof_implementation.h
@@ -20,10 +20,7 @@
#define CVC4__SAT__PROOF_IMPLEMENTATION_H
#include "proof/clause_id.h"
-#include "proof/cnf_proof.h"
#include "proof/sat_proof.h"
-#include "prop/bvminisat/bvminisat.h"
-#include "prop/bvminisat/core/Solver.h"
#include "prop/minisat/core/Solver.h"
#include "prop/minisat/minisat.h"
#include "prop/sat_solver_types.h"
@@ -712,11 +709,6 @@ void TSatProof<Solver>::registerResolution(ClauseId id, ResChain<Solver>* res) {
Assert(checkResolution(id));
}
- PSTATS(uint64_t resolutionSteps =
- static_cast<uint64_t>(res.getSteps().size());
- d_statistics.d_resChainLengths << resolutionSteps;
- d_statistics.d_avgChainLength.addEntry(resolutionSteps);
- ++(d_statistics.d_numLearnedClauses);)
}
/// recording resolutions
@@ -912,14 +904,6 @@ void TSatProof<Solver>::markDeleted(typename Solver::TCRef clause) {
}
}
-// template<>
-// void toSatClause< ::BVMinisat::Solver> (const BVMinisat::Solver::TClause&
-// minisat_cl,
-// prop::SatClause& sat_cl) {
-
-// prop::BVMinisatSatSolver::toSatClause(minisat_cl, sat_cl);
-// }
-
template <class Solver>
void TSatProof<Solver>::constructProof(ClauseId conflict) {
d_satProofConstructed = true;
@@ -1002,9 +986,6 @@ void TSatProof<Solver>::collectClauses(ClauseId id) {
const ResolutionChain& res = getResolutionChain(id);
const typename ResolutionChain::ResSteps& steps = res.getSteps();
- PSTATS(d_statistics.d_usedResChainLengths
- << ((uint64_t)steps.size());
- d_statistics.d_usedClauseGlue << ((uint64_t)d_glueMap[id]););
ClauseId start = res.getStart();
collectClauses(start);
@@ -1018,8 +999,6 @@ void TSatProof<Solver>::collectClausesUsed(IdToSatClause& inputs,
IdToSatClause& lemmas) {
inputs = d_seenInputs;
lemmas = d_seenLemmas;
- PSTATS(d_statistics.d_numLearnedInProof.setData(d_seenLearnt.size());
- d_statistics.d_numLemmasInProof.setData(d_seenLemmas.size()););
}
template <class Solver>
diff --git a/src/proof/simplify_boolean_node.cpp b/src/proof/simplify_boolean_node.cpp
deleted file mode 100644
index 5f1943654..000000000
--- a/src/proof/simplify_boolean_node.cpp
+++ /dev/null
@@ -1,183 +0,0 @@
-/********************* */
-/*! \file simplify_boolean_node.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Guy Katz, Liana Hadarean, Andrew Reynolds
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief Simplifying a boolean node, needed for constructing LFSC proofs.
- **
- **/
-
-#include "cvc4_private.h"
-
-#include "proof_manager.h"
-
-namespace CVC4 {
-
-inline static Node eqNode(TNode n1, TNode n2) {
- return NodeManager::currentNM()->mkNode(kind::EQUAL, n1, n2);
-}
-
-Node simplifyBooleanNode(const Node &n) {
- if (n.isNull())
- return n;
-
- // Only simplify boolean nodes
- if (!n.getType().isBoolean())
- return n;
-
- // Sometimes we get sent intermediate nodes that we shouldn't simplify.
- // If a node doesn't have a literal, it's clearly intermediate - ignore.
- if (!ProofManager::hasLitName(n))
- return n;
-
- // If we already simplified the node, ignore.
- if (ProofManager::currentPM()->haveRewriteFilter(n.negate()))
- return n;
-
-
- std::string litName = ProofManager::getLitName(n.negate());
- Node falseNode = NodeManager::currentNM()->mkConst(false);
- Node trueNode = NodeManager::currentNM()->mkConst(true);
- Node simplified = n;
-
- // (not (= false b)), (not (= true b)))
- if ((n.getKind() == kind::NOT) && (n[0].getKind() == kind::EQUAL) &&
- (n[0][0].getKind() == kind::BOOLEAN_TERM_VARIABLE || n[0][1].getKind() == kind::BOOLEAN_TERM_VARIABLE)) {
- Node lhs = n[0][0];
- Node rhs = n[0][1];
-
- if (lhs == falseNode) {
- Assert(rhs != falseNode);
- Assert(rhs.getKind() == kind::BOOLEAN_TERM_VARIABLE);
- // (not (= false b)) --> true = b
-
- simplified = eqNode(trueNode, rhs);
-
- std::string simplifiedLitName = ProofManager::getLitName(simplified.negate());
- std::stringstream newLitName;
- newLitName << "(pred_not_iff_f _ " << litName << ")";
- ProofManager::currentPM()->addRewriteFilter(simplifiedLitName, newLitName.str());
-
- } else if (rhs == falseNode) {
- Assert(lhs != falseNode);
- Assert(lhs.getKind() == kind::BOOLEAN_TERM_VARIABLE);
- // (not (= b false)) --> b = true
-
- simplified = eqNode(lhs, trueNode);
- std::string simplifiedLitName = ProofManager::getLitName(simplified.negate());
- std::stringstream newLitName;
- newLitName << "(pred_not_iff_f_2 _ " << litName << ")";
- ProofManager::currentPM()->addRewriteFilter(simplifiedLitName, newLitName.str());
-
- } else if (lhs == trueNode) {
- Assert(rhs != trueNode);
- Assert(rhs.getKind() == kind::BOOLEAN_TERM_VARIABLE);
- // (not (= true b)) --> b = false
-
- simplified = eqNode(falseNode, rhs);
- std::string simplifiedLitName = ProofManager::getLitName(simplified.negate());
- std::stringstream newLitName;
- newLitName << "(pred_not_iff_t _ " << litName << ")";
- ProofManager::currentPM()->addRewriteFilter(simplifiedLitName, newLitName.str());
-
- } else if (rhs == trueNode) {
- Assert(lhs != trueNode);
- Assert(lhs.getKind() == kind::BOOLEAN_TERM_VARIABLE);
- // (not (= b true)) --> b = false
-
- simplified = eqNode(lhs, falseNode);
- std::string simplifiedLitName = ProofManager::getLitName(simplified.negate());
- std::stringstream newLitName;
- newLitName << "(pred_not_iff_t_2 _ " << litName << ")";
- ProofManager::currentPM()->addRewriteFilter(simplifiedLitName, newLitName.str());
- }
-
- } else if ((n.getKind() == kind::EQUAL) &&
- (n[0].getKind() == kind::BOOLEAN_TERM_VARIABLE || n[1].getKind() == kind::BOOLEAN_TERM_VARIABLE)) {
- Node lhs = n[0];
- Node rhs = n[1];
-
- if (lhs == falseNode) {
- Assert(rhs != falseNode);
- Assert(rhs.getKind() == kind::BOOLEAN_TERM_VARIABLE);
- // (= false b)
-
- std::stringstream newLitName;
- newLitName << "(pred_iff_f _ " << litName << ")";
- ProofManager::currentPM()->addRewriteFilter(litName, newLitName.str());
-
- } else if (rhs == falseNode) {
- Assert(lhs != falseNode);
- Assert(lhs.getKind() == kind::BOOLEAN_TERM_VARIABLE);
- // (= b false))
-
- std::stringstream newLitName;
- newLitName << "(pred_iff_f_2 _ " << litName << ")";
- ProofManager::currentPM()->addRewriteFilter(litName, newLitName.str());
-
- } else if (lhs == trueNode) {
- Assert(rhs != trueNode);
- Assert(rhs.getKind() == kind::BOOLEAN_TERM_VARIABLE);
- // (= true b)
-
- std::stringstream newLitName;
- newLitName << "(pred_iff_t _ " << litName << ")";
- ProofManager::currentPM()->addRewriteFilter(litName, newLitName.str());
-
- } else if (rhs == trueNode) {
- Assert(lhs != trueNode);
- Assert(lhs.getKind() == kind::BOOLEAN_TERM_VARIABLE);
- // (= b true)
-
-
- std::stringstream newLitName;
- newLitName << "(pred_iff_t_2 _ " << litName << ")";
- ProofManager::currentPM()->addRewriteFilter(litName, newLitName.str());
- }
-
- } else if ((n.getKind() == kind::NOT) && (n[0].getKind() == kind::BOOLEAN_TERM_VARIABLE)) {
- // (not b) --> b = false
- simplified = eqNode(n[0], falseNode);
- std::string simplifiedLitName = ProofManager::getLitName(simplified.negate());
- std::stringstream newLitName;
- newLitName << "(pred_eq_f _ " << litName << ")";
- ProofManager::currentPM()->addRewriteFilter(simplifiedLitName, newLitName.str());
-
- } else if (n.getKind() == kind::BOOLEAN_TERM_VARIABLE) {
- // (b) --> b = true
- simplified = eqNode(n, trueNode);
- std::string simplifiedLitName = ProofManager::getLitName(simplified.negate());
- std::stringstream newLitName;
- newLitName << "(pred_eq_t _ " << litName << ")";
- ProofManager::currentPM()->addRewriteFilter(simplifiedLitName, newLitName.str());
-
- } else if ((n.getKind() == kind::NOT) && (n[0].getKind() == kind::SELECT)) {
- // not(a[x]) --> a[x] = false
- simplified = eqNode(n[0], falseNode);
- std::string simplifiedLitName = ProofManager::getLitName(simplified.negate());
- std::stringstream newLitName;
- newLitName << "(pred_eq_f _ " << litName << ")";
- ProofManager::currentPM()->addRewriteFilter(simplifiedLitName, newLitName.str());
-
- } else if (n.getKind() == kind::SELECT) {
- // a[x] --> a[x] = true
- simplified = eqNode(n, trueNode);
- std::string simplifiedLitName = ProofManager::getLitName(simplified.negate());
- std::stringstream newLitName;
- newLitName << "(pred_eq_t _ " << litName << ")";
- ProofManager::currentPM()->addRewriteFilter(simplifiedLitName, newLitName.str());
- }
-
- if (simplified != n)
- Debug("pf::simplify") << "simplifyBooleanNode: " << n << " --> " << simplified << std::endl;
-
- return simplified;
-}
-
-}/* CVC4 namespace */
diff --git a/src/proof/simplify_boolean_node.h b/src/proof/simplify_boolean_node.h
deleted file mode 100644
index bb4fe2e47..000000000
--- a/src/proof/simplify_boolean_node.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/********************* */
-/*! \file simplify_boolean_node.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Mathias Preiner, Guy Katz
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief Simplifying a boolean node, needed for constructing LFSC proofs.
- **
- **/
-
-#include "cvc4_private.h"
-
-#ifndef CVC4__SIMPLIFY_BOOLEAN_NODE_H
-#define CVC4__SIMPLIFY_BOOLEAN_NODE_H
-
-namespace CVC4 {
-
-Node simplifyBooleanNode(const Node &n);
-
-}/* CVC4 namespace */
-
-#endif /* CVC4__SIMPLIFY_BOOLEAN_NODE_H */
diff --git a/src/proof/skolemization_manager.cpp b/src/proof/skolemization_manager.cpp
deleted file mode 100644
index 1bb14598d..000000000
--- a/src/proof/skolemization_manager.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-/********************* */
-/*! \file skolemization_manager.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Paul Meng, Tim King, Mathias Preiner
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** [[ Add lengthier description here ]]
-
- ** \todo document this file
-
- **/
-
-#include "proof/skolemization_manager.h"
-
-namespace CVC4 {
-
-void SkolemizationManager::registerSkolem(Node disequality, Node skolem) {
- Debug("pf::pm") << "SkolemizationManager: registerSkolem: disequality = " << disequality << ", skolem = " << skolem << std::endl;
-
- if (isSkolem(skolem)) {
- Assert(d_skolemToDisequality[skolem] == disequality);
- return;
- }
-
- d_disequalityToSkolem[disequality] = skolem;
- d_skolemToDisequality[skolem] = disequality;
-}
-
-bool SkolemizationManager::hasSkolem(Node disequality) {
- return (d_disequalityToSkolem.find(disequality) != d_disequalityToSkolem.end());
-}
-
-Node SkolemizationManager::getSkolem(Node disequality) {
- Debug("pf::pm") << "SkolemizationManager: getSkolem( ";
- Assert(d_disequalityToSkolem.find(disequality)
- != d_disequalityToSkolem.end());
- Debug("pf::pm") << disequality << " ) = " << d_disequalityToSkolem[disequality] << std::endl;
- return d_disequalityToSkolem[disequality];
-}
-
-Node SkolemizationManager::getDisequality(Node skolem) {
- Assert(d_skolemToDisequality.find(skolem) != d_skolemToDisequality.end());
- return d_skolemToDisequality[skolem];
-}
-
-bool SkolemizationManager::isSkolem(Node skolem) {
- return (d_skolemToDisequality.find(skolem) != d_skolemToDisequality.end());
-}
-
-void SkolemizationManager::clear() {
- Debug("pf::pm") << "SkolemizationManager: clear" << std::endl;
- d_disequalityToSkolem.clear();
- d_skolemToDisequality.clear();
-}
-
-std::unordered_map<Node, Node, NodeHashFunction>::const_iterator SkolemizationManager::begin() {
- return d_disequalityToSkolem.begin();
-}
-
-std::unordered_map<Node, Node, NodeHashFunction>::const_iterator SkolemizationManager::end() {
- return d_disequalityToSkolem.end();
-}
-
-} /* CVC4 namespace */
diff --git a/src/proof/skolemization_manager.h b/src/proof/skolemization_manager.h
deleted file mode 100644
index a2c61db4d..000000000
--- a/src/proof/skolemization_manager.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/********************* */
-/*! \file skolemization_manager.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Guy Katz, Tim King, Mathias Preiner
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** [[ Add lengthier description here ]]
-
- ** \todo document this file
-
- **/
-
-#include "cvc4_private.h"
-
-#ifndef CVC4__SKOLEMIZATION_MANAGER_H
-#define CVC4__SKOLEMIZATION_MANAGER_H
-
-#include <iostream>
-#include <unordered_map>
-
-#include "proof/proof.h"
-#include "util/proof.h"
-#include "expr/node.h"
-#include "theory/logic_info.h"
-#include "theory/substitutions.h"
-
-namespace CVC4 {
-
-class SkolemizationManager {
-public:
- void registerSkolem(Node disequality, Node skolem);
- bool hasSkolem(Node disequality);
- Node getSkolem(Node disequality);
- Node getDisequality(Node skolem);
- bool isSkolem(Node skolem);
- void clear();
-
- std::unordered_map<Node, Node, NodeHashFunction>::const_iterator begin();
- std::unordered_map<Node, Node, NodeHashFunction>::const_iterator end();
-
-private:
- std::unordered_map<Node, Node, NodeHashFunction> d_disequalityToSkolem;
- std::unordered_map<Node, Node, NodeHashFunction> d_skolemToDisequality;
-};
-
-}/* CVC4 namespace */
-
-
-
-#endif /* CVC4__SKOLEMIZATION_MANAGER_H */
diff --git a/src/proof/theory_proof.cpp b/src/proof/theory_proof.cpp
deleted file mode 100644
index b47fd6a1e..000000000
--- a/src/proof/theory_proof.cpp
+++ /dev/null
@@ -1,1756 +0,0 @@
-/********************* */
-/*! \file theory_proof.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Guy Katz, Liana Hadarean, Yoni Zohar
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief [[ Add one-line brief description here ]]
- **
- ** [[ Add lengthier description here ]]
- ** \todo document this file
- **/
-#include "proof/theory_proof.h"
-
-#include "base/check.h"
-#include "context/context.h"
-#include "expr/node_visitor.h"
-#include "options/bv_options.h"
-#include "options/proof_options.h"
-#include "proof/arith_proof.h"
-#include "proof/array_proof.h"
-#include "proof/clausal_bitvector_proof.h"
-#include "proof/clause_id.h"
-#include "proof/cnf_proof.h"
-#include "proof/proof_manager.h"
-#include "proof/proof_output_channel.h"
-#include "proof/proof_utils.h"
-#include "proof/resolution_bitvector_proof.h"
-#include "proof/sat_proof.h"
-#include "proof/simplify_boolean_node.h"
-#include "proof/uf_proof.h"
-#include "prop/sat_solver_types.h"
-#include "smt/smt_engine.h"
-#include "smt/smt_engine_scope.h"
-#include "theory/arrays/theory_arrays.h"
-#include "theory/bv/theory_bv.h"
-#include "theory/output_channel.h"
-#include "theory/term_registration_visitor.h"
-#include "theory/uf/theory_uf.h"
-#include "theory/valuation.h"
-#include "util/hash.h"
-#include "util/proof.h"
-
-namespace CVC4 {
-
-using proof::LfscResolutionBitVectorProof;
-using proof::ResolutionBitVectorProof;
-
-unsigned CVC4::ProofLetCount::counter = 0;
-static unsigned LET_COUNT = 1;
-
-TheoryProofEngine::TheoryProofEngine()
- : d_registrationCache()
- , d_theoryProofTable()
-{
- d_theoryProofTable[theory::THEORY_BOOL] = new LFSCBooleanProof(this);
-}
-
-TheoryProofEngine::~TheoryProofEngine() {
- TheoryProofTable::iterator it = d_theoryProofTable.begin();
- TheoryProofTable::iterator end = d_theoryProofTable.end();
- for (; it != end; ++it) {
- delete it->second;
- }
-}
-
-void TheoryProofEngine::registerTheory(theory::Theory* th) {
- if (th) {
- theory::TheoryId id = th->getId();
- if(d_theoryProofTable.find(id) == d_theoryProofTable.end()) {
-
- Trace("pf::tp") << "TheoryProofEngine::registerTheory: " << id << std::endl;
-
- if (id == theory::THEORY_UF) {
- d_theoryProofTable[id] = new LFSCUFProof((theory::uf::TheoryUF*)th, this);
- return;
- }
-
- if (id == theory::THEORY_BV) {
- auto thBv = static_cast<theory::bv::TheoryBV*>(th);
- if (options::bitblastMode() == options::BitblastMode::EAGER
- && options::bvSatSolver() == options::SatSolverMode::CRYPTOMINISAT)
- {
- proof::BitVectorProof* bvp = nullptr;
- switch (options::bvProofFormat())
- {
- case options::BvProofFormat::DRAT:
- {
- bvp = new proof::LfscDratBitVectorProof(thBv, this);
- break;
- }
- case options::BvProofFormat::LRAT:
- {
- bvp = new proof::LfscLratBitVectorProof(thBv, this);
- break;
- }
- case options::BvProofFormat::ER:
- {
- bvp = new proof::LfscErBitVectorProof(thBv, this);
- break;
- }
- default:
- {
- Unreachable() << "Invalid BvProofFormat";
- }
- };
- d_theoryProofTable[id] = bvp;
- }
- else
- {
- proof::BitVectorProof* bvp =
- new proof::LfscResolutionBitVectorProof(thBv, this);
- d_theoryProofTable[id] = bvp;
- }
- return;
- }
-
- if (id == theory::THEORY_ARRAYS) {
- d_theoryProofTable[id] = new LFSCArrayProof((theory::arrays::TheoryArrays*)th, this);
- return;
- }
-
- if (id == theory::THEORY_ARITH) {
- d_theoryProofTable[id] = new LFSCArithProof((theory::arith::TheoryArith*)th, this);
- return;
- }
-
- // TODO other theories
- }
- }
-}
-
-void TheoryProofEngine::finishRegisterTheory(theory::Theory* th) {
- if (th) {
- theory::TheoryId id = th->getId();
- if (id == theory::THEORY_BV) {
- theory::bv::TheoryBV* bv_th = static_cast<theory::bv::TheoryBV*>(th);
- Assert(d_theoryProofTable.find(id) != d_theoryProofTable.end());
- proof::BitVectorProof* bvp =
- static_cast<proof::BitVectorProof*>(d_theoryProofTable[id]);
- bv_th->setProofLog(bvp);
- return;
- }
- }
-}
-
-TheoryProof* TheoryProofEngine::getTheoryProof(theory::TheoryId id) {
- // The UF theory handles queries for the Builtin theory.
- if (id == theory::THEORY_BUILTIN) {
- Debug("pf::tp") << "TheoryProofEngine::getTheoryProof: BUILTIN --> UF" << std::endl;
- id = theory::THEORY_UF;
- }
-
- if (d_theoryProofTable.find(id) == d_theoryProofTable.end()) {
- InternalError()
- << "Error! Proofs not yet supported for the following theory: " << id
- << std::endl;
- }
-
- return d_theoryProofTable[id];
-}
-
-void TheoryProofEngine::markTermForFutureRegistration(Expr term, theory::TheoryId id) {
- d_exprToTheoryIds[term].insert(id);
-}
-
-void TheoryProofEngine::printConstantDisequalityProof(std::ostream& os, Expr c1, Expr c2, const ProofLetMap &globalLetMap) {
- Assert(c1.isConst());
- Assert(c2.isConst());
-
- Assert(theory::Theory::theoryOf(c1) == theory::Theory::theoryOf(c2));
- getTheoryProof(theory::Theory::theoryOf(c1))->printConstantDisequalityProof(os, c1, c2, globalLetMap);
-}
-
-void TheoryProofEngine::printTheoryTerm(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType)
-{
- this->printTheoryTermAsType(term, os, map, expectedType);
-}
-
-TypeNode TheoryProofEngine::equalityType(const Expr& left, const Expr& right)
-{
- // Ask the two theories what they think..
- TypeNode leftType = getTheoryProof(theory::Theory::theoryOf(left))->equalityType(left, right);
- TypeNode rightType = getTheoryProof(theory::Theory::theoryOf(right))->equalityType(left, right);
-
- // Error if the disagree.
- Assert(leftType.isNull() || rightType.isNull() || leftType == rightType)
- << "TheoryProofEngine::equalityType(" << left << ", " << right << "):" << std::endl
- << "theories disagree about the type of an equality:" << std::endl
- << "\tleft: " << leftType << std::endl
- << "\tright:" << rightType;
-
- return leftType.isNull() ? rightType : leftType;
-}
-
-void TheoryProofEngine::registerTerm(Expr term) {
- Debug("pf::tp::register") << "TheoryProofEngine::registerTerm: registering term: " << term << std::endl;
-
- if (d_registrationCache.count(term)) {
- return;
- }
-
- Debug("pf::tp::register") << "TheoryProofEngine::registerTerm: registering NEW term: " << term << std::endl;
-
- theory::TheoryId theory_id = theory::Theory::theoryOf(term);
-
- Debug("pf::tp::register") << "Term's theory( " << term << " ) = " << theory_id << std::endl;
-
- // don't need to register boolean terms
- if (theory_id == theory::THEORY_BUILTIN ||
- term.getKind() == kind::ITE) {
- for (unsigned i = 0; i < term.getNumChildren(); ++i) {
- registerTerm(term[i]);
- }
- d_registrationCache.insert(term);
- return;
- }
-
- if (!supportedTheory(theory_id)) return;
-
- // Register the term with its owner theory
- getTheoryProof(theory_id)->registerTerm(term);
-
- // A special case: the array theory needs to know of every skolem, even if
- // it belongs to another theory (e.g., a BV skolem)
- if (ProofManager::getSkolemizationManager()->isSkolem(term) && theory_id != theory::THEORY_ARRAYS) {
- Debug("pf::tp::register") << "TheoryProofEngine::registerTerm: registering a non-array skolem: " << term << std::endl;
- getTheoryProof(theory::THEORY_ARRAYS)->registerTerm(term);
- }
-
- d_registrationCache.insert(term);
-}
-
-theory::TheoryId TheoryProofEngine::getTheoryForLemma(const prop::SatClause* clause) {
- ProofManager* pm = ProofManager::currentPM();
-
- std::set<Node> nodes;
- for(unsigned i = 0; i < clause->size(); ++i) {
- prop::SatLiteral lit = (*clause)[i];
- Node node = pm->getCnfProof()->getAtom(lit.getSatVariable());
- Expr atom = node.toExpr();
- if (atom.isConst()) {
- Assert(atom == utils::mkTrue());
- continue;
- }
-
- nodes.insert(lit.isNegated() ? node.notNode() : node);
- }
-
- // Ensure that the lemma is in the database.
- Assert(pm->getCnfProof()->haveProofRecipe(nodes));
- return pm->getCnfProof()->getProofRecipe(nodes).getTheory();
-}
-
-void LFSCTheoryProofEngine::bind(Expr term, ProofLetMap& map, Bindings& let_order) {
- ProofLetMap::iterator it = map.find(term);
- if (it != map.end()) {
- ProofLetCount& count = it->second;
- count.increment();
- return;
- }
- for (unsigned i = 0; i < term.getNumChildren(); ++i) {
- bind(term[i], map, let_order);
- }
- unsigned new_id = ProofLetCount::newId();
- map[term] = ProofLetCount(new_id);
- let_order.push_back(LetOrderElement(term, new_id));
-}
-
-void LFSCTheoryProofEngine::printLetTerm(Expr term, std::ostream& os) {
- ProofLetMap map;
- Bindings let_order;
- bind(term, map, let_order);
- std::ostringstream paren;
- for (unsigned i = 0; i < let_order.size(); ++i) {
- Expr current_expr = let_order[i].expr;
- unsigned let_id = let_order[i].id;
- ProofLetMap::const_iterator it = map.find(current_expr);
- Assert(it != map.end());
- unsigned let_count = it->second.count;
- Assert(let_count);
- // skip terms that only appear once
- if (let_count <= LET_COUNT) {
- continue;
- }
-
- os << "(@ let" <<let_id << " ";
- printTheoryTerm(current_expr, os, map);
- paren <<")";
- }
- unsigned last_let_id = let_order.back().id;
- Expr last = let_order.back().expr;
- unsigned last_count = map.find(last)->second.count;
- if (last_count <= LET_COUNT) {
- printTheoryTerm(last, os, map);
- }
- else {
- os << " let" << last_let_id;
- }
- os << paren.str();
-}
-
-void LFSCTheoryProofEngine::printTheoryTermAsType(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType)
-{
- theory::TheoryId theory_id = theory::Theory::theoryOf(term);
-
- // boolean terms and ITEs are special because they
- // are common to all theories
- if (theory_id == theory::THEORY_BUILTIN ||
- term.getKind() == kind::ITE ||
- term.getKind() == kind::EQUAL) {
- printCoreTerm(term, os, map, expectedType);
- return;
- }
- // dispatch to proper theory
- getTheoryProof(theory_id)->printOwnedTerm(term, os, map, expectedType);
-}
-
-void LFSCTheoryProofEngine::printSort(Type type, std::ostream& os) {
- if (type.isSort()) {
- getTheoryProof(theory::THEORY_UF)->printOwnedSort(type, os);
- return;
- }
- if (type.isBitVector()) {
- getTheoryProof(theory::THEORY_BV)->printOwnedSort(type, os);
- return;
- }
-
- if (type.isArray()) {
- getTheoryProof(theory::THEORY_ARRAYS)->printOwnedSort(type, os);
- return;
- }
-
- if (type.isInteger() || type.isReal()) {
- getTheoryProof(theory::THEORY_ARITH)->printOwnedSort(type, os);
- return;
- }
-
- if (type.isBoolean()) {
- getTheoryProof(theory::THEORY_BOOL)->printOwnedSort(type, os);
- return;
- }
-
- Unreachable();
-}
-
-void LFSCTheoryProofEngine::performExtraRegistrations() {
- ExprToTheoryIds::const_iterator it;
- for (it = d_exprToTheoryIds.begin(); it != d_exprToTheoryIds.end(); ++it) {
- if (d_registrationCache.count(it->first)) { // Only register if the term appeared
- TheoryIdSet::const_iterator theoryIt;
- for (theoryIt = it->second.begin(); theoryIt != it->second.end(); ++theoryIt) {
- Debug("pf::tp") << "\tExtra registration of term " << it->first
- << " with theory: " << *theoryIt << std::endl;
- Assert(supportedTheory(*theoryIt));
- getTheoryProof(*theoryIt)->registerTerm(it->first);
- }
- }
- }
-}
-
-void LFSCTheoryProofEngine::registerTermsFromAssertions() {
- ProofManager::assertions_iterator it = ProofManager::currentPM()->begin_assertions();
- ProofManager::assertions_iterator end = ProofManager::currentPM()->end_assertions();
-
- for(; it != end; ++it) {
- registerTerm(*it);
- }
-
- performExtraRegistrations();
-}
-
-void LFSCTheoryProofEngine::printAssertions(std::ostream& os, std::ostream& paren) {
- Debug("pf::tp") << "LFSCTheoryProofEngine::printAssertions called" << std::endl << std::endl;
-
- ProofManager::assertions_iterator it = ProofManager::currentPM()->begin_assertions();
- ProofManager::assertions_iterator end = ProofManager::currentPM()->end_assertions();
-
- for (; it != end; ++it) {
- Debug("pf::tp") << "printAssertions: assertion is: " << *it << std::endl;
- os << "(% " << ProofManager::currentPM()->getInputFormulaName(*it) << " (th_holds ";
-
- // Assertions appear before the global let map, so we use a dummpMap to avoid letification here.
- ProofLetMap dummyMap;
-
- bool convertFromBool = (it->getType().isBoolean() && printsAsBool(*it));
- if (convertFromBool) os << "(p_app ";
- printBoundTerm(*it, os, dummyMap);
- if (convertFromBool) os << ")";
-
- os << ")\n";
- paren << ")";
- }
-
- Debug("pf::tp") << "LFSCTheoryProofEngine::printAssertions done" << std::endl << std::endl;
-}
-
-void LFSCTheoryProofEngine::printLemmaRewrites(NodePairSet& rewrites,
- std::ostream& os,
- std::ostream& paren) {
- Debug("pf::tp") << "LFSCTheoryProofEngine::printLemmaRewrites called" << std::endl << std::endl;
-
- NodePairSet::const_iterator it;
-
- for (it = rewrites.begin(); it != rewrites.end(); ++it) {
- Debug("pf::tp") << "printLemmaRewrites: " << it->first << " --> " << it->second << std::endl;
-
- Node n1 = it->first;
- Node n2 = it->second;
- Assert(n1.toExpr() == utils::mkFalse()
- || theory::Theory::theoryOf(n1) == theory::Theory::theoryOf(n2));
-
- std::ostringstream rewriteRule;
- rewriteRule << ".lrr" << d_assertionToRewrite.size();
-
- os << "(th_let_pf _ ";
- getTheoryProof(theory::Theory::theoryOf(n1))->printRewriteProof(os, n1, n2);
- os << "(\\ " << rewriteRule.str() << "\n";
-
- d_assertionToRewrite[it->first] = rewriteRule.str();
- Debug("pf::tp") << "d_assertionToRewrite[" << it->first << "] = " << rewriteRule.str() << std::endl;
- paren << "))";
- }
-
- Debug("pf::tp") << "LFSCTheoryProofEngine::printLemmaRewrites done" << std::endl << std::endl;
-}
-
-void LFSCTheoryProofEngine::printSortDeclarations(std::ostream& os, std::ostream& paren) {
- Debug("pf::tp") << "LFSCTheoryProofEngine::printSortDeclarations called" << std::endl << std::endl;
-
- TheoryProofTable::const_iterator it = d_theoryProofTable.begin();
- TheoryProofTable::const_iterator end = d_theoryProofTable.end();
- for (; it != end; ++it) {
- it->second->printSortDeclarations(os, paren);
- }
-
- Debug("pf::tp") << "LFSCTheoryProofEngine::printSortDeclarations done" << std::endl << std::endl;
-}
-
-void LFSCTheoryProofEngine::printTermDeclarations(std::ostream& os, std::ostream& paren) {
- Debug("pf::tp") << "LFSCTheoryProofEngine::printTermDeclarations called" << std::endl << std::endl;
-
- TheoryProofTable::const_iterator it = d_theoryProofTable.begin();
- TheoryProofTable::const_iterator end = d_theoryProofTable.end();
- for (; it != end; ++it) {
- it->second->printTermDeclarations(os, paren);
- }
-
- Debug("pf::tp") << "LFSCTheoryProofEngine::printTermDeclarations done" << std::endl << std::endl;
-}
-
-void LFSCTheoryProofEngine::printDeferredDeclarations(std::ostream& os, std::ostream& paren) {
- Debug("pf::tp") << "LFSCTheoryProofEngine::printDeferredDeclarations called" << std::endl;
-
- TheoryProofTable::const_iterator it = d_theoryProofTable.begin();
- TheoryProofTable::const_iterator end = d_theoryProofTable.end();
- for (; it != end; ++it) {
- it->second->printDeferredDeclarations(os, paren);
- }
-}
-
-void LFSCTheoryProofEngine::printAliasingDeclarations(std::ostream& os, std::ostream& paren, const ProofLetMap &globalLetMap) {
- Debug("pf::tp") << "LFSCTheoryProofEngine::printAliasingDeclarations called" << std::endl;
-
- TheoryProofTable::const_iterator it = d_theoryProofTable.begin();
- TheoryProofTable::const_iterator end = d_theoryProofTable.end();
- for (; it != end; ++it) {
- it->second->printAliasingDeclarations(os, paren, globalLetMap);
- }
-}
-
-void LFSCTheoryProofEngine::dumpTheoryLemmas(const IdToSatClause& lemmas) {
- Debug("pf::dumpLemmas") << "Dumping ALL theory lemmas" << std::endl << std::endl;
-
- ProofManager* pm = ProofManager::currentPM();
- for (IdToSatClause::const_iterator it = lemmas.begin(); it != lemmas.end(); ++it) {
- ClauseId id = it->first;
- Debug("pf::dumpLemmas") << "**** \tLemma ID = " << id << std::endl;
- const prop::SatClause* clause = it->second;
- std::set<Node> nodes;
- for(unsigned i = 0; i < clause->size(); ++i) {
- prop::SatLiteral lit = (*clause)[i];
- Node node = pm->getCnfProof()->getAtom(lit.getSatVariable());
- if (node.isConst()) {
- Assert(node.toExpr() == utils::mkTrue());
- continue;
- }
- nodes.insert(lit.isNegated() ? node.notNode() : node);
- }
-
- LemmaProofRecipe recipe = pm->getCnfProof()->getProofRecipe(nodes);
- recipe.dump("pf::dumpLemmas");
- }
-
- Debug("pf::dumpLemmas") << "Theory lemma printing DONE" << std::endl << std::endl;
-}
-
-// TODO: this function should be moved into the BV prover.
-void LFSCTheoryProofEngine::finalizeBvConflicts(const IdToSatClause& lemmas, std::ostream& os) {
- // BitVector theory is special case: must know all conflicts needed
- // ahead of time for resolution proof lemmas
- std::vector<Expr> bv_lemmas;
-
- for (IdToSatClause::const_iterator it = lemmas.begin(); it != lemmas.end(); ++it) {
- const prop::SatClause* clause = it->second;
-
- std::vector<Expr> conflict;
- std::set<Node> conflictNodes;
- for(unsigned i = 0; i < clause->size(); ++i) {
- prop::SatLiteral lit = (*clause)[i];
- Node node = ProofManager::currentPM()->getCnfProof()->getAtom(lit.getSatVariable());
- Expr atom = node.toExpr();
-
- // The literals (true) and (not false) are omitted from conflicts
- if (atom.isConst()) {
- Assert(atom == utils::mkTrue()
- || (atom == utils::mkFalse() && lit.isNegated()));
- continue;
- }
-
- Expr expr_lit = lit.isNegated() ? atom.notExpr() : atom;
- conflict.push_back(expr_lit);
- conflictNodes.insert(lit.isNegated() ? node.notNode() : node);
- }
-
- LemmaProofRecipe recipe = ProofManager::currentPM()->getCnfProof()->getProofRecipe(conflictNodes);
-
- unsigned numberOfSteps = recipe.getNumSteps();
-
- prop::SatClause currentClause = *clause;
- std::vector<Expr> currentClauseExpr = conflict;
-
- for (unsigned i = 0; i < numberOfSteps; ++i) {
- const LemmaProofRecipe::ProofStep* currentStep = recipe.getStep(i);
-
- if (currentStep->getTheory() != theory::THEORY_BV) {
- continue;
- }
-
- // If any rewrites took place, we need to update the conflict clause accordingly
- std::set<Node> missingAssertions = recipe.getMissingAssertionsForStep(i);
- std::map<Node, Node> explanationToMissingAssertion;
- std::set<Node>::iterator assertionIt;
- for (assertionIt = missingAssertions.begin();
- assertionIt != missingAssertions.end();
- ++assertionIt) {
- Node negated = (*assertionIt).negate();
- explanationToMissingAssertion[recipe.getExplanation(negated)] = negated;
- }
-
- currentClause = *clause;
- currentClauseExpr = conflict;
-
- for (unsigned j = 0; j < i; ++j) {
- // Literals already used in previous steps need to be negated
- Node previousLiteralNode = recipe.getStep(j)->getLiteral();
-
- // If this literal is the result of a rewrite, we need to translate it
- if (explanationToMissingAssertion.find(previousLiteralNode) !=
- explanationToMissingAssertion.end()) {
- previousLiteralNode = explanationToMissingAssertion[previousLiteralNode];
- }
-
- Node previousLiteralNodeNegated = previousLiteralNode.negate();
- prop::SatLiteral previousLiteralNegated =
- ProofManager::currentPM()->getCnfProof()->getLiteral(previousLiteralNodeNegated);
-
- currentClause.push_back(previousLiteralNegated);
- currentClauseExpr.push_back(previousLiteralNodeNegated.toExpr());
- }
-
- // If we're in the final step, the last literal is Null and should not be added.
- // Otherwise, the current literal does NOT need to be negated
- Node currentLiteralNode = currentStep->getLiteral();
-
- if (currentLiteralNode != Node()) {
- prop::SatLiteral currentLiteral =
- ProofManager::currentPM()->getCnfProof()->getLiteral(currentLiteralNode);
-
- currentClause.push_back(currentLiteral);
- currentClauseExpr.push_back(currentLiteralNode.toExpr());
- }
-
- bv_lemmas.push_back(utils::mkSortedExpr(kind::OR, currentClauseExpr));
- }
- }
-
- proof::BitVectorProof* bv = ProofManager::getBitVectorProof();
- bv->finalizeConflicts(bv_lemmas);
-}
-
-void LFSCTheoryProofEngine::printTheoryLemmas(const IdToSatClause& lemmas,
- std::ostream& os,
- std::ostream& paren,
- ProofLetMap& map) {
- os << " ;; Theory Lemmas \n";
- Debug("pf::tp") << "LFSCTheoryProofEngine::printTheoryLemmas: starting" << std::endl;
-
- if (Debug.isOn("pf::dumpLemmas")) {
- dumpTheoryLemmas(lemmas);
- }
-
- // finalizeBvConflicts(lemmas, os, paren, map);
- ProofManager::getBitVectorProof()->printBBDeclarationAndCnf(os, paren, map);
-
- if (options::bitblastMode() == options::BitblastMode::EAGER)
- {
- Assert(lemmas.size() == 1);
- // nothing more to do (no combination with eager so far)
- return;
- }
-
- ProofManager* pm = ProofManager::currentPM();
- Debug("pf::tp") << "LFSCTheoryProofEngine::printTheoryLemmas: printing lemmas..." << std::endl;
-
- for (IdToSatClause::const_iterator it = lemmas.begin(); it != lemmas.end(); ++it) {
- ClauseId id = it->first;
- const prop::SatClause* clause = it->second;
-
- Debug("pf::tp") << "LFSCTheoryProofEngine::printTheoryLemmas: printing lemma. ID = "
- << id << std::endl;
-
- std::vector<Expr> clause_expr;
- std::set<Node> clause_expr_nodes;
- for(unsigned i = 0; i < clause->size(); ++i) {
- prop::SatLiteral lit = (*clause)[i];
- Node node = pm->getCnfProof()->getAtom(lit.getSatVariable());
- Expr atom = node.toExpr();
- if (atom.isConst()) {
- Assert(atom == utils::mkTrue());
- continue;
- }
- Expr expr_lit = lit.isNegated() ? atom.notExpr(): atom;
- clause_expr.push_back(expr_lit);
- clause_expr_nodes.insert(lit.isNegated() ? node.notNode() : node);
- }
-
- LemmaProofRecipe recipe = pm->getCnfProof()->getProofRecipe(clause_expr_nodes);
-
- if (recipe.simpleLemma()) {
- // In a simple lemma, there will be no propositional resolution in the end
-
- Debug("pf::tp") << "Simple lemma" << std::endl;
- // Printing the clause as it appears in resolution proof
- os << "(satlem _ _ ";
- std::ostringstream clause_paren;
- pm->getCnfProof()->printClause(*clause, os, clause_paren);
-
- // Find and handle missing assertions, due to rewrites
- std::set<Node> missingAssertions = recipe.getMissingAssertionsForStep(0);
- if (!missingAssertions.empty()) {
- Debug("pf::tp") << "Have missing assertions for this simple lemma!" << std::endl;
- }
-
- std::set<Node>::const_iterator missingAssertion;
- for (missingAssertion = missingAssertions.begin();
- missingAssertion != missingAssertions.end();
- ++missingAssertion) {
-
- Debug("pf::tp") << "Working on missing assertion: " << *missingAssertion << std::endl;
- Assert(recipe.wasRewritten(missingAssertion->negate()));
- Node explanation = recipe.getExplanation(missingAssertion->negate()).negate();
- Debug("pf::tp") << "Found explanation: " << explanation << std::endl;
-
- // We have a missing assertion.
- // rewriteIt->first is the assertion after the rewrite (the explanation),
- // rewriteIt->second is the original assertion that needs to be fed into the theory.
-
- bool found = false;
- unsigned k;
- for (k = 0; k < clause_expr.size(); ++k) {
- if (clause_expr[k] == explanation.toExpr()) {
- found = true;
- break;
- }
- }
-
- AlwaysAssert(found);
- Debug("pf::tp") << "Replacing theory assertion "
- << clause_expr[k]
- << " with "
- << *missingAssertion
- << std::endl;
-
- clause_expr[k] = missingAssertion->toExpr();
-
- std::ostringstream rewritten;
-
- if (missingAssertion->getKind() == kind::NOT && (*missingAssertion)[0].toExpr() == utils::mkFalse()) {
- rewritten << "(or_elim_2 _ _ ";
- rewritten << "(not_not_intro _ ";
- rewritten << pm->getLitName(explanation);
- rewritten << ") (iff_elim_2 _ _ ";
- rewritten << d_assertionToRewrite[missingAssertion->negate()];
- rewritten << "))";
- }
- else {
- rewritten << "(or_elim_1 _ _ ";
- rewritten << "(not_not_intro _ ";
- rewritten << pm->getLitName(explanation);
- rewritten << ") (iff_elim_1 _ _ ";
- rewritten << d_assertionToRewrite[missingAssertion->negate()];
- rewritten << "))";
- }
-
- Debug("pf::tp") << "Setting a rewrite filter for this proof: " << std::endl
- << pm->getLitName(*missingAssertion) << " --> " << rewritten.str()
- << ", explanation = " << explanation
- << std::endl << std::endl;
-
- pm->addRewriteFilter(pm->getLitName(*missingAssertion), rewritten.str());
- }
-
- // Query the appropriate theory for a proof of this clause
- theory::TheoryId theory_id = getTheoryForLemma(clause);
- Debug("pf::tp") << "Get theory lemma from " << theory_id << "..." << std::endl;
- getTheoryProof(theory_id)->printTheoryLemmaProof(clause_expr, os, paren, map);
-
- // Turn rewrite filter OFF
- pm->clearRewriteFilters();
-
- Debug("pf::tp") << "Get theory lemma from " << theory_id << "... DONE!" << std::endl;
- os << clause_paren.str();
- os << "( \\ " << pm->getLemmaClauseName(id) <<"\n";
- paren << "))";
- } else { // This is a composite lemma
-
- unsigned numberOfSteps = recipe.getNumSteps();
- prop::SatClause currentClause = *clause;
- std::vector<Expr> currentClauseExpr = clause_expr;
-
- for (unsigned i = 0; i < numberOfSteps; ++i) {
- const LemmaProofRecipe::ProofStep* currentStep = recipe.getStep(i);
-
- currentClause = *clause;
- currentClauseExpr = clause_expr;
-
- for (unsigned j = 0; j < i; ++j) {
- // Literals already used in previous steps need to be negated
- Node previousLiteralNode = recipe.getStep(j)->getLiteral();
- Node previousLiteralNodeNegated = previousLiteralNode.negate();
- prop::SatLiteral previousLiteralNegated =
- ProofManager::currentPM()->getCnfProof()->getLiteral(previousLiteralNodeNegated);
- currentClause.push_back(previousLiteralNegated);
- currentClauseExpr.push_back(previousLiteralNodeNegated.toExpr());
- }
-
- // If the current literal is NULL, can ignore (final step)
- // Otherwise, the current literal does NOT need to be negated
- Node currentLiteralNode = currentStep->getLiteral();
- if (currentLiteralNode != Node()) {
- prop::SatLiteral currentLiteral =
- ProofManager::currentPM()->getCnfProof()->getLiteral(currentLiteralNode);
-
- currentClause.push_back(currentLiteral);
- currentClauseExpr.push_back(currentLiteralNode.toExpr());
- }
-
- os << "(satlem _ _ ";
- std::ostringstream clause_paren;
-
- pm->getCnfProof()->printClause(currentClause, os, clause_paren);
-
- // query appropriate theory for proof of clause
- theory::TheoryId theory_id = currentStep->getTheory();
- Debug("pf::tp") << "Get theory lemma from " << theory_id << "..." << std::endl;
-
- std::set<Node> missingAssertions = recipe.getMissingAssertionsForStep(i);
- if (!missingAssertions.empty()) {
- Debug("pf::tp") << "Have missing assertions for this step!" << std::endl;
- }
-
- // Turn rewrite filter ON
- std::set<Node>::const_iterator missingAssertion;
- for (missingAssertion = missingAssertions.begin();
- missingAssertion != missingAssertions.end();
- ++missingAssertion) {
-
- Debug("pf::tp") << "Working on missing assertion: " << *missingAssertion << std::endl;
-
- Assert(recipe.wasRewritten(missingAssertion->negate()));
- Node explanation = recipe.getExplanation(missingAssertion->negate()).negate();
-
- Debug("pf::tp") << "Found explanation: " << explanation << std::endl;
-
- // We have a missing assertion.
- // rewriteIt->first is the assertion after the rewrite (the explanation),
- // rewriteIt->second is the original assertion that needs to be fed into the theory.
-
- bool found = false;
- unsigned k;
- for (k = 0; k < currentClauseExpr.size(); ++k) {
- if (currentClauseExpr[k] == explanation.toExpr()) {
- found = true;
- break;
- }
- }
-
- AlwaysAssert(found);
-
- Debug("pf::tp") << "Replacing theory assertion "
- << currentClauseExpr[k]
- << " with "
- << *missingAssertion
- << std::endl;
-
- currentClauseExpr[k] = missingAssertion->toExpr();
-
- std::ostringstream rewritten;
-
- if (missingAssertion->getKind() == kind::NOT && (*missingAssertion)[0].toExpr() == utils::mkFalse()) {
- rewritten << "(or_elim_2 _ _ ";
- rewritten << "(not_not_intro _ ";
- rewritten << pm->getLitName(explanation);
- rewritten << ") (iff_elim_2 _ _ ";
- rewritten << d_assertionToRewrite[missingAssertion->negate()];
- rewritten << "))";
- }
- else {
- rewritten << "(or_elim_1 _ _ ";
- rewritten << "(not_not_intro _ ";
- rewritten << pm->getLitName(explanation);
- rewritten << ") (iff_elim_1 _ _ ";
- rewritten << d_assertionToRewrite[missingAssertion->negate()];
- rewritten << "))";
- }
-
- Debug("pf::tp") << "Setting a rewrite filter for this proof: " << std::endl
- << pm->getLitName(*missingAssertion) << " --> " << rewritten.str()
- << "explanation = " << explanation
- << std::endl << std::endl;
-
- pm->addRewriteFilter(pm->getLitName(*missingAssertion), rewritten.str());
- }
-
- getTheoryProof(theory_id)->printTheoryLemmaProof(currentClauseExpr, os, paren, map);
-
- // Turn rewrite filter OFF
- pm->clearRewriteFilters();
-
- Debug("pf::tp") << "Get theory lemma from " << theory_id << "... DONE!" << std::endl;
- os << clause_paren.str();
- os << "( \\ " << pm->getLemmaClauseName(id) << "s" << i <<"\n";
- paren << "))";
- }
-
- Assert(numberOfSteps >= 2);
-
- os << "(satlem_simplify _ _ _ ";
- for (unsigned i = 0; i < numberOfSteps - 1; ++i) {
- // Resolve step i with step i + 1
- if (recipe.getStep(i)->getLiteral().getKind() == kind::NOT) {
- os << "(Q _ _ ";
- } else {
- os << "(R _ _ ";
- }
-
- os << pm->getLemmaClauseName(id) << "s" << i;
- os << " ";
- }
-
- os << pm->getLemmaClauseName(id) << "s" << numberOfSteps - 1 << " ";
-
- prop::SatLiteral v;
- for (int i = numberOfSteps - 2; i >= 0; --i) {
- v = ProofManager::currentPM()->getCnfProof()->getLiteral(recipe.getStep(i)->getLiteral());
- os << ProofManager::getVarName(v.getSatVariable(), "") << ") ";
- }
-
- os << "( \\ " << pm->getLemmaClauseName(id) << "\n";
- paren << "))";
- }
- }
-}
-
-void LFSCTheoryProofEngine::printBoundTermAsType(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType)
-{
- Debug("pf::tp") << "LFSCTheoryProofEngine::printBoundTerm( " << term << " ) " << std::endl;
-
- // Since let-abbreviated terms are abbreviated with their default type, only
- // use the let map if there is no expectedType or the expectedType matches
- // the default.
- if (expectedType.isNull()
- || TypeNode::fromType(term.getType()) == expectedType)
- {
- ProofLetMap::const_iterator it = map.find(term);
- if (it != map.end())
- {
- unsigned id = it->second.id;
- unsigned count = it->second.count;
-
- if (count > LET_COUNT)
- {
- os << "let" << id;
- Debug("pf::tp::letmap") << "Using let map for " << term << std::endl;
- return;
- }
- }
- }
- Debug("pf::tp::letmap") << "Skipping let map for " << term << std::endl;
-
- printTheoryTerm(term, os, map, expectedType);
-}
-
-void LFSCTheoryProofEngine::printBoundFormula(Expr term,
- std::ostream& os,
- const ProofLetMap& map)
-{
- Assert(term.getType().isBoolean() or term.getType().isPredicate());
- bool wrapWithBoolToPred = term.getType().isBoolean() and printsAsBool(term);
- if (wrapWithBoolToPred)
- {
- os << "(p_app ";
- }
- printBoundTerm(term, os, map);
- if (wrapWithBoolToPred)
- {
- os << ")";
- }
-}
-
-void LFSCTheoryProofEngine::printCoreTerm(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType)
-{
- if (term.isVariable()) {
- os << ProofManager::sanitize(term);
- return;
- }
-
- Kind k = term.getKind();
-
- switch(k) {
- case kind::ITE: {
- TypeNode armType = expectedType.isNull()
- ? TypeNode::fromType(term.getType())
- : expectedType;
- bool useFormulaType = term.getType().isBoolean();
- Assert(term[1].getType().isSubtypeOf(term.getType()));
- Assert(term[2].getType().isSubtypeOf(term.getType()));
- os << (useFormulaType ? "(ifte " : "(ite _ ");
-
- printBoundFormula(term[0], os, map);
- os << " ";
- if (useFormulaType)
- {
- printBoundFormula(term[1], os, map);
- }
- else
- {
- printBoundTerm(term[1], os, map, armType);
- }
- os << " ";
- if (useFormulaType)
- {
- printBoundFormula(term[2], os, map);
- }
- else
- {
- printBoundTerm(term[2], os, map, armType);
- }
- os << ")";
- return;
- }
-
- case kind::EQUAL: {
- bool booleanCase = term[0].getType().isBoolean();
- TypeNode armType = equalityType(term[0], term[1]);
-
- os << "(";
- if (booleanCase) {
- os << "iff ";
- } else {
- os << "= ";
- printSort(term[0].getType(), os);
- os << " ";
- }
-
- if (booleanCase && printsAsBool(term[0])) os << "(p_app ";
- printBoundTerm(term[0], os, map, armType);
- if (booleanCase && printsAsBool(term[0])) os << ")";
-
- os << " ";
-
- if (booleanCase && printsAsBool(term[1])) os << "(p_app ";
- printBoundTerm(term[1], os, map, armType);
- if (booleanCase && printsAsBool(term[1])) os << ") ";
- os << ")";
-
- return;
- }
-
- case kind::DISTINCT:
- {
- // Distinct nodes can have any number of chidlren.
- Assert(term.getNumChildren() >= 2);
- TypeNode armType = equalityType(term[0], term[1]);
-
- if (term.getNumChildren() == 2) {
- os << "(not (= ";
- printSort(term[0].getType(), os);
- os << " ";
- printBoundTerm(term[0], os, map, armType);
- os << " ";
- printBoundTerm(term[1], os, map, armType);
- os << "))";
- } else {
- unsigned numOfPairs = term.getNumChildren() * (term.getNumChildren() - 1) / 2;
- for (unsigned i = 1; i < numOfPairs; ++i) {
- os << "(and ";
- }
-
- for (unsigned i = 0; i < term.getNumChildren(); ++i) {
- for (unsigned j = i + 1; j < term.getNumChildren(); ++j) {
- armType = equalityType(term[i], term[j]);
- if ((i != 0) || (j != 1)) {
- os << "(not (= ";
- printSort(term[0].getType(), os);
- os << " ";
- printBoundTerm(term[i], os, map, armType);
- os << " ";
- printBoundTerm(term[j], os, map, armType);
- os << ")))";
- } else {
- os << "(not (= ";
- printSort(term[0].getType(), os);
- os << " ";
- printBoundTerm(term[0], os, map, armType);
- os << " ";
- printBoundTerm(term[1], os, map, armType);
- os << "))";
- }
- }
- }
- }
- return;
- }
-
- default: Unhandled() << k;
- }
-}
-
-void TheoryProof::printTheoryLemmaProof(std::vector<Expr>& lemma,
- std::ostream& os,
- std::ostream& paren,
- const ProofLetMap& map) {
- // Default method for replaying proofs: assert (negated) literals back to a fresh copy of the theory
- Assert(d_theory != NULL);
-
- context::UserContext fakeContext;
- ProofOutputChannel oc;
- theory::Valuation v(NULL);
- //make new copy of theory
- theory::Theory* th;
- Trace("pf::tp") << ";; Print theory lemma proof, theory id = " << d_theory->getId() << std::endl;
-
- if (d_theory->getId()==theory::THEORY_UF) {
- th = new theory::uf::TheoryUF(&fakeContext,
- &fakeContext,
- oc,
- v,
- ProofManager::currentPM()->getLogicInfo(),
- nullptr,
- "replay::");
- } else if (d_theory->getId()==theory::THEORY_ARRAYS) {
- th = new theory::arrays::TheoryArrays(
- &fakeContext,
- &fakeContext,
- oc,
- v,
- ProofManager::currentPM()->getLogicInfo(),
- nullptr,
- "replay::");
- } else if (d_theory->getId() == theory::THEORY_ARITH) {
- Trace("theory-proof-debug") << "Arith proofs currently not supported. Use 'trust'" << std::endl;
- os << " (clausify_false trust)";
- return;
- } else {
- InternalError() << "can't generate theory-proof for "
- << ProofManager::currentPM()->getLogic();
- }
- // must perform initialization on the theory
- if (th != nullptr)
- {
- // finish init, standalone version
- th->finishInitStandalone();
- }
-
- Debug("pf::tp") << "TheoryProof::printTheoryLemmaProof - calling th->ProduceProofs()" << std::endl;
- th->produceProofs();
- Debug("pf::tp") << "TheoryProof::printTheoryLemmaProof - th->ProduceProofs() DONE" << std::endl;
-
- MyPreRegisterVisitor preRegVisitor(th);
- for (unsigned i=0; i<lemma.size(); i++) {
- Node strippedLit = (lemma[i].getKind() == kind::NOT) ? lemma[i][0] : lemma[i];
- if (strippedLit.getKind() == kind::EQUAL ||
- d_theory->getId() == theory::Theory::theoryOf(strippedLit)) {
- Node lit = Node::fromExpr( lemma[i] ).negate();
- Trace("pf::tp") << "; preregistering and asserting " << lit << std::endl;
- NodeVisitor<MyPreRegisterVisitor>::run(preRegVisitor, lit);
- th->assertFact(lit, false);
- }
- }
-
- Debug("pf::tp") << "TheoryProof::printTheoryLemmaProof - calling th->check()" << std::endl;
- th->check(theory::Theory::EFFORT_FULL);
- Debug("pf::tp") << "TheoryProof::printTheoryLemmaProof - th->check() DONE" << std::endl;
-
- if(!oc.hasConflict()) {
- Trace("pf::tp") << "; conflict is null" << std::endl;
- Node lastLemma = oc.getLastLemma();
- Assert(!lastLemma.isNull());
- Trace("pf::tp") << "; ++ but got lemma: " << lastLemma << std::endl;
-
- if (lastLemma.getKind() == kind::OR) {
- Debug("pf::tp") << "OR lemma. Negating each child separately" << std::endl;
- for (unsigned i = 0; i < lastLemma.getNumChildren(); ++i) {
- if (lastLemma[i].getKind() == kind::NOT) {
- Trace("pf::tp") << "; asserting fact: " << lastLemma[i][0] << std::endl;
- th->assertFact(lastLemma[i][0], false);
- }
- else {
- Trace("pf::tp") << "; asserting fact: " << lastLemma[i].notNode() << std::endl;
- th->assertFact(lastLemma[i].notNode(), false);
- }
- }
- } else {
- Unreachable();
-
- Assert(oc.getLastLemma().getKind() == kind::NOT);
- Debug("pf::tp") << "NOT lemma" << std::endl;
- Trace("pf::tp") << "; asserting fact: " << oc.getLastLemma()[0]
- << std::endl;
- th->assertFact(oc.getLastLemma()[0], false);
- }
-
- // Trace("pf::tp") << "; ++ but got lemma: " << oc.d_lemma << std::endl;
- // Trace("pf::tp") << "; asserting " << oc.d_lemma[1].negate() << std::endl;
- // th->assertFact(oc.d_lemma[1].negate(), false);
-
- //
- th->check(theory::Theory::EFFORT_FULL);
- } else {
- Debug("pf::tp") << "Calling oc.d_proof->toStream(os)" << std::endl;
- oc.getConflictProof().toStream(os, map);
- Debug("pf::tp") << "Calling oc.d_proof->toStream(os) -- DONE!" << std::endl;
- }
-
- Debug("pf::tp") << "About to delete the theory solver used for proving the lemma... " << std::endl;
- delete th;
- Debug("pf::tp") << "About to delete the theory solver used for proving the lemma: DONE! " << std::endl;
-}
-
-bool TheoryProofEngine::supportedTheory(theory::TheoryId id) {
- return (id == theory::THEORY_ARRAYS ||
- id == theory::THEORY_ARITH ||
- id == theory::THEORY_BV ||
- id == theory::THEORY_UF ||
- id == theory::THEORY_BOOL);
-}
-
-bool TheoryProofEngine::printsAsBool(const Node &n) {
- if (!n.getType().isBoolean()) {
- return false;
- }
-
- theory::TheoryId theory_id = theory::Theory::theoryOf(n);
- return getTheoryProof(theory_id)->printsAsBool(n);
-}
-
-BooleanProof::BooleanProof(TheoryProofEngine* proofEngine)
- : TheoryProof(NULL, proofEngine)
-{}
-
-void BooleanProof::registerTerm(Expr term) {
- Assert(term.getType().isBoolean());
-
- if (term.isVariable() && d_declarations.find(term) == d_declarations.end()) {
- d_declarations.insert(term);
- return;
- }
- for (unsigned i = 0; i < term.getNumChildren(); ++i) {
- d_proofEngine->registerTerm(term[i]);
- }
-}
-
-theory::TheoryId BooleanProof::getTheoryId() { return theory::THEORY_BOOL; }
-void LFSCBooleanProof::printConstantDisequalityProof(std::ostream& os, Expr c1, Expr c2, const ProofLetMap &globalLetMap) {
- Node falseNode = NodeManager::currentNM()->mkConst(false);
- Node trueNode = NodeManager::currentNM()->mkConst(true);
-
- Assert(c1 == falseNode.toExpr() || c1 == trueNode.toExpr());
- Assert(c2 == falseNode.toExpr() || c2 == trueNode.toExpr());
- Assert(c1 != c2);
-
- if (c1 == trueNode.toExpr())
- os << "t_t_neq_f";
- else
- os << "(negsymm _ _ _ t_t_neq_f)";
-}
-
-void LFSCBooleanProof::printOwnedTermAsType(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType)
-{
- Assert(term.getType().isBoolean());
- if (term.isVariable()) {
- os << ProofManager::sanitize(term);
- return;
- }
-
- Kind k = term.getKind();
- switch(k) {
- case kind::OR:
- case kind::AND:
- if (options::lfscLetification() && term.getNumChildren() > 2) {
- // If letification is on, the entire term is probably a let expression.
- // However, we need to transform it from (and a b c) into (and a (and b c)) form first.
- Node currentExpression = term[term.getNumChildren() - 1];
- for (int i = term.getNumChildren() - 2; i >= 0; --i) {
- NodeBuilder<> builder(k);
- builder << term[i];
- builder << currentExpression.toExpr();
- currentExpression = builder;
- }
-
- // The let map should already have the current expression.
- ProofLetMap::const_iterator it = map.find(currentExpression.toExpr());
- if (it != map.end()) {
- unsigned id = it->second.id;
- unsigned count = it->second.count;
-
- if (count > LET_COUNT) {
- os << "let" << id;
- break;
- }
- }
- }
-
- // If letification is off or there were 2 children, same treatment as the other cases.
- CVC4_FALLTHROUGH;
- case kind::XOR:
- case kind::IMPLIES:
- case kind::NOT:
- // print the Boolean operators
- os << "(" << utils::toLFSCKind(k);
- if(term.getNumChildren() > 2) {
- // LFSC doesn't allow declarations with variable numbers of
- // arguments, so we have to flatten these N-ary versions.
- std::ostringstream paren;
- os << " ";
- for (unsigned i = 0; i < term.getNumChildren(); ++i) {
-
- if (printsAsBool(term[i])) os << "(p_app ";
- d_proofEngine->printBoundTerm(term[i], os, map);
- if (printsAsBool(term[i])) os << ")";
-
- os << " ";
- if(i < term.getNumChildren() - 2) {
- os << "(" << utils::toLFSCKind(k) << " ";
- paren << ")";
- }
- }
- os << paren.str() << ")";
- } else {
- // this is for binary and unary operators
- for (unsigned i = 0; i < term.getNumChildren(); ++i) {
- os << " ";
- if (printsAsBool(term[i])) os << "(p_app ";
- d_proofEngine->printBoundTerm(term[i], os, map);
- if (printsAsBool(term[i])) os << ")";
- }
- os << ")";
- }
- return;
-
- case kind::CONST_BOOLEAN:
- os << (term.getConst<bool>() ? "true" : "false");
- return;
-
- default: Unhandled() << k;
- }
-}
-
-void LFSCBooleanProof::printOwnedSort(Type type, std::ostream& os) {
- Assert(type.isBoolean());
- os << "Bool";
-}
-
-void LFSCBooleanProof::printSortDeclarations(std::ostream& os, std::ostream& paren) {
- // Nothing to do here at this point.
-}
-
-void LFSCBooleanProof::printTermDeclarations(std::ostream& os, std::ostream& paren) {
- for (ExprSet::const_iterator it = d_declarations.begin(); it != d_declarations.end(); ++it) {
- Expr term = *it;
-
- os << "(% " << ProofManager::sanitize(term) << " (term ";
- printSort(term.getType(), os);
- os <<")\n";
- paren <<")";
- }
-}
-
-void LFSCBooleanProof::printDeferredDeclarations(std::ostream& os, std::ostream& paren) {
- // Nothing to do here at this point.
-}
-
-void LFSCBooleanProof::printAliasingDeclarations(std::ostream& os, std::ostream& paren, const ProofLetMap &globalLetMap) {
- // Nothing to do here at this point.
-}
-
-void LFSCBooleanProof::printTheoryLemmaProof(std::vector<Expr>& lemma,
- std::ostream& os,
- std::ostream& paren,
- const ProofLetMap& map) {
- Unreachable() << "No boolean lemmas yet!";
-}
-
-bool LFSCBooleanProof::printsAsBool(const Node &n)
-{
- Kind k = n.getKind();
- switch (k) {
- case kind::BOOLEAN_TERM_VARIABLE:
- case kind::VARIABLE:
- return true;
-
- default:
- return false;
- }
-}
-
-void TheoryProof::printConstantDisequalityProof(std::ostream& os, Expr c1, Expr c2, const ProofLetMap &globalLetMap) {
- // By default, we just print a trust statement. Specific theories can implement
- // better proofs.
-
- os << "(trust_f (not (= _ ";
- d_proofEngine->printBoundTerm(c1, os, globalLetMap);
- os << " ";
- d_proofEngine->printBoundTerm(c2, os, globalLetMap);
- os << ")))";
-}
-
-void TheoryProof::printRewriteProof(std::ostream& os, const Node &n1, const Node &n2) {
- // This is the default for a rewrite proof: just a trust statement.
- ProofLetMap emptyMap;
- os << "(trust_f (iff ";
- d_proofEngine->printBoundTerm(n1.toExpr(), os, emptyMap);
- os << " ";
- d_proofEngine->printBoundTerm(n2.toExpr(), os, emptyMap);
- os << "))";
-}
-
-void TheoryProof::printOwnedTerm(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType)
-{
- this->printOwnedTermAsType(term, os, map, expectedType);
-}
-
-TypeNode TheoryProof::equalityType(const Expr& left, const Expr& right)
-{
- Assert(left.getType() == right.getType())
- << "TheoryProof::equalityType(" << left << ", " << right << "):" << std::endl
- << "types disagree:" << std::endl
- << "\tleft: " << left.getType() << std::endl
- << "\tright:" << right.getType();
- return TypeNode::fromType(left.getType());
-}
-
-bool TheoryProof::match(TNode n1, TNode n2)
-{
- theory::TheoryId theoryId = this->getTheoryId();
- ProofManager* pm = ProofManager::currentPM();
- bool ufProof = (theoryId == theory::THEORY_UF);
- Debug(ufProof ? "pf::uf" : "mgd") << "match " << n1 << " " << n2 << std::endl;
- if (pm->hasOp(n1))
- {
- n1 = pm->lookupOp(n1);
- }
- if (pm->hasOp(n2))
- {
- n2 = pm->lookupOp(n2);
- }
- Debug(ufProof ? "pf::uf" : "mgd") << "+ match " << n1 << " " << n2
- << std::endl;
- if (!ufProof)
- {
- Debug("pf::array") << "+ match: step 1" << std::endl;
- }
- if (n1 == n2)
- {
- return true;
- }
-
- if (n1.getType().isFunction() && n2.hasOperator())
- {
- if (pm->hasOp(n2.getOperator()))
- {
- return n1 == pm->lookupOp(n2.getOperator());
- }
- else
- {
- return n1 == n2.getOperator();
- }
- }
-
- if (n2.getType().isFunction() && n1.hasOperator())
- {
- if (pm->hasOp(n1.getOperator()))
- {
- return n2 == pm->lookupOp(n1.getOperator());
- }
- else
- {
- return n2 == n1.getOperator();
- }
- }
-
- if (n1.hasOperator() && n2.hasOperator()
- && n1.getOperator() != n2.getOperator())
- {
- if (ufProof
- || !((n1.getKind() == kind::SELECT
- && n2.getKind() == kind::PARTIAL_SELECT_0)
- || (n1.getKind() == kind::SELECT
- && n2.getKind() == kind::PARTIAL_SELECT_1)
- || (n1.getKind() == kind::PARTIAL_SELECT_1
- && n2.getKind() == kind::SELECT)
- || (n1.getKind() == kind::PARTIAL_SELECT_1
- && n2.getKind() == kind::PARTIAL_SELECT_0)
- || (n1.getKind() == kind::PARTIAL_SELECT_0
- && n2.getKind() == kind::SELECT)
- || (n1.getKind() == kind::PARTIAL_SELECT_0
- && n2.getKind() == kind::PARTIAL_SELECT_1)))
- {
- return false;
- }
- }
-
- for (size_t i = 0; i < n1.getNumChildren() && i < n2.getNumChildren(); ++i)
- {
- if (n1[i] != n2[i])
- {
- return false;
- }
- }
-
- return true;
-}
-
-int TheoryProof::assertAndPrint(
- const theory::eq::EqProof& pf,
- const ProofLetMap& map,
- std::shared_ptr<theory::eq::EqProof> subTrans,
- theory::eq::EqProof::PrettyPrinter* pPrettyPrinter)
-{
- theory::TheoryId theoryId = getTheoryId();
- int neg = -1;
- Assert(theoryId == theory::THEORY_UF || theoryId == theory::THEORY_ARRAYS);
- bool ufProof = (theoryId == theory::THEORY_UF);
- std::string theoryName = theory::getStatsPrefix(theoryId);
- pf.debug_print(("pf::" + theoryName).c_str(), 0, pPrettyPrinter);
- Debug("pf::" + theoryName) << std::endl;
-
- Assert(pf.d_id == theory::eq::MERGED_THROUGH_TRANS);
- Assert(!pf.d_node.isNull());
- Assert(pf.d_children.size() >= 2);
-
- subTrans->d_id = theory::eq::MERGED_THROUGH_TRANS;
- subTrans->d_node = pf.d_node;
-
- size_t i = 0;
- while (i < pf.d_children.size())
- {
- // special treatment for uf and not for array
- if (ufProof
- || pf.d_children[i]->d_id != theory::eq::MERGED_THROUGH_CONGRUENCE)
- {
- pf.d_children[i]->d_node = simplifyBooleanNode(pf.d_children[i]->d_node);
- }
-
- // Look for the negative clause, with which we will form a contradiction.
- if (!pf.d_children[i]->d_node.isNull()
- && pf.d_children[i]->d_node.getKind() == kind::NOT)
- {
- Assert(neg < 0);
- (neg) = i;
- ++i;
- }
-
- // Handle congruence closures over equalities.
- else if (pf.d_children[i]->d_id == theory::eq::MERGED_THROUGH_CONGRUENCE
- && pf.d_children[i]->d_node.isNull())
- {
- Debug("pf::" + theoryName) << "Handling congruence over equalities"
- << std::endl;
-
- // Gather the sequence of consecutive congruence closures.
- std::vector<std::shared_ptr<const theory::eq::EqProof>>
- congruenceClosures;
- unsigned count;
- Debug("pf::" + theoryName) << "Collecting congruence sequence"
- << std::endl;
- for (count = 0; i + count < pf.d_children.size()
- && pf.d_children[i + count]->d_id
- == theory::eq::MERGED_THROUGH_CONGRUENCE
- && pf.d_children[i + count]->d_node.isNull();
- ++count)
- {
- Debug("pf::" + theoryName) << "Found a congruence: " << std::endl;
- pf.d_children[i + count]->debug_print(
- ("pf::" + theoryName).c_str(), 0, pPrettyPrinter);
- congruenceClosures.push_back(pf.d_children[i + count]);
- }
-
- Debug("pf::" + theoryName)
- << "Total number of congruences found: " << congruenceClosures.size()
- << std::endl;
-
- // Determine if the "target" of the congruence sequence appears right
- // before or right after the sequence.
- bool targetAppearsBefore = true;
- bool targetAppearsAfter = true;
-
- if ((i == 0) || (i == 1 && neg == 0))
- {
- Debug("pf::" + theoryName) << "Target does not appear before"
- << std::endl;
- targetAppearsBefore = false;
- }
-
- if ((i + count >= pf.d_children.size())
- || (!pf.d_children[i + count]->d_node.isNull()
- && pf.d_children[i + count]->d_node.getKind() == kind::NOT))
- {
- Debug("pf::" + theoryName) << "Target does not appear after"
- << std::endl;
- targetAppearsAfter = false;
- }
-
- // Flow changes between uf and array
- if (ufProof)
- {
- // Assert that we have precisely at least one possible clause.
- Assert(targetAppearsBefore || targetAppearsAfter);
-
- // If both are valid, assume the one after the sequence is correct
- if (targetAppearsAfter && targetAppearsBefore)
- {
- targetAppearsBefore = false;
- }
- }
- else
- { // not a uf proof
- // Assert that we have precisely one target clause.
- Assert(targetAppearsBefore != targetAppearsAfter);
- }
-
- // Begin breaking up the congruences and ordering the equalities
- // correctly.
- std::vector<std::shared_ptr<theory::eq::EqProof>> orderedEqualities;
-
- // Insert target clause first.
- if (targetAppearsBefore)
- {
- orderedEqualities.push_back(pf.d_children[i - 1]);
- // The target has already been added to subTrans; remove it.
- subTrans->d_children.pop_back();
- }
- else
- {
- orderedEqualities.push_back(pf.d_children[i + count]);
- }
-
- // Start with the congruence closure closest to the target clause, and
- // work our way back/forward.
- if (targetAppearsBefore)
- {
- for (unsigned j = 0; j < count; ++j)
- {
- if (pf.d_children[i + j]->d_children[0]->d_id
- != theory::eq::MERGED_THROUGH_REFLEXIVITY)
- orderedEqualities.insert(orderedEqualities.begin(),
- pf.d_children[i + j]->d_children[0]);
- if (pf.d_children[i + j]->d_children[1]->d_id
- != theory::eq::MERGED_THROUGH_REFLEXIVITY)
- orderedEqualities.insert(orderedEqualities.end(),
- pf.d_children[i + j]->d_children[1]);
- }
- }
- else
- {
- for (unsigned j = 0; j < count; ++j)
- {
- if (pf.d_children[i + count - 1 - j]->d_children[0]->d_id
- != theory::eq::MERGED_THROUGH_REFLEXIVITY)
- orderedEqualities.insert(
- orderedEqualities.begin(),
- pf.d_children[i + count - 1 - j]->d_children[0]);
- if (pf.d_children[i + count - 1 - j]->d_children[1]->d_id
- != theory::eq::MERGED_THROUGH_REFLEXIVITY)
- orderedEqualities.insert(
- orderedEqualities.end(),
- pf.d_children[i + count - 1 - j]->d_children[1]);
- }
- }
-
- // Copy the result into the main transitivity proof.
- subTrans->d_children.insert(subTrans->d_children.end(),
- orderedEqualities.begin(),
- orderedEqualities.end());
-
- // Increase i to skip over the children that have been processed.
- i += count;
- if (targetAppearsAfter)
- {
- ++i;
- }
- }
-
- // Else, just copy the child proof as is
- else
- {
- subTrans->d_children.push_back(pf.d_children[i]);
- ++i;
- }
- }
-
- bool disequalityFound = (neg >= 0);
- if (!disequalityFound)
- {
- Debug("pf::" + theoryName)
- << "A disequality was NOT found. UNSAT due to merged constants"
- << std::endl;
- Debug("pf::" + theoryName) << "Proof for: " << pf.d_node << std::endl;
- Assert(pf.d_node.getKind() == kind::EQUAL);
- Assert(pf.d_node.getNumChildren() == 2);
- Assert(pf.d_node[0].isConst() && pf.d_node[1].isConst());
- }
- return neg;
-}
-
-std::pair<Node, Node> TheoryProof::identicalEqualitiesPrinterHelper(
- bool evenLengthSequence,
- bool sequenceOver,
- const theory::eq::EqProof& pf,
- const ProofLetMap& map,
- const std::string subproofStr,
- std::stringstream* outStream,
- Node n,
- Node nodeAfterEqualitySequence)
-{
- theory::TheoryId theoryId = getTheoryId();
- Assert(theoryId == theory::THEORY_UF || theoryId == theory::THEORY_ARRAYS);
- bool ufProof = (theoryId == theory::THEORY_UF);
- std::string theoryName = theory::getStatsPrefix(theoryId);
- if (evenLengthSequence)
- {
- // If the length is even, we need to apply transitivity for the "correct"
- // hand of the equality.
-
- Debug("pf::" + theoryName) << "Equality sequence of even length"
- << std::endl;
- Debug("pf::" + theoryName) << "n1 is: " << n << std::endl;
- Debug("pf::" + theoryName) << "pf-d_node is: " << pf.d_node << std::endl;
- Debug("pf::" + theoryName) << "Next node is: " << nodeAfterEqualitySequence
- << std::endl;
-
- (*outStream) << "(trans _ _ _ _ ";
-
- // If the sequence is at the very end of the transitivity proof, use
- // pf.d_node to guide us.
- if (!sequenceOver)
- {
- if (match(n[0], pf.d_node[0]))
- {
- n = n[0].eqNode(n[0]);
- (*outStream) << subproofStr << " (symm _ _ _ " << subproofStr << ")";
- }
- else if (match(n[1], pf.d_node[1]))
- {
- n = n[1].eqNode(n[1]);
- (*outStream) << " (symm _ _ _ " << subproofStr << ")" << subproofStr;
- }
- else
- {
- Debug("pf::" + theoryName) << "Error: identical equalities over, but "
- "hands don't match what we're proving."
- << std::endl;
- Assert(false);
- }
- }
- else
- {
- // We have a "next node". Use it to guide us.
- if (!ufProof && nodeAfterEqualitySequence.getKind() == kind::NOT)
- {
- nodeAfterEqualitySequence = nodeAfterEqualitySequence[0];
- }
-
- Assert(nodeAfterEqualitySequence.getKind() == kind::EQUAL);
-
- if ((n[0] == nodeAfterEqualitySequence[0])
- || (n[0] == nodeAfterEqualitySequence[1]))
- {
- // Eliminate n[1]
- (*outStream) << subproofStr << " (symm _ _ _ " << subproofStr << ")";
- n = n[0].eqNode(n[0]);
- }
- else if ((n[1] == nodeAfterEqualitySequence[0])
- || (n[1] == nodeAfterEqualitySequence[1]))
- {
- // Eliminate n[0]
- (*outStream) << " (symm _ _ _ " << subproofStr << ")" << subproofStr;
- n = n[1].eqNode(n[1]);
- }
- else
- {
- Debug("pf::" + theoryName) << "Error: even length sequence, but I "
- "don't know which hand to keep!"
- << std::endl;
- Assert(false);
- }
- }
-
- (*outStream) << ")";
- }
- else
- {
- Debug("pf::" + theoryName) << "Equality sequence length is odd!"
- << std::endl;
- (*outStream).str(subproofStr);
- }
-
- Debug("pf::" + theoryName) << "Have proven: " << n << std::endl;
- return std::make_pair<Node&, Node&>(n, nodeAfterEqualitySequence);
-}
-
-} /* namespace CVC4 */
diff --git a/src/proof/theory_proof.h b/src/proof/theory_proof.h
deleted file mode 100644
index dd5fe0326..000000000
--- a/src/proof/theory_proof.h
+++ /dev/null
@@ -1,510 +0,0 @@
-/********************* */
-/*! \file theory_proof.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Liana Hadarean, Guy Katz, Alex Ozdemir
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** [[ Add lengthier description here ]]
-
- ** \todo document this file
-
-**/
-
-#include "cvc4_private.h"
-
-#ifndef CVC4__THEORY_PROOF_H
-#define CVC4__THEORY_PROOF_H
-
-#include <iosfwd>
-#include <unordered_map>
-#include <unordered_set>
-
-#include "expr/expr.h"
-#include "expr/type_node.h"
-#include "proof/clause_id.h"
-#include "proof/proof_utils.h"
-#include "prop/sat_solver_types.h"
-#include "theory/uf/equality_engine.h"
-#include "util/proof.h"
-namespace CVC4 {
-
-namespace theory {
-class Theory;
-} /* namespace CVC4::theory */
-
-typedef std::unordered_map < ClauseId, prop::SatClause* > IdToSatClause;
-
-class TheoryProof;
-
-typedef std::unordered_set<Expr, ExprHashFunction > ExprSet;
-typedef std::map<theory::TheoryId, TheoryProof* > TheoryProofTable;
-
-typedef std::set<theory::TheoryId> TheoryIdSet;
-typedef std::map<Expr, TheoryIdSet> ExprToTheoryIds;
-
-class TheoryProofEngine {
-protected:
- ExprSet d_registrationCache;
- TheoryProofTable d_theoryProofTable;
- ExprToTheoryIds d_exprToTheoryIds;
-
- /**
- * Returns whether the theory is currently supported in proof
- * production mode.
- */
- bool supportedTheory(theory::TheoryId id);
-public:
-
- TheoryProofEngine();
- virtual ~TheoryProofEngine();
-
- /**
- * Print the theory term (could be an atom) by delegating to the proper theory.
- *
- * @param term
- * @param os
- */
- virtual void printLetTerm(Expr term, std::ostream& os) = 0;
-
- /**
- * Print a term in some (core or non-core) theory
- *
- * @param term expression representing term
- * @param os output stream
- * @param expectedType The type that this is expected to have in a parent
- * node. Null if there are no such requirements. This is useful for requesting
- * type conversions from the theory. e.g. in (5.5 == 4) the right-hand-side
- * should be converted to a real.
- *
- * The first version of this function has a default value for expectedType
- * (null) The second version is virtual.
- *
- * They are split to avoid mixing virtual function and default argument
- * values, which behave weirdly when combined.
- */
- void printBoundTerm(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType = TypeNode())
- {
- this->printBoundTermAsType(term, os, map, expectedType);
- }
- virtual void printBoundTermAsType(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType) = 0;
-
- /**
- * Print the proof representation of the given sort.
- *
- * @param os
- */
- virtual void printSort(Type type, std::ostream& os) = 0;
-
- /**
- * Go over the assertions and register all terms with the theories.
- *
- * @param os
- * @param paren closing parenthesis
- */
- virtual void registerTermsFromAssertions() = 0;
-
- /**
- * Print the theory assertions (arbitrary formulas over
- * theory atoms)
- *
- * @param os
- * @param paren closing parenthesis
- */
- virtual void printAssertions(std::ostream& os, std::ostream& paren) = 0;
- /**
- * Print variable declarations that need to appear within the proof,
- * e.g. skolemized variables.
- *
- * @param os
- * @param paren closing parenthesis
- */
- virtual void printDeferredDeclarations(std::ostream& os, std::ostream& paren) = 0;
-
- /**
- * Print aliasing declarations.
- *
- * @param os
- * @param paren closing parenthesis
- */
- virtual void printAliasingDeclarations(std::ostream& os, std::ostream& paren, const ProofLetMap &globalLetMap) = 0;
-
- /**
- * Print proofs of all the theory lemmas (must prove
- * actual clause used in resolution proof).
- *
- * @param os
- * @param paren
- */
- virtual void printTheoryLemmas(const IdToSatClause& lemmas, std::ostream& os,
- std::ostream& paren, ProofLetMap& map) = 0;
-
- /**
- * Register theory atom (ensures all terms and atoms are declared).
- *
- * @param atom
- */
- void registerTerm(Expr atom);
-
- /**
- * Ensures that a theory proof class for the given theory is created.
- * This method can be invoked regardless of whether the "proof" option
- * has been set.
- *
- * @param theory
- */
- void registerTheory(theory::Theory* theory);
- /**
- * Additional configuration of the theory proof class for the given theory.
- * This method should only be invoked when the "proof" option has been set.
- *
- * @param theory
- */
- void finishRegisterTheory(theory::Theory* theory);
-
- theory::TheoryId getTheoryForLemma(const prop::SatClause* clause);
- TheoryProof* getTheoryProof(theory::TheoryId id);
-
- void markTermForFutureRegistration(Expr term, theory::TheoryId id);
-
- void printConstantDisequalityProof(std::ostream& os, Expr c1, Expr c2, const ProofLetMap &globalLetMap);
-
- /**
- * Print a term in some non-core theory
- *
- * @param term expression representing term
- * @param os output stream
- * @param expectedType The type that this is expected to have in a parent
- * node. Null if there are no such requirements. This is useful for requesting
- * type conversions from the theory. e.g. in (5.5 == 4) the right-hand-side
- * should be converted to a real.
- *
- * The first version of this function has a default value for expectedType
- * (null) The second version is virtual.
- *
- * They are split to avoid mixing virtual function and default argument
- * values, which behave weirdly when combined.
- */
- void printTheoryTerm(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType = TypeNode());
- virtual void printTheoryTermAsType(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType) = 0;
- /**
- * Calls `TheoryProof::equalityType` on the appropriate theory.
- */
- TypeNode equalityType(const Expr& left, const Expr& right);
-
- bool printsAsBool(const Node &n);
-};
-
-class LFSCTheoryProofEngine : public TheoryProofEngine {
- void bind(Expr term, ProofLetMap& map, Bindings& let_order);
-public:
- LFSCTheoryProofEngine()
- : TheoryProofEngine() {}
-
- void printTheoryTermAsType(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType) override;
-
- void registerTermsFromAssertions() override;
- void printSortDeclarations(std::ostream& os, std::ostream& paren);
- void printTermDeclarations(std::ostream& os, std::ostream& paren);
- void printCoreTerm(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType = TypeNode());
- void printLetTerm(Expr term, std::ostream& os) override;
- void printBoundTermAsType(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType) override;
- void printAssertions(std::ostream& os, std::ostream& paren) override;
- void printLemmaRewrites(NodePairSet& rewrites,
- std::ostream& os,
- std::ostream& paren);
- void printDeferredDeclarations(std::ostream& os,
- std::ostream& paren) override;
- void printAliasingDeclarations(std::ostream& os,
- std::ostream& paren,
- const ProofLetMap& globalLetMap) override;
- void printTheoryLemmas(const IdToSatClause& lemmas,
- std::ostream& os,
- std::ostream& paren,
- ProofLetMap& map) override;
- void printSort(Type type, std::ostream& os) override;
-
- void performExtraRegistrations();
-
- void finalizeBvConflicts(const IdToSatClause& lemmas, std::ostream& os);
-
-private:
- static void dumpTheoryLemmas(const IdToSatClause& lemmas);
-
- // Prints this boolean term as a formula.
- // If necessary, it prints a wrapper converting a `Bool`-sorted term to a
- // formula.
- void printBoundFormula(Expr term, std::ostream& os, const ProofLetMap& map);
-
- // TODO: this function should be moved into the BV prover.
-
- std::map<Node, std::string> d_assertionToRewrite;
-};
-
-class TheoryProof {
-protected:
- // Pointer to the theory for this proof
- theory::Theory* d_theory;
- TheoryProofEngine* d_proofEngine;
- virtual theory::TheoryId getTheoryId() = 0;
-
- public:
- TheoryProof(theory::Theory* th, TheoryProofEngine* proofEngine)
- : d_theory(th)
- , d_proofEngine(proofEngine)
- {}
- virtual ~TheoryProof() {};
- /**
- * Print a term belonging some theory, not necessarily this one.
- *
- * @param term expresion representing term
- * @param os output stream
- */
- void printTerm(Expr term, std::ostream& os, const ProofLetMap& map) {
- d_proofEngine->printBoundTerm(term, os, map);
- }
- /**
- * Print a term belonging to THIS theory.
- *
- * @param term expression representing term
- * @param os output stream
- * @param expectedType The type that this is expected to have in a parent
- * node. Null if there are no such requirements. This is useful for requesting
- * type conversions from the theory. e.g. in (5.5 == 4) the right-hand-side
- * should be converted to a real.
- *
- * The first version of this function has a default value for expectedType
- * (null) The second version is virtual.
- *
- * They are split to avoid mixing virtual function and default argument
- * values, which behave weirdly when combined.
- */
- void printOwnedTerm(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType = TypeNode());
-
- virtual void printOwnedTermAsType(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType) = 0;
-
- /**
- * Return the type (at the SMT level, the sort) of an equality or disequality
- * between `left` and `right`.
- *
- * The default implementation asserts that the two have the same type, and
- * returns it.
- *
- * A theory may want to do something else.
- *
- * For example, the theory of arithmetic allows equalities between Reals and
- * Integers. In this case the integer is upcast to a real, and the equality
- * is over reals.
- */
- virtual TypeNode equalityType(const Expr& left, const Expr& right);
-
- /**
- * Print the proof representation of the given type that belongs to some theory.
- *
- * @param type
- * @param os
- */
- void printSort(Type type, std::ostream& os) {
- d_proofEngine->printSort(type, os);
- }
-
- // congrence matching term helper
- bool match(TNode n1, TNode n2);
-
- /**
- * Helper function for ProofUF::toStreamRecLFSC and
- * ProofArray::toStreamRecLFSC
- * Inputs:
- * - pf: equality engine proof
- * - map: A map for the let-expressions in the proof
- * - subTrans: main transitivity proof part
- * - pPrettyPrinter: optional pretty printer for sub-proofs
- * returns:
- * - the index of the contradicting node in pf.
- * */
- int assertAndPrint(
- const theory::eq::EqProof& pf,
- const ProofLetMap& map,
- std::shared_ptr<theory::eq::EqProof> subTrans,
- theory::eq::EqProof::PrettyPrinter* pPrettyPrinter = nullptr);
-
- /**
- * Helper function for ProofUF::toStreamRecLFSC and
- * ProofArray::toStreamRecLFSC
- * Inputs:
- * - evenLengthSequence: true iff the length of the sequence
- * of the identical equalities is even.
- * - sequenceOver: have we reached the last equality of this sequence?
- * - pf: equality engine proof
- * - map: A map for the let-expressions in the proof
- * - subproofStr: current stringstream content
- * - outStream: output stream to which the proof is printed
- * - n: transitivity sub-proof
- * - nodeAfterEqualitySequence: The node after the identical sequence.
- * Returns:
- * A pair of nodes, that are the updated nodes n and nodeAfterEqualitySequence
- *
- */
- std::pair<Node, Node> identicalEqualitiesPrinterHelper(
- bool evenLengthSequence,
- bool sequenceOver,
- const theory::eq::EqProof& pf,
- const ProofLetMap& map,
- const std::string subproofStr,
- std::stringstream* outStream,
- Node n,
- Node nodeAfterEqualitySequence);
-
- /**
- * Print the proof representation of the given type that belongs to THIS theory.
- *
- * @param type
- * @param os
- */
- virtual void printOwnedSort(Type type, std::ostream& os) = 0;
- /**
- * Print a proof for the theory lemmas. Must prove
- * clause representing lemmas to be used in resolution proof.
- *
- * @param os output stream
- */
- virtual void printTheoryLemmaProof(std::vector<Expr>& lemma,
- std::ostream& os,
- std::ostream& paren,
- const ProofLetMap& map);
- /**
- * Print the sorts declarations for this theory.
- *
- * @param os
- * @param paren
- */
- virtual void printSortDeclarations(std::ostream& os, std::ostream& paren) = 0;
- /**
- * Print the term declarations for this theory.
- *
- * @param os
- * @param paren
- */
- virtual void printTermDeclarations(std::ostream& os, std::ostream& paren) = 0;
- /**
- * Print any deferred variable/sorts declarations for this theory
- * (those that need to appear inside the actual proof).
- *
- * @param os
- * @param paren
- */
- virtual void printDeferredDeclarations(std::ostream& os, std::ostream& paren) = 0;
- /**
- * Print any aliasing declarations.
- *
- * @param os
- * @param paren
- */
- virtual void printAliasingDeclarations(std::ostream& os, std::ostream& paren, const ProofLetMap &globalLetMap) = 0;
- /**
- * Register a term of this theory that appears in the proof.
- *
- * @param term
- */
- virtual void registerTerm(Expr term) = 0;
- /**
- * Print a proof for the disequality of two constants that belong to this theory.
- *
- * @param term
- */
- virtual void printConstantDisequalityProof(std::ostream& os, Expr c1, Expr c2, const ProofLetMap &globalLetMap);
- /**
- * Print a proof for the equivalence of n1 and n2.
- *
- * @param term
- */
- virtual void printRewriteProof(std::ostream& os, const Node &n1, const Node &n2);
-
- /**
- * Return whether this node, when serialized as an LFSC proof, has sort `Bool`.
- *
- * This is virtual because it ultimately, theories control the serialization
- * of their proofs, so a theory will need to override this appropriately.
- *
- * This should only be called on nodes of type `Bool`.
- */
- virtual bool printsAsBool(const Node &n) {
- // Most nodes print as formulas, so this is the default.
- return false;
- }
-};
-
-class BooleanProof : public TheoryProof {
-protected:
- ExprSet d_declarations; // all the boolean variables
- theory::TheoryId getTheoryId() override;
-
- public:
- BooleanProof(TheoryProofEngine* proofEngine);
-
- void registerTerm(Expr term) override;
-};
-
-class LFSCBooleanProof : public BooleanProof {
-public:
- LFSCBooleanProof(TheoryProofEngine* proofEngine)
- : BooleanProof(proofEngine)
- {}
- void printOwnedTermAsType(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode ty) override;
- void printOwnedSort(Type type, std::ostream& os) override;
- void printTheoryLemmaProof(std::vector<Expr>& lemma,
- std::ostream& os,
- std::ostream& paren,
- const ProofLetMap& map) override;
- void printSortDeclarations(std::ostream& os, std::ostream& paren) override;
- void printTermDeclarations(std::ostream& os, std::ostream& paren) override;
- void printDeferredDeclarations(std::ostream& os,
- std::ostream& paren) override;
- void printAliasingDeclarations(std::ostream& os,
- std::ostream& paren,
- const ProofLetMap& globalLetMap) override;
-
- bool printsAsBool(const Node& n) override;
- void printConstantDisequalityProof(std::ostream& os,
- Expr c1,
- Expr c2,
- const ProofLetMap& globalLetMap) override;
-};
-
-} /* CVC4 namespace */
-
-#endif /* CVC4__THEORY_PROOF_H */
diff --git a/src/proof/uf_proof.cpp b/src/proof/uf_proof.cpp
deleted file mode 100644
index 74990ff44..000000000
--- a/src/proof/uf_proof.cpp
+++ /dev/null
@@ -1,759 +0,0 @@
-/********************* */
-/*! \file uf_proof.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Liana Hadarean, Guy Katz, Yoni Zohar
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** [[ Add lengthier description here ]]
-
- ** \todo document this file
-
-**/
-#include "proof/uf_proof.h"
-
-#include <stack>
-
-#include "proof/proof_manager.h"
-#include "proof/simplify_boolean_node.h"
-#include "theory/uf/theory_uf.h"
-
-namespace CVC4 {
-
-void ProofUF::toStream(std::ostream& out) const
-{
- ProofLetMap map;
- toStream(out, map);
-}
-
-void ProofUF::toStream(std::ostream& out, const ProofLetMap& map) const
-{
- Trace("theory-proof-debug") << "; Print UF proof..." << std::endl;
- //AJR : carry this further?
- toStreamLFSC(out, ProofManager::getUfProof(), *d_proof, map);
-}
-
-void ProofUF::toStreamLFSC(std::ostream& out,
- TheoryProof* tp,
- const theory::eq::EqProof& pf,
- const ProofLetMap& map)
-{
- Debug("pf::uf") << "ProofUF::toStreamLFSC starting" << std::endl;
- Debug("lfsc-uf") << "Printing uf proof in LFSC : " << std::endl;
- pf.debug_print("lfsc-uf");
- Debug("lfsc-uf") << std::endl;
- toStreamRecLFSC( out, tp, pf, 0, map );
-}
-
-Node ProofUF::toStreamRecLFSC(std::ostream& out,
- TheoryProof* tp,
- const theory::eq::EqProof& pf,
- unsigned tb,
- const ProofLetMap& map)
-{
- Debug("pf::uf") << std::endl
- << std::endl
- << "toStreamRecLFSC called. tb = " << tb
- << " . proof:" << std::endl;
- if (tb == 0)
- {
- // Special case: false was an input, so the proof is just "false".
- if (pf.d_id == theory::eq::MERGED_THROUGH_EQUALITY &&
- pf.d_node == NodeManager::currentNM()->mkConst(false)) {
- out << "(clausify_false ";
- out << ProofManager::getLitName(NodeManager::currentNM()->mkConst(false).notNode());
- out << ")" << std::endl;
- return Node();
- }
-
- std::shared_ptr<theory::eq::EqProof> subTrans =
- std::make_shared<theory::eq::EqProof>();
-
- int neg = tp->assertAndPrint(pf, map, subTrans);
-
- Node n1;
- std::stringstream ss, ss2;
- Debug("pf::uf") << "\nsubtrans has " << subTrans->d_children.size() << " children\n";
- bool disequalityFound = (neg >= 0);
-
- if(!disequalityFound || subTrans->d_children.size() >= 2) {
- n1 = toStreamRecLFSC(ss, tp, *subTrans, 1, map);
- } else {
- n1 = toStreamRecLFSC(ss, tp, *(subTrans->d_children[0]), 1, map);
- Debug("pf::uf") << "\nsubTrans unique child "
- << subTrans->d_children[0]->d_id
- << " was proven\ngot: " << n1 << std::endl;
- }
-
- Debug("pf::uf") << "\nhave proven: " << n1 << std::endl;
-
- out << "(clausify_false (contra _ ";
- if (disequalityFound) {
- Node n2 = pf.d_children[neg]->d_node;
- Assert(n2.getKind() == kind::NOT);
-
- Debug("pf::uf") << "n2 is " << n2[0] << std::endl;
-
- if (n2[0].getNumChildren() > 0)
- {
- Debug("pf::uf") << "\nn2[0]: " << n2[0][0] << std::endl;
- }
- if (n1.getNumChildren() > 1) { Debug("pf::uf") << "n1[1]: " << n1[1] << std::endl; }
-
- if(n2[0].getKind() == kind::APPLY_UF) {
- out << "(trans _ _ _ _ ";
-
- if (n1[0] == n2[0]) {
- out << "(symm _ _ _ ";
- out << ss.str();
- out << ") ";
- } else {
- Assert(n1[1] == n2[0]);
- out << ss.str();
- }
- out << "(pred_eq_f _ " << ProofManager::getLitName(n2[0]) << ")) t_t_neq_f))" << std::endl;
- } else if (n2[0].getKind() == kind::BOOLEAN_TERM_VARIABLE) {
- out << ss.str() << " " << ProofManager::getLitName(n2[0]) << "))";
- } else {
- Assert((n1[0] == n2[0][0] && n1[1] == n2[0][1])
- || (n1[1] == n2[0][0] && n1[0] == n2[0][1]));
- if(n1[1] == n2[0][0]) {
- out << "(symm _ _ _ " << ss.str() << ")";
- } else {
- out << ss.str();
- }
- out << " " << ProofManager::getLitName(n2[0]) << "))" << std::endl;
- }
- } else {
- Node n2 = pf.d_node;
- Assert(n2.getKind() == kind::EQUAL);
- Assert((n1[0] == n2[0] && n1[1] == n2[1])
- || (n1[1] == n2[0] && n1[0] == n2[1]));
-
- out << ss.str();
- out << " ";
- ProofManager::getTheoryProofEngine()->printConstantDisequalityProof(
- out, n1[0].toExpr(), n1[1].toExpr(), map);
- out << "))" << std::endl;
- }
-
- return Node();
- }
- // TODO (#2965): improve this code, which is highly complicated.
- switch(pf.d_id) {
- case theory::eq::MERGED_THROUGH_CONGRUENCE: {
- Debug("pf::uf") << "\nok, looking at congruence:\n";
- pf.debug_print("pf::uf");
- std::stack<const theory::eq::EqProof*> stk;
- for (const theory::eq::EqProof* pf2 = &pf;
- pf2->d_id == theory::eq::MERGED_THROUGH_CONGRUENCE;
- pf2 = pf2->d_children[0].get()) {
- Assert(!pf2->d_node.isNull());
- Assert(pf2->d_node.getKind() == kind::PARTIAL_APPLY_UF
- || pf2->d_node.getKind() == kind::BUILTIN
- || pf2->d_node.getKind() == kind::APPLY_UF
- || pf2->d_node.getKind() == kind::SELECT
- || pf2->d_node.getKind() == kind::STORE);
- Assert(pf2->d_children.size() == 2);
- out << "(cong _ _ _ _ _ _ ";
- stk.push(pf2);
- }
- Assert(stk.top()->d_children[0]->d_id
- != theory::eq::MERGED_THROUGH_CONGRUENCE);
- NodeBuilder<> b1(kind::PARTIAL_APPLY_UF), b2(kind::PARTIAL_APPLY_UF);
- const theory::eq::EqProof* pf2 = stk.top();
- stk.pop();
- Assert(pf2->d_id == theory::eq::MERGED_THROUGH_CONGRUENCE);
- Node n1 = toStreamRecLFSC(out, tp, *(pf2->d_children[0]), tb + 1, map);
- out << " ";
- std::stringstream ss;
- Node n2 = toStreamRecLFSC(ss, tp, *(pf2->d_children[1]), tb + 1, map);
- Debug("pf::uf") << "\nok, in FIRST cong[" << stk.size() << "]" << "\n";
- pf2->debug_print("pf::uf");
- Debug("pf::uf") << "looking at " << pf2->d_node << "\n";
- Debug("pf::uf") << " " << n1 << "\n";
- Debug("pf::uf") << " " << n2 << "\n";
- int side = 0;
- if (tp->match(pf2->d_node, n1[0]))
- {
- //if(tb == 1) {
- Debug("pf::uf") << "SIDE IS 0\n";
- //}
- side = 0;
- } else {
- //if(tb == 1) {
- Debug("pf::uf") << "SIDE IS 1\n";
- //}
- if (!tp->match(pf2->d_node, n1[1]))
- {
- Debug("pf::uf") << "IN BAD CASE, our first subproof is\n";
- pf2->d_children[0]->debug_print("pf::uf");
- }
- Assert(tp->match(pf2->d_node, n1[1]));
- side = 1;
- }
- if (n1[side].getKind() == kind::APPLY_UF
- || n1[side].getKind() == kind::PARTIAL_APPLY_UF
- || n1[side].getKind() == kind::SELECT
- || n1[side].getKind() == kind::STORE)
- {
- if (n1[side].getKind() == kind::APPLY_UF
- || n1[side].getKind() == kind::PARTIAL_APPLY_UF)
- {
- b1 << n1[side].getOperator();
- } else {
- b1 << ProofManager::currentPM()->mkOp(n1[side].getOperator());
- }
- b1.append(n1[side].begin(), n1[side].end());
- } else {
- b1 << n1[side];
- }
- if(n1[1-side].getKind() == kind::PARTIAL_APPLY_UF || n1[1-side].getKind() == kind::APPLY_UF || n1[side].getKind() == kind::SELECT || n1[side].getKind() == kind::STORE) {
- if (n1[1 - side].getKind() == kind::PARTIAL_APPLY_UF
- || n1[1 - side].getKind() == kind::APPLY_UF)
- {
- b2 << n1[1-side].getOperator();
- } else {
- b2 << ProofManager::currentPM()->mkOp(n1[1-side].getOperator());
- }
- b2.append(n1[1-side].begin(), n1[1-side].end());
- } else {
- b2 << n1[1-side];
- }
- Debug("pf::uf") << "pf2->d_node " << pf2->d_node << std::endl;
- Debug("pf::uf") << "b1.getNumChildren() " << b1.getNumChildren() << std::endl;
- Debug("pf::uf") << "n1 " << n1 << std::endl;
- Debug("pf::uf") << "n2 " << n2 << std::endl;
- Debug("pf::uf") << "side " << side << std::endl;
- if(pf2->d_node[b1.getNumChildren() - (pf2->d_node.getMetaKind() == kind::metakind::PARAMETERIZED ? 0 : 1)] == n2[side]) {
- b1 << n2[side];
- b2 << n2[1-side];
- out << ss.str();
- } else {
- Assert(pf2->d_node[b1.getNumChildren()
- - (pf2->d_node.getMetaKind()
- == kind::metakind::PARAMETERIZED
- ? 0
- : 1)]
- == n2[1 - side]);
- b1 << n2[1-side];
- b2 << n2[side];
- out << "(symm _ _ _ " << ss.str() << ")";
- }
- out << ")";
- while(!stk.empty()) {
- if(tb == 1) {
- Debug("pf::uf") << "\nMORE TO DO\n";
- }
- pf2 = stk.top();
- stk.pop();
- Assert(pf2->d_id == theory::eq::MERGED_THROUGH_CONGRUENCE);
- out << " ";
- ss.str("");
- n2 = toStreamRecLFSC(ss, tp, *(pf2->d_children[1]), tb + 1, map);
- Debug("pf::uf") << "\nok, in cong[" << stk.size() << "]" << "\n";
- Debug("pf::uf") << "looking at " << pf2->d_node << "\n";
- Debug("pf::uf") << " " << n1 << "\n";
- Debug("pf::uf") << " " << n2 << "\n";
- Debug("pf::uf") << " " << b1 << "\n";
- Debug("pf::uf") << " " << b2 << "\n";
- if(pf2->d_node[b1.getNumChildren()] == n2[side]) {
- b1 << n2[side];
- b2 << n2[1-side];
- out << ss.str();
- } else {
- Assert(pf2->d_node[b1.getNumChildren()] == n2[1 - side]);
- b1 << n2[1-side];
- b2 << n2[side];
- out << "(symm _ _ _ " << ss.str() << ")";
- }
- out << ")";
- }
- n1 = b1;
- n2 = b2;
- Debug("pf::uf") << "at end assert, got " << pf2->d_node << " and " << n1 << std::endl;
- if(pf2->d_node.getKind() == kind::PARTIAL_APPLY_UF) {
- Assert(n1 == pf2->d_node);
- }
- if(n1.getOperator().getType().getNumChildren() == n1.getNumChildren() + 1) {
- if(ProofManager::currentPM()->hasOp(n1.getOperator())) {
- b1.clear(ProofManager::currentPM()->lookupOp(n2.getOperator()).getConst<Kind>());
- } else {
- b1.clear(kind::APPLY_UF);
- b1 << n1.getOperator();
- }
- b1.append(n1.begin(), n1.end());
- n1 = b1;
- Debug("pf::uf") << "at[2] end assert, got " << pf2->d_node << " and " << n1 << std::endl;
- if(pf2->d_node.getKind() == kind::APPLY_UF) {
- Assert(n1 == pf2->d_node);
- }
- }
- if(n2.getOperator().getType().getNumChildren() == n2.getNumChildren() + 1) {
- if(ProofManager::currentPM()->hasOp(n2.getOperator())) {
- b2.clear(ProofManager::currentPM()->lookupOp(n2.getOperator()).getConst<Kind>());
- } else {
- b2.clear(kind::APPLY_UF);
- b2 << n2.getOperator();
- }
- b2.append(n2.begin(), n2.end());
- n2 = b2;
- }
- Node n = (side == 0 ? n1.eqNode(n2) : n2.eqNode(n1));
- if(tb == 1) {
- Debug("pf::uf") << "\ncong proved: " << n << "\n";
- }
- return n;
- }
-
- case theory::eq::MERGED_THROUGH_REFLEXIVITY:
- {
- Assert(!pf.d_node.isNull());
- Assert(pf.d_children.empty());
- out << "(refl _ ";
- tp->printTerm(NodeManager::currentNM()->toExpr(pf.d_node), out, map);
- out << ")";
- return pf.d_node.eqNode(pf.d_node);
- }
- case theory::eq::MERGED_THROUGH_EQUALITY:
- Assert(!pf.d_node.isNull());
- Assert(pf.d_children.empty());
- out << ProofManager::getLitName(pf.d_node.negate());
- return pf.d_node;
-
- case theory::eq::MERGED_THROUGH_TRANS: {
- Assert(!pf.d_node.isNull());
- Assert(pf.d_children.size() >= 2);
- std::stringstream ss;
- Debug("pf::uf") << "\ndoing trans proof[[\n";
- pf.debug_print("pf::uf");
- Debug("pf::uf") << "\n";
-
- pf.d_children[0]->d_node = simplifyBooleanNode(pf.d_children[0]->d_node);
-
- Node n1 = toStreamRecLFSC(ss, tp, *(pf.d_children[0]), tb + 1, map);
- Debug("pf::uf") << "\ndoing trans proof, got n1 " << n1 << "\n";
- if(tb == 1) {
- Debug("pf::uf") << "\ntrans proof[0], got n1 " << n1 << "\n";
- }
-
- bool identicalEqualities = false;
- bool evenLengthSequence;
- std::stringstream dontCare;
- Node nodeAfterEqualitySequence =
- toStreamRecLFSC(dontCare, tp, *(pf.d_children[0]), tb + 1, map);
-
- std::map<size_t, Node> childToStream;
- std::pair<Node, Node> nodePair;
- for(size_t i = 1; i < pf.d_children.size(); ++i) {
- std::stringstream ss1(ss.str()), ss2;
- ss.str("");
-
- pf.d_children[i]->d_node = simplifyBooleanNode(pf.d_children[i]->d_node);
-
- // It is possible that we've already converted the i'th child to stream.
- // If so,
- // use previously stored result. Otherwise, convert and store.
- Node n2;
- if (childToStream.find(i) != childToStream.end())
- n2 = childToStream[i];
- else
- {
- n2 = toStreamRecLFSC(ss2, tp, *(pf.d_children[i]), tb + 1, map);
- childToStream[i] = n2;
- }
-
- // The following branch is dedicated to handling sequences of identical
- // equalities,
- // i.e. trans[ a=b, a=b, a=b ].
- //
- // There are two cases:
- // 1. The number of equalities is odd. Then, the sequence can be
- // collapsed to just one equality,
- // i.e. a=b.
- // 2. The number of equalities is even. Now, we have two options: a=a
- // or b=b. To determine this,
- // we look at the node after the equality sequence. If it needs a,
- // we go for a=a; and if it needs
- // b, we go for b=b. If there is no following node, we look at the
- // goal of the transitivity proof,
- // and use it to determine which option we need.
- if (n2.getKind() == kind::EQUAL)
- {
- if (((n1[0] == n2[0]) && (n1[1] == n2[1]))
- || ((n1[0] == n2[1]) && (n1[1] == n2[0])))
- {
- // We are in a sequence of identical equalities
-
- Debug("pf::uf") << "Detected identical equalities: " << std::endl
- << "\t" << n1 << std::endl;
-
- if (!identicalEqualities)
- {
- // The sequence of identical equalities has started just now
- identicalEqualities = true;
-
- Debug("pf::uf")
- << "The sequence is just beginning. Determining length..."
- << std::endl;
-
- // Determine whether the length of this sequence is odd or even.
- evenLengthSequence = true;
- bool sequenceOver = false;
- size_t j = i + 1;
-
- while (j < pf.d_children.size() && !sequenceOver)
- {
- std::stringstream ignore;
- nodeAfterEqualitySequence =
- toStreamRecLFSC(ignore, tp, *(pf.d_children[j]), tb + 1, map);
-
- if (((nodeAfterEqualitySequence[0] == n1[0])
- && (nodeAfterEqualitySequence[1] == n1[1]))
- || ((nodeAfterEqualitySequence[0] == n1[1])
- && (nodeAfterEqualitySequence[1] == n1[0])))
- {
- evenLengthSequence = !evenLengthSequence;
- }
- else
- {
- sequenceOver = true;
- }
-
- ++j;
- }
-
- nodePair =
- tp->identicalEqualitiesPrinterHelper(evenLengthSequence,
- sequenceOver,
- pf,
- map,
- ss1.str(),
- &ss,
- n1,
- nodeAfterEqualitySequence);
- n1 = nodePair.first;
- nodeAfterEqualitySequence = nodePair.second;
- } else {
- ss.str(ss1.str());
- }
-
- // Ignore the redundancy.
- continue;
- }
- }
-
- if (identicalEqualities) {
- // We were in a sequence of identical equalities, but it has now ended. Resume normal operation.
- identicalEqualities = false;
- }
-
- Debug("pf::uf") << "\ndoing trans proof, got n2 " << n2 << "\n";
- if(tb == 1) {
- Debug("pf::uf") << "\ntrans proof[" << i << "], got n2 " << n2 << "\n";
- Debug("pf::uf") << (n2.getKind() == kind::EQUAL) << "\n";
-
- if ((n1.getNumChildren() >= 2) && (n2.getNumChildren() >= 2)) {
- Debug("pf::uf") << n1[0].getId() << " " << n1[1].getId() << " / " << n2[0].getId() << " " << n2[1].getId() << "\n";
- Debug("pf::uf") << n1[0].getId() << " " << n1[0] << "\n";
- Debug("pf::uf") << n1[1].getId() << " " << n1[1] << "\n";
- Debug("pf::uf") << n2[0].getId() << " " << n2[0] << "\n";
- Debug("pf::uf") << n2[1].getId() << " " << n2[1] << "\n";
- Debug("pf::uf") << (n1[0] == n2[0]) << "\n";
- Debug("pf::uf") << (n1[1] == n2[1]) << "\n";
- Debug("pf::uf") << (n1[0] == n2[1]) << "\n";
- Debug("pf::uf") << (n1[1] == n2[0]) << "\n";
- }
- }
-
- ss << "(trans _ _ _ _ ";
-
- if(n2.getKind() == kind::EQUAL && n1.getKind() == kind::EQUAL)
- // Both elements of the transitivity rule are equalities/iffs
- {
- if(n1[0] == n2[0]) {
- if(tb == 1) { Debug("pf::uf") << "case 1\n"; }
- n1 = n1[1].eqNode(n2[1]);
- ss << "(symm _ _ _ " << ss1.str() << ") " << ss2.str();
- } else if(n1[1] == n2[1]) {
- if(tb == 1) { Debug("pf::uf") << "case 2\n"; }
- n1 = n1[0].eqNode(n2[0]);
- ss << ss1.str() << " (symm _ _ _ " << ss2.str() << ")";
- } else if(n1[0] == n2[1]) {
- if(tb == 1) { Debug("pf::uf") << "case 3\n"; }
- n1 = n2[0].eqNode(n1[1]);
- ss << ss2.str() << " " << ss1.str();
- if(tb == 1) { Debug("pf::uf") << "++ proved " << n1 << "\n"; }
- } else if(n1[1] == n2[0]) {
- if(tb == 1) { Debug("pf::uf") << "case 4\n"; }
- n1 = n1[0].eqNode(n2[1]);
- ss << ss1.str() << " " << ss2.str();
- } else {
- Warning() << "\n\ntrans proof failure at step " << i << "\n\n";
- Warning() << "0 proves " << n1 << "\n";
- Warning() << "1 proves " << n2 << "\n\n";
- pf.debug_print("pf::uf",0);
- //toStreamRec(Warning.getStream(), pf, 0);
- Warning() << "\n\n";
- Unreachable();
- }
- Debug("pf::uf") << "++ trans proof[" << i << "], now have " << n1 << std::endl;
- } else if(n1.getKind() == kind::EQUAL) {
- // n1 is an equality/iff, but n2 is a predicate
- if(n1[0] == n2) {
- n1 = n1[1].eqNode(NodeManager::currentNM()->mkConst(true));
- ss << "(symm _ _ _ " << ss1.str() << ") (pred_eq_t _ " << ss2.str() << ")";
- } else if(n1[1] == n2) {
- n1 = n1[0].eqNode(NodeManager::currentNM()->mkConst(true));
- ss << ss1.str() << " (pred_eq_t _ " << ss2.str() << ")";
- } else {
- Unreachable();
- }
- } else if(n2.getKind() == kind::EQUAL) {
- // n2 is an equality/iff, but n1 is a predicate
- if(n2[0] == n1) {
- n1 = n2[1].eqNode(NodeManager::currentNM()->mkConst(true));
- ss << "(symm _ _ _ " << ss2.str() << ") (pred_eq_t _ " << ss1.str() << ")";
- } else if(n2[1] == n1) {
- n1 = n2[0].eqNode(NodeManager::currentNM()->mkConst(true));
- ss << ss2.str() << " (pred_eq_t _ " << ss1.str() << ")";
- } else {
- Unreachable();
- }
- } else {
- // Both n1 and n2 are predicates.
- // We want to prove b1 = b2, and we know that ((b1), (b2)) or ((not b1), (not b2))
- if (n1.getKind() == kind::NOT) {
- Assert(n2.getKind() == kind::NOT);
- Assert(pf.d_node[0] == n1[0] || pf.d_node[0] == n2[0]);
- Assert(pf.d_node[1] == n1[0] || pf.d_node[1] == n2[0]);
- Assert(n1[0].getKind() == kind::BOOLEAN_TERM_VARIABLE);
- Assert(n2[0].getKind() == kind::BOOLEAN_TERM_VARIABLE);
-
- if (pf.d_node[0] == n1[0]) {
- ss << "(false_preds_equal _ _ " << ss1.str() << " " << ss2.str() << ") ";
- ss << "(pred_refl_neg _ " << ss2.str() << ")";
- } else {
- ss << "(false_preds_equal _ _ " << ss2.str() << " " << ss1.str() << ") ";
- ss << "(pred_refl_neg _ " << ss1.str() << ")";
- }
- n1 = pf.d_node;
-
- } else if (n1.getKind() == kind::BOOLEAN_TERM_VARIABLE) {
- Assert(n2.getKind() == kind::BOOLEAN_TERM_VARIABLE);
- Assert(pf.d_node[0] == n1 || pf.d_node[0] == n2);
- Assert(pf.d_node[1] == n1 || pf.d_node[2] == n2);
-
- if (pf.d_node[0] == n1) {
- ss << "(true_preds_equal _ _ " << ss1.str() << " " << ss2.str() << ") ";
- ss << "(pred_refl_pos _ " << ss2.str() << ")";
- } else {
- ss << "(true_preds_equal _ _ " << ss2.str() << " " << ss1.str() << ") ";
- ss << "(pred_refl_pos _ " << ss1.str() << ")";
- }
- n1 = pf.d_node;
-
- } else {
-
- Unreachable();
- }
- }
-
- ss << ")";
- }
- out << ss.str();
- Debug("pf::uf") << "\n++ trans proof done, have proven " << n1 << std::endl;
- return n1;
- }
-
- default:
- Assert(!pf.d_node.isNull());
- Assert(pf.d_children.empty());
- Debug("pf::uf") << "theory proof: " << pf.d_node << " by rule " << int(pf.d_id) << std::endl;
- AlwaysAssert(false);
- return pf.d_node;
- }
-}
-
-UFProof::UFProof(theory::uf::TheoryUF* uf, TheoryProofEngine* pe)
- : TheoryProof(uf, pe)
-{}
-
-theory::TheoryId UFProof::getTheoryId() { return theory::THEORY_UF; }
-void UFProof::registerTerm(Expr term) {
- // already registered
- if (d_declarations.find(term) != d_declarations.end())
- return;
-
- Type type = term.getType();
- if (type.isSort()) {
- // declare uninterpreted sorts
- d_sorts.insert(type);
- }
-
- if (term.getKind() == kind::APPLY_UF) {
- Expr function = term.getOperator();
- d_declarations.insert(function);
- }
-
- if (term.isVariable()) {
- d_declarations.insert(term);
-
-
- if (term.getKind() == kind::BOOLEAN_TERM_VARIABLE) {
- // Ensure cnf literals
- Node asNode(term);
- ProofManager::currentPM()->ensureLiteral(
- asNode.eqNode(NodeManager::currentNM()->mkConst(true)));
- ProofManager::currentPM()->ensureLiteral(
- asNode.eqNode(NodeManager::currentNM()->mkConst(false)));
- }
- }
-
- // recursively declare all other terms
- for (unsigned i = 0; i < term.getNumChildren(); ++i) {
- // could belong to other theories
- d_proofEngine->registerTerm(term[i]);
- }
-}
-
-void LFSCUFProof::printOwnedTermAsType(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType)
-{
- Node node = Node::fromExpr(term);
- Debug("pf::uf") << std::endl << "(pf::uf) LFSCUfProof::printOwnedTerm: term = " << node << std::endl;
-
- Assert(theory::Theory::theoryOf(node) == theory::THEORY_UF);
-
- if (node.getKind() == kind::VARIABLE ||
- node.getKind() == kind::SKOLEM ||
- node.getKind() == kind::BOOLEAN_TERM_VARIABLE) {
- os << node;
- return;
- }
-
- Assert(node.getKind() == kind::APPLY_UF);
-
- if(node.getType().isBoolean()) {
- os << "(p_app ";
- }
- Node func = node.getOperator();
- for (unsigned i = 0; i < term.getNumChildren(); ++i) {
- os << "(apply _ _ ";
- }
- os << func << " ";
- Assert(func.getType().isFunction());
- std::vector<TypeNode> argsTypes = node.getOperator().getType().getArgTypes();
- for (unsigned i = 0; i < node.getNumChildren(); ++i) {
-
- bool convertToBool = (node[i].getType().isBoolean() && !d_proofEngine->printsAsBool(node[i]));
- if (convertToBool) os << "(f_to_b ";
- d_proofEngine->printBoundTerm(term[i], os, map, argsTypes[i]);
- if (convertToBool) os << ")";
- os << ")";
- }
- if(term.getType().isBoolean()) {
- os << ")";
- }
-}
-
-void LFSCUFProof::printOwnedSort(Type type, std::ostream& os) {
- Debug("pf::uf") << std::endl << "(pf::uf) LFSCArrayProof::printOwnedSort: type is: " << type << std::endl;
-
- Assert(type.isSort());
- os << type;
-}
-
-void LFSCUFProof::printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren, const ProofLetMap& map) {
- os << " ;; UF Theory Lemma \n;;";
- for (unsigned i = 0; i < lemma.size(); ++i) {
- os << lemma[i] <<" ";
- }
- os <<"\n";
- //os << " (clausify_false trust)";
- UFProof::printTheoryLemmaProof(lemma, os, paren, map);
-}
-
-void LFSCUFProof::printSortDeclarations(std::ostream& os, std::ostream& paren) {
- for (TypeSet::const_iterator it = d_sorts.begin(); it != d_sorts.end(); ++it) {
- if (!ProofManager::currentPM()->wasPrinted(*it)) {
- os << "(% " << *it << " sort\n";
- paren << ")";
- ProofManager::currentPM()->markPrinted(*it);
- }
- }
-}
-
-void LFSCUFProof::printTermDeclarations(std::ostream& os, std::ostream& paren) {
- // declaring the terms
- Debug("pf::uf") << "LFSCUFProof::printTermDeclarations called" << std::endl;
-
- for (ExprSet::const_iterator it = d_declarations.begin(); it != d_declarations.end(); ++it) {
- Expr term = *it;
-
- os << "(% " << ProofManager::sanitize(term) << " ";
- os << "(term ";
-
- Type type = term.getType();
- if (type.isFunction()) {
- std::ostringstream fparen;
- FunctionType ftype = (FunctionType)type;
- std::vector<Type> args = ftype.getArgTypes();
- args.push_back(ftype.getRangeType());
- os << "(arrow";
- for (unsigned i = 0; i < args.size(); i++) {
- Type arg_type = args[i];
- os << " ";
- d_proofEngine->printSort(arg_type, os);
- if (i < args.size() - 2) {
- os << " (arrow";
- fparen << ")";
- }
- }
- os << fparen.str() << "))\n";
- } else {
- Assert(term.isVariable());
- os << type << ")\n";
- }
- paren << ")";
- }
-
- Debug("pf::uf") << "LFSCUFProof::printTermDeclarations done" << std::endl;
-}
-
-void LFSCUFProof::printDeferredDeclarations(std::ostream& os, std::ostream& paren) {
- // Nothing to do here at this point.
-}
-
-void LFSCUFProof::printAliasingDeclarations(std::ostream& os, std::ostream& paren, const ProofLetMap &globalLetMap) {
- // Nothing to do here at this point.
-}
-
-bool LFSCUFProof::printsAsBool(const Node &n) {
- if (n.getKind() == kind::BOOLEAN_TERM_VARIABLE)
- return true;
-
- return false;
-}
-
-void LFSCUFProof::printConstantDisequalityProof(std::ostream& os, Expr c1, Expr c2, const ProofLetMap &globalLetMap) {
- Node falseNode = NodeManager::currentNM()->mkConst(false);
- Node trueNode = NodeManager::currentNM()->mkConst(true);
-
- Assert(c1 == falseNode.toExpr() || c1 == trueNode.toExpr());
- Assert(c2 == falseNode.toExpr() || c2 == trueNode.toExpr());
- Assert(c1 != c2);
-
- if (c1 == trueNode.toExpr())
- os << "t_t_neq_f";
- else
- os << "(symm _ _ _ t_t_neq_f)";
-}
-
-} /* namespace CVC4 */
diff --git a/src/proof/uf_proof.h b/src/proof/uf_proof.h
deleted file mode 100644
index 647359a87..000000000
--- a/src/proof/uf_proof.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/********************* */
-/*! \file uf_proof.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Mathias Preiner, Liana Hadarean, Tim King
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief UF proof
- **
- ** UF proof
- **/
-
-#include "cvc4_private.h"
-
-#ifndef CVC4__UF__PROOF_H
-#define CVC4__UF__PROOF_H
-
-#include <memory>
-#include <unordered_set>
-
-#include "expr/expr.h"
-#include "proof/theory_proof.h"
-#include "theory/uf/equality_engine.h"
-#include "util/proof.h"
-
-namespace CVC4 {
-
-// proof object outputted by TheoryUF
-class ProofUF : public Proof
-{
- public:
- ProofUF(std::shared_ptr<theory::eq::EqProof> pf) : d_proof(pf) {}
- void toStream(std::ostream& out) const override;
- void toStream(std::ostream& out, const ProofLetMap& map) const override;
-
- private:
- static void toStreamLFSC(std::ostream& out, TheoryProof* tp,
- const theory::eq::EqProof& pf,
- const ProofLetMap& map);
- static Node toStreamRecLFSC(std::ostream& out, TheoryProof* tp,
- const theory::eq::EqProof& pf, unsigned tb,
- const ProofLetMap& map);
-
- // it is simply an equality engine proof
- std::shared_ptr<theory::eq::EqProof> d_proof;
-};
-
-namespace theory {
-namespace uf {
-class TheoryUF;
-}
-}
-
-typedef std::unordered_set<Type, TypeHashFunction > TypeSet;
-
-
-class UFProof : public TheoryProof {
-protected:
- TypeSet d_sorts; // all the uninterpreted sorts in this theory
- ExprSet d_declarations; // all the variable/function declarations
- theory::TheoryId getTheoryId() override;
-
- public:
- UFProof(theory::uf::TheoryUF* uf, TheoryProofEngine* proofEngine);
-
- void registerTerm(Expr term) override;
-};
-
-class LFSCUFProof : public UFProof {
-public:
- LFSCUFProof(theory::uf::TheoryUF* uf, TheoryProofEngine* proofEngine)
- : UFProof(uf, proofEngine)
- {}
- void printOwnedTermAsType(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType) override;
- void printOwnedSort(Type type, std::ostream& os) override;
- void printTheoryLemmaProof(std::vector<Expr>& lemma,
- std::ostream& os,
- std::ostream& paren,
- const ProofLetMap& map) override;
- void printSortDeclarations(std::ostream& os, std::ostream& paren) override;
- void printTermDeclarations(std::ostream& os, std::ostream& paren) override;
- void printDeferredDeclarations(std::ostream& os,
- std::ostream& paren) override;
- void printAliasingDeclarations(std::ostream& os,
- std::ostream& paren,
- const ProofLetMap& globalLetMap) override;
-
- bool printsAsBool(const Node& n) override;
-
- void printConstantDisequalityProof(std::ostream& os,
- Expr c1,
- Expr c2,
- const ProofLetMap& globalLetMap) override;
-};
-
-
-}/* CVC4 namespace */
-
-#endif /* CVC4__UF__PROOF_H */
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback