summaryrefslogtreecommitdiff
path: root/src/proof
diff options
context:
space:
mode:
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