This deletes much of the old proof code. Basically everything but the minimal necessary infra-structure for producing unsat cores. That includes dependency tracking in preprocessing, the prop engine proof and the unsat core computation code in the old proof manager. These should also go once we fully integrate into master the new proof infrastructure.
It also cleans interfaces that were using old-proof-code-specific constructs (such as LemmaProofRecipe). When possible or when it made sense standalone local proof production code was kept, but deactivated (such is in the equality engine and in the arithmetic solver).
printer/smt2/smt2_printer.h
printer/tptp/tptp_printer.cpp
printer/tptp/tptp_printer.h
- proof/arith_proof.cpp
- proof/arith_proof.h
- proof/arith_proof_recorder.cpp
- proof/arith_proof_recorder.h
- proof/array_proof.cpp
- proof/array_proof.h
- proof/bitvector_proof.cpp
- proof/bitvector_proof.h
- proof/clausal_bitvector_proof.cpp
- proof/clausal_bitvector_proof.h
proof/clause_id.h
proof/cnf_proof.cpp
proof/cnf_proof.h
- proof/dimacs.cpp
- proof/dimacs.h
- proof/drat/drat_proof.cpp
- proof/drat/drat_proof.h
- proof/er/er_proof.cpp
- proof/er/er_proof.h
- proof/lemma_proof.cpp
- proof/lemma_proof.h
- proof/lfsc_proof_printer.cpp
- proof/lfsc_proof_printer.h
- proof/lrat/lrat_proof.cpp
- proof/lrat/lrat_proof.h
- proof/proof.h
proof/proof_manager.cpp
proof/proof_manager.h
- proof/proof_output_channel.cpp
- proof/proof_output_channel.h
- proof/proof_utils.cpp
- proof/proof_utils.h
- proof/resolution_bitvector_proof.cpp
- proof/resolution_bitvector_proof.h
proof/sat_proof.h
proof/sat_proof_implementation.h
- proof/simplify_boolean_node.cpp
- proof/simplify_boolean_node.h
- proof/skolemization_manager.cpp
- proof/skolemization_manager.h
- proof/theory_proof.cpp
- proof/theory_proof.h
- proof/uf_proof.cpp
- proof/uf_proof.h
proof/unsat_core.cpp
proof/unsat_core.h
prop/bvminisat/bvminisat.cpp
theory/arith/type_enumerator.h
theory/arrays/array_info.cpp
theory/arrays/array_info.h
- theory/arrays/array_proof_reconstruction.cpp
- theory/arrays/array_proof_reconstruction.h
theory/arrays/static_fact_manager.cpp
theory/arrays/static_fact_manager.h
theory/arrays/theory_arrays.cpp
util/integer_gmp_imp.h
util/maybe.h
util/poly_util.h
- util/proof.h
util/rational_cln_imp.h
util/rational_gmp_imp.h
util/real_algebraic_number_poly_imp.h
name = "Bitvector theory"
header = "options/bv_options.h"
-[[option]]
- name = "bvProofFormat"
- category = "expert"
- long = "bv-proof-format=MODE"
- type = "BvProofFormat"
- default = "ER"
- predicates = ["checkSatSolverEnabled<BvProofFormat>"]
- help = "choose which UNSAT proof format to use, see --bv-sat-solver=help"
- help_mode = "Bit-vector proof formats."
-[[option.mode.ER]]
- name = "er"
- help = "Extended Resolution, i.e. resolution with new variable definitions."
-[[option.mode.DRAT]]
- name = "drat"
- help = "Deletion and Resolution Asymmetric Tautology Additions."
-[[option.mode.LRAT]]
- name = "lrat"
- help = "DRAT with unit propagation hints to accelerate checking."
-
-[[option]]
- name = "bvOptimizeSatProof"
- category = "expert"
- long = "bv-optimize-sat-proof=MODE"
- type = "BvOptimizeSatProof"
- default = "FORMULA"
- predicates = ["checkSatSolverEnabled<BvOptimizeSatProof>"]
- help = "enable SAT proof optimizations, see --bv-optimize-sat-proof=help"
- help_mode = "SAT proof optimization level."
-[[option.mode.NONE]]
- name = "none"
- help = "Do not optimize the SAT proof."
-[[option.mode.PROOF]]
- name = "proof"
- help = "Use drat-trim to shrink the SAT proof."
-[[option.mode.FORMULA]]
- name = "formula"
- help = "Use drat-trim to shrink the SAT proof and formula."
-
[[option]]
name = "bvSatSolver"
smt_name = "bv-sat-solver"
options::InstFormatMode getInstFormatMode() const;
OutputLanguage getOutputLanguage() const;
bool getUfHo() const;
- bool getCheckProofs() const;
bool getDumpInstantiations() const;
bool getDumpModels() const;
bool getDumpProofs() const;
bool getMemoryMap() const;
bool getParseOnly() const;
bool getProduceModels() const;
- bool getProof() const;
bool getSegvSpin() const;
bool getSemanticChecks() const;
bool getStatistics() const;
bool Options::getUfHo() const { return (*this)[options::ufHo]; }
-bool Options::getCheckProofs() const{
- return (*this)[options::checkProofs];
-}
-
bool Options::getDumpInstantiations() const{
return (*this)[options::dumpInstantiations];
}
return (*this)[options::produceModels];
}
-bool Options::getProof() const{
- return (*this)[options::proof];
-}
-
bool Options::getSegvSpin() const{
return (*this)[options::segvSpin];
}
id = "PROOF"
name = "Proof"
header = "options/proof_options.h"
-
-[[option]]
- name = "lfscLetification"
- category = "regular"
- long = "lfsc-letification"
- type = "bool"
- default = "true"
- read_only = true
- help = "turns on global letification in LFSC proofs"
-
-[[option]]
- name = "aggressiveCoreMin"
- category = "regular"
- long = "aggressive-core-min"
- type = "bool"
- default = "false"
- read_only = true
- help = "turns on aggressive unsat core minimization (experimental)"
-
-[[option]]
- name = "fewerPreprocessingHoles"
- category = "regular"
- long = "fewer-preprocessing-holes"
- type = "bool"
- default = "false"
- help = "try to eliminate preprocessing holes in proofs"
-
-[[option]]
- name = "allowEmptyDependencies"
- category = "regular"
- long = "allow-empty-dependencies"
- type = "bool"
- default = "false"
- read_only = true
- help = "if unable to track the dependencies of a rewritten/preprocessed assertion, fail silently"
name = "values"
help = "Block models based on the concrete model values for the free variables."
-[[option]]
- name = "proof"
- smt_name = "produce-proofs"
- category = "regular"
- long = "proof"
- type = "bool"
- default = "false"
- predicates = ["proofEnabledBuild"]
- help = "turn on proof generation"
-
-[[option]]
- name = "checkProofs"
- category = "regular"
- long = "check-proofs"
- type = "bool"
- predicates = ["LFSCEnabledBuild"]
- help = "after UNSAT/VALID, machine-check the generated proof"
-
[[option]]
name = "dumpProofs"
category = "regular"
type = "bool"
default = "false"
help = "calculate sort inference of input problem, convert the input based on monotonic sorts"
-
+
[[option]]
name = "incrementalSolving"
category = "common"
[[option.mode.BITWISE]]
name = "bitwise"
help = "use bitwise comparisons on binary representation of integer for refinement (experimental)"
-
+
[[option]]
name = "solveIntAsBV"
category = "undocumented"
#include "preprocessing/assertion_pipeline.h"
#include "expr/node_manager.h"
-#include "proof/proof.h"
+#include "options/smt_options.h"
#include "proof/proof_manager.h"
#include "theory/rewriter.h"
void AssertionPipeline::replace(size_t i, Node n, ProofGenerator* pgen)
{
- PROOF(ProofManager::currentPM()->addDependence(n, d_nodes[i]););
+ if (options::unsatCores())
+ {
+ ProofManager::currentPM()->addDependence(n, d_nodes[i]);
+ }
if (isProofEnabled())
{
d_pppg->notifyPreprocessed(d_nodes[i], n, pgen);
const std::vector<Node>& addnDeps,
ProofGenerator* pgen)
{
- PROOF(ProofManager::currentPM()->addDependence(n, d_nodes[i]);
- for (const auto& addnDep
- : addnDeps) {
- ProofManager::currentPM()->addDependence(n, addnDep);
- });
+ if (options::unsatCores())
+ {
+ ProofManager::currentPM()->addDependence(n, d_nodes[i]);
+ for (const auto& addnDep : addnDeps)
+ {
+ ProofManager::currentPM()->addDependence(n, addnDep);
+ }
+ }
if (isProofEnabled())
{
d_pppg->notifyPreprocessed(d_nodes[i], n, pgen);
#include <vector>
-#include "options/proof_options.h"
#include "smt/smt_statistics_registry.h"
#include "smt_util/nary_builder.h"
#include "theory/arith/arith_ite_utils.h"
// This pass does not support dependency tracking yet
// (learns substitutions from all assertions so just
// adding addDependence is not enough)
- if (options::unsatCores() || options::fewerPreprocessingHoles())
+ if (options::unsatCores())
{
return true;
}
Node n = Rewriter::rewrite(geq.andNode(leq));
assertionsToPreprocess->push_back(n);
- PROOF(ProofManager::currentPM()->addDependence(n, Node::null()));
-
+ if (options::unsatCores())
+ {
+ ProofManager::currentPM()->addDependence(n, Node::null());
+ }
SubstitutionMap nullMap(&fakeContext);
Theory::PPAssertStatus status CVC4_UNUSED; // just for assertions
status = te->solve(geq, nullMap);
Debug("miplib") << " " << newAssertion << endl;
assertionsToPreprocess->push_back(newAssertion);
- PROOF(ProofManager::currentPM()->addDependence(newAssertion,
- Node::null()));
-
+ if (options::unsatCores())
+ {
+ ProofManager::currentPM()->addDependence(newAssertion,
+ Node::null());
+ }
Debug("miplib") << " assertions to remove: " << endl;
for (vector<TNode>::const_iterator k = asserts[pos_var].begin(),
k_end = asserts[pos_var].end();
#include <vector>
#include "context/cdo.h"
-#include "options/proof_options.h"
#include "smt/smt_statistics_registry.h"
#include "theory/theory_model.h"
PreprocessingPassResult NonClausalSimp::applyInternal(
AssertionPipeline* assertionsToPreprocess)
{
- Assert(!options::unsatCores() && !options::fewerPreprocessingHoles());
+ Assert(!options::unsatCores());
d_preprocContext->spendResource(ResourceManager::Resource::PreprocessStep);
// If in conflict, just return false
Trace("non-clausal-simplify")
<< "conflict in non-clausal propagation" << std::endl;
- Assert(!options::unsatCores() && !options::fewerPreprocessingHoles());
+ Assert(!options::unsatCores());
assertionsToPreprocess->clear();
Node n = NodeManager::currentNM()->mkConst<bool>(false);
assertionsToPreprocess->push_back(n);
- PROOF(ProofManager::currentPM()->addDependence(n, Node::null()));
+ if (options::unsatCores())
+ {
+ ProofManager::currentPM()->addDependence(n, Node::null());
+ }
propagator->setNeedsFinish(true);
return PreprocessingPassResult::CONFLICT;
}
assertionsToPreprocess->clear();
Node n = NodeManager::currentNM()->mkConst<bool>(false);
assertionsToPreprocess->push_back(n);
- PROOF(ProofManager::currentPM()->addDependence(n, Node::null()));
+ if (options::unsatCores())
+ {
+ ProofManager::currentPM()->addDependence(n, Node::null());
+ }
propagator->setNeedsFinish(true);
return PreprocessingPassResult::CONFLICT;
}
assertionsToPreprocess->clear();
Node n = NodeManager::currentNM()->mkConst<bool>(false);
assertionsToPreprocess->push_back(n);
- PROOF(ProofManager::currentPM()->addDependence(n, Node::null()));
+ if (options::unsatCores())
+ {
+ ProofManager::currentPM()->addDependence(n, Node::null());
+ }
propagator->setNeedsFinish(true);
return PreprocessingPassResult::CONFLICT;
}
// equations[0].second); assertionsToPreprocess->clear();
// Node n = NodeManager::currentNM()->mkConst<bool>(false);
// assertionsToPreprocess->push_back(n);
- // PROOF(ProofManager::currentPM()->addDependence(n, Node::null()));
// false); return;
// }
// top_level_substs.simplifyRHS(constantPropagations);
#include <vector>
#include "options/quantifiers_options.h"
-#include "proof/proof_manager.h"
#include "smt/smt_engine.h"
#include "smt/smt_engine_scope.h"
#include "theory/arith/arith_msum.h"
for( int i=0; i<(int)assertions.size(); i++ ){
Trace("macros-debug") << " process assertion " << assertions[i] << std::endl;
if( processAssertion( assertions[i] ) ){
- PROOF(
- if( std::find( macro_assertions.begin(), macro_assertions.end(), assertions[i] )==macro_assertions.end() ){
- macro_assertions.push_back( assertions[i] );
- }
- );
+ if (options::unsatCores()
+ && std::find(macro_assertions.begin(),
+ macro_assertions.end(),
+ assertions[i])
+ == macro_assertions.end())
+ {
+ macro_assertions.push_back(assertions[i]);
+ }
//process this assertion again
i--;
}
if( curr!=assertions[i] ){
curr = Rewriter::rewrite( curr );
Trace("macros-rewrite") << "Rewrite " << assertions[i] << " to " << curr << std::endl;
- //for now, it is dependent upon all assertions involving macros, this is an over-approximation.
- //a more fine-grained unsat core computation would require caching dependencies for each subterm of the formula,
- // which is expensive.
- PROOF(ProofManager::currentPM()->addDependence(curr, assertions[i]);
- for (unsigned j = 0; j < macro_assertions.size(); j++) {
- if (macro_assertions[j] != assertions[i])
- {
- ProofManager::currentPM()->addDependence(
- curr, macro_assertions[j]);
- }
- });
+ // for now, it is dependent upon all assertions involving macros, this
+ // is an over-approximation. a more fine-grained unsat core
+ // computation would require caching dependencies for each subterm of
+ // the formula, which is expensive.
+ if (options::unsatCores())
+ {
+ ProofManager::currentPM()->addDependence(curr, assertions[i]);
+ for (unsigned j = 0; j < macro_assertions.size(); j++)
+ {
+ if (macro_assertions[j] != assertions[i])
+ {
+ ProofManager::currentPM()->addDependence(curr,
+ macro_assertions[j]);
+ }
+ }
+ }
assertions[i] = curr;
retVal = true;
}
for( unsigned i=0; i<children.size(); i++ ){
Node etc = TypeNode::getEnsureTypeCondition( children[i], tno[i] );
if( etc.isNull() ){
- //if this does fail, we are incomplete, since we are eliminating quantified formula corresponding to op,
+ // if this does fail, we are incomplete, since we are eliminating
+ // quantified formula corresponding to op,
// and not ensuring it applies to n when its types are correct.
- //Assert( false );
success = false;
break;
}else if( !etc.isConst() ){
+++ /dev/null
-/********************* */
-/*! \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 */
+++ /dev/null
-/********************* */
-/*! \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 */
+++ /dev/null
-/********************* */
-/*! \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
+++ /dev/null
-/********************* */
-/*! \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
+++ /dev/null
-/********************* */
-/*! \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 */
+++ /dev/null
-/********************* */
-/*! \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 */
+++ /dev/null
-/********************* */
-/*! \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
+++ /dev/null
-/********************* */
-/*! \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 */
+++ /dev/null
-/********************* */
-/*! \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
+++ /dev/null
-/********************* */
-/*! \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 */
*/
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 */
#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"
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)
{
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) {
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()
Assert(d_currentAssertionStack.size());
Debug("proof:cnf") << "CnfProof::popCurrentAssertion "
- << d_currentAssertionStack.back() << std::endl;
+ << d_currentAssertionStack.back().first << std::endl;
d_currentAssertionStack.pop_back();
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 */
#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 {
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;
/** 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;
// 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 */
+++ /dev/null
-/********************* */
-/*! \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
+++ /dev/null
-/********************* */
-/*! \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
+++ /dev/null
-/********************* */
-/*! \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
+++ /dev/null
-/********************* */
-/*! \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
+++ /dev/null
-/********************* */
-/*! \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
+++ /dev/null
-/********************* */
-/*! \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
+++ /dev/null
-/********************* */
-/*! \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 */
+++ /dev/null
-/********************* */
-/*! \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 */
+++ /dev/null
-/********************* */
-/*! \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
+++ /dev/null
-/********************* */
-/*! \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 */
+++ /dev/null
-/********************* */
-/*! \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
+++ /dev/null
-/********************* */
-/*! \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
+++ /dev/null
-/********************* */
-/*! \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 */
#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"
#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)
{
}
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()
{
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();
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;
} 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 << "'";
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);
}
}
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) {
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 */
#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;
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 */
+++ /dev/null
-/********************* */
-/*! \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 */
+++ /dev/null
-/********************* */
-/*! \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 */
+++ /dev/null
-/********************* */
-/*! \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 */
+++ /dev/null
-/********************* */
-/*! \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);
-}
-
-}
-}
+++ /dev/null
-/********************* */
-/*! \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 */
+++ /dev/null
-/********************* */
-/*! \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 */
#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.
#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"
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
}
}
-// 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;
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);
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>
+++ /dev/null
-/********************* */
-/*! \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 */
+++ /dev/null
-/********************* */
-/*! \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 */
+++ /dev/null
-/********************* */
-/*! \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 */
+++ /dev/null
-/********************* */
-/*! \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 */
+++ /dev/null
-/********************* */
-/*! \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 */
+++ /dev/null
-/********************* */
-/*! \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 */
+++ /dev/null
-/********************* */
-/*! \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 */
+++ /dev/null
-/********************* */
-/*! \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 */
#include "prop/bvminisat/simp/SimpSolver.h"
#include "proof/clause_id.h"
-#include "proof/sat_proof.h"
#include "util/statistics_registry.h"
namespace CVC4 {
// }
ClauseId clause_id = ClauseIdError;
d_minisat->addClause(minisat_clause, clause_id);
- THEORY_PROOF(Assert(clause_id != ClauseIdError););
return clause_id;
}
void BVMinisatSatSolver::addMarkerLiteral(SatLiteral lit) {
d_minisat->addMarkerLiteral(BVMinisat::var(toMinisatLit(lit)));
- markUnremovable(lit);
+ markUnremovable(lit);
}
void BVMinisatSatSolver::explain(SatLiteral lit, std::vector<SatLiteral>& explanation) {
std::vector<BVMinisat::Lit> minisat_explanation;
d_minisat->explain(toMinisatLit(lit), minisat_explanation);
for (unsigned i = 0; i < minisat_explanation.size(); ++i) {
- explanation.push_back(toSatLiteral(minisat_explanation[i]));
+ explanation.push_back(toSatLiteral(minisat_explanation[i]));
}
}
d_minisat->popAssumption();
}
-void BVMinisatSatSolver::setResolutionProofLog(
- proof::ResolutionBitVectorProof* bvp)
-{
- d_minisat->setProofLog( bvp );
-}
-
SatVariable BVMinisatSatSolver::newVar(bool isTheoryAtom, bool preRegister, bool canErase){
return d_minisat->newVar(true, true, !canErase);
}
return result;
}
-bool BVMinisatSatSolver::ok() const {
- return d_minisat->okay();
-}
+bool BVMinisatSatSolver::ok() const { return d_minisat->okay(); }
void BVMinisatSatSolver::getUnsatCore(SatClause& unsatCore) {
// TODO add assertion to check the call was after an unsat call
}
SatValue BVMinisatSatSolver::value(SatLiteral l){
- return toSatLiteralValue(d_minisat->value(toMinisatLit(l)));
+ return toSatLiteralValue(d_minisat->value(toMinisatLit(l)));
}
SatValue BVMinisatSatSolver::modelValue(SatLiteral l){
- return toSatLiteralValue(d_minisat->modelValue(toMinisatLit(l)));
+ return toSatLiteralValue(d_minisat->modelValue(toMinisatLit(l)));
}
void BVMinisatSatSolver::unregisterVar(SatLiteral lit) {
} /* namespace CVC4::prop */
} /* namespace CVC4 */
-
-namespace CVC4 {
-template<>
-prop::SatLiteral toSatLiteral< BVMinisat::Solver>(BVMinisat::Solver::TLit lit) {
- return prop::BVMinisatSatSolver::toSatLiteral(lit);
-}
-
-template<>
-void toSatClause< BVMinisat::Solver> (const BVMinisat::Solver::TClause& minisat_cl,
- prop::SatClause& sat_cl) {
- prop::BVMinisatSatSolver::toSatClause(minisat_cl, sat_cl);
-}
-
-}
#include <memory>
#include "context/cdo.h"
-#include "proof/clause_id.h"
-#include "proof/resolution_bitvector_proof.h"
#include "prop/bv_sat_solver_notify.h"
#include "prop/bvminisat/simp/SimpSolver.h"
#include "prop/sat_solver.h"
}
};
- std::unique_ptr<BVMinisat::SimpSolver> d_minisat;
- std::unique_ptr<MinisatNotify> d_minisatNotify;
+ std::unique_ptr<BVMinisat::SimpSolver> d_minisat;
+ std::unique_ptr<MinisatNotify> d_minisatNotify;
unsigned d_assertionsCount;
context::CDO<unsigned> d_assertionsRealCount;
ClauseId addXorClause(SatClause& clause, bool rhs, bool removable) override
{
Unreachable() << "Minisat does not support native XOR reasoning";
+ return ClauseIdError;
}
SatValue propagate() override;
void popAssumption() override;
- void setResolutionProofLog(proof::ResolutionBitVectorProof* bvp) override;
-
private:
/* Disable the default constructor. */
BVMinisatSatSolver() = delete;
#include "base/output.h"
#include "options/bv_options.h"
#include "options/smt_options.h"
-#include "proof/clause_id.h"
-#include "proof/proof_manager.h"
-#include "proof/resolution_bitvector_proof.h"
-#include "proof/sat_proof.h"
-#include "proof/sat_proof_implementation.h"
#include "prop/bvminisat/mtl/Sort.h"
#include "theory/interrupted.h"
#include "util/utility.h"
,
conflict_budget(-1),
propagation_budget(-1),
- asynch_interrupt(false),
- d_bvp(NULL)
+ asynch_interrupt(false)
{
// Create the constant variables
varTrue = newVar(true, false);
if (decisionLevel() > 0) {
cancelUntil(0);
}
-
+
if (!ok) {
id = ClauseIdUndef;
return false;
sort(ps);
Lit p; int i, j;
int falseLiteralsCount = 0;
-
+
for (i = j = 0, p = lit_Undef; i < ps.size(); i++) {
// tautologies are ignored
if (value(ps[i]) == l_True || ps[i] == ~p) {
}
if (value(ps[i]) == l_False) {
- if (!THEORY_PROOF_ON())
- continue;
- ++falseLiteralsCount;
+ continue;
}
ps[j++] = p = ps[i];
}
-
+
ps.shrink(i - j);
clause_added = true;
- Assert(falseLiteralsCount == 0 || THEORY_PROOF_ON());
-
if(falseLiteralsCount == 0) {
if (ps.size() == 0) {
- Assert(!THEORY_PROOF_ON());
return ok = false;
}
else if (ps.size() == 1){
- if(d_bvp){ id = d_bvp->getSatProof()->registerUnitClause(ps[0], INPUT);}
uncheckedEnqueue(ps[0]);
CRef confl_ref = propagate();
ok = (confl_ref == CRef_Undef);
- if(d_bvp){ if (!ok) d_bvp->getSatProof()->finalizeProof(confl_ref); }
return ok;
} else {
CRef cr = ca.alloc(ps, false);
clauses.push(cr);
attachClause(cr);
- if(d_bvp){ id = d_bvp->getSatProof()->registerClause(cr, INPUT);}
- }
- return ok;
- }
-
- if (falseLiteralsCount != 0 && THEORY_PROOF_ON()) {
- // we are in a conflicting state
- if (ps.size() == falseLiteralsCount && falseLiteralsCount == 1) {
- if(d_bvp){ id = d_bvp->getSatProof()->storeUnitConflict(ps[0], INPUT); }
- if(d_bvp){ d_bvp->getSatProof()->finalizeProof(CVC4::BVMinisat::CRef_Lazy); }
- return ok = false;
- }
-
- assign_lt lt(*this);
- sort(ps, lt);
-
- CRef cr = ca.alloc(ps, false);
- clauses.push(cr);
- attachClause(cr);
-
- if(d_bvp){id = d_bvp->getSatProof()->registerClause(cr, INPUT);}
-
- if(ps.size() == falseLiteralsCount) {
- if(d_bvp){ d_bvp->getSatProof()->finalizeProof(cr); }
- return ok = false;
- }
-
- // Check if it propagates
- if (ps.size() == falseLiteralsCount + 1) {
- Clause& cl = ca[cr];
-
- Assert(value(cl[0]) == l_Undef);
- uncheckedEnqueue(cl[0], cr);
- Assert(cl.size() > 1);
- CRef confl = propagate();
- ok = (confl == CRef_Undef);
- if(!ok) {
- if(d_bvp){
- if(ca[confl].size() == 1) {
- id = d_bvp->getSatProof()->storeUnitConflict(ca[confl][0], LEARNT);
- d_bvp->getSatProof()->finalizeProof(CVC4::BVMinisat::CRef_Lazy);
- } else {
- d_bvp->getSatProof()->finalizeProof(confl);
- }
- }
- }
}
+ return ok;
}
return ok;
}
void Solver::detachClause(CRef cr, bool strict) {
const Clause& clause = ca[cr];
- if (d_bvp)
- {
- d_bvp->getSatProof()->markDeleted(cr); }
assert(clause.size() > 1);
return next == var_Undef ? lit_Undef : mkLit(next, rnd_pol ? drand(random_seed) < 0.5 : polarity[next]);
}
-
/*_________________________________________________________________________________________________
|
-| analyze : (confl : Clause*) (out_learnt : vec<Lit>&) (out_btlevel : int&) -> [void]
-|
+| analyze : (confl : Clause*) (out_learnt : vec<Lit>&) (out_btlevel : int&) ->
+[void]
+|
| Description:
| Analyze conflict and produce a reason clause.
-|
+|
| Pre-conditions:
| * 'out_learnt' is assumed to be cleared.
| * Current decision level must be greater than root level.
-|
+|
| Post-conditions:
| * 'out_learnt[0]' is the asserting literal at level 'out_btlevel'.
-| * If out_learnt.size() > 1 then 'out_learnt[1]' has the greatest decision level of the
-| rest of literals. There may be others from the same level though.
-|
+| * If out_learnt.size() > 1 then 'out_learnt[1]' has the greatest decision
+level of the | rest of literals. There may be others from the same level
+though.
+|
|________________________________________________________________________________________________@*/
void Solver::analyze(CRef confl, vec<Lit>& out_learnt, int& out_btlevel, UIP uip)
{
int index = trail.size() - 1;
bool done = false;
-
- if(d_bvp){ d_bvp->getSatProof()->startResChain(confl); }
do{
assert(confl != CRef_Undef); // (otherwise should be UIP)
out_learnt.push(q);
}
- if (level(var(q)) == 0)
- {
- if (d_bvp)
- {
- d_bvp->getSatProof()->resolveOutUnit(q);
- }
- }
}
// Select next clause to look at:
seen[var(p)] = 0;
pathC--;
- if ( pathC > 0 && confl != CRef_Undef ) {
- if(d_bvp){ d_bvp->getSatProof()->addResolutionStep(p, confl, sign(p));}
- }
-
switch (uip) {
case UIP_FIRST:
done = pathC == 0;
// Literal is not redundant
out_learnt[j++] = out_learnt[i1];
}
- else
- {
- if (d_bvp)
- {
- d_bvp->getSatProof()->storeLitRedundant(out_learnt[i1]);
- }
- }
}
}
}else if (ccmin_mode == 1){
return true;
}
-/**
+/**
* Specialized analyzeFinal procedure where we test the consistency
* of the assumptions before backtracking bellow the assumption level.
- *
+ *
* @param p the original uip (may be unit)
* @param confl_clause the conflict clause
* @param out_conflict the conflict in terms of assumptions we are building
assert (decisionLevel() == assumptions.size());
assert (level(var(p)) == assumptions.size());
- out_conflict.clear();
-
+ out_conflict.clear();
+
Clause& cl = ca[confl_clause];
for (int i = 0; i < cl.size(); ++i) {
seen[var(cl[i])] = 1;
}
- int end = options::proof() ? 0 : trail_lim[0];
+ int end = trail_lim[0];
for (int i = trail.size() - 1; i >= end; i--) {
Var x = var(trail[i]);
if (seen[x]) {
if (marker[x] == 2) {
assert (level(x) > 0);
out_conflict.push(~trail[i]);
- } else {
- if(d_bvp){d_bvp->getSatProof()->resolveOutUnit(~(trail[i])); }
}
- } else {
- if(d_bvp){d_bvp->getSatProof()->resolveOutUnit(~p);}
}
} else {
Clause& clause = ca[reason(x)];
- if(d_bvp){d_bvp->getSatProof()->addResolutionStep(trail[i],reason(x), sign(trail[i]));}
for (int j = 1; j < clause.size(); j++)
{
if (level(var(clause[j])) > 0) seen[var(clause[j])] = 1;
- if(d_bvp){
- if (level(var(clause[j])) == 0)
- {
- d_bvp->getSatProof()->resolveOutUnit(clause[j]);
- seen[var(clause[j])] =
- 0; // we don't need to resolve it out again
- }
- }
}
}
seen[x] = 0;
}
- assert (seen[x] == 0);
+ assert(seen[x] == 0);
}
- assert (out_conflict.size());
+ assert(out_conflict.size());
}
/*_________________________________________________________________________________________________
|
| analyzeFinal : (p : Lit) -> [void]
-|
+|
| Description:
-| Specialized analysis procedure to express the final conflict in terms of assumptions.
-| Calculates the (possibly empty) set of assumptions that led to the assignment of 'p', and
-| stores the result in 'out_conflict'.
+| Specialized analysis procedure to express the final conflict in terms of
+assumptions. | Calculates the (possibly empty) set of assumptions that led to
+the assignment of 'p', and | stores the result in 'out_conflict'.
|________________________________________________________________________________________________@*/
void Solver::analyzeFinal(Lit p, vec<Lit>& out_conflict)
{
out_conflict.push(p);
}
- if(d_bvp){
- if (level(var(p)) == 0 && d_bvp->isAssumptionConflict()) {
- Assert(marker[var(p)] == 2);
- if (reason(var(p)) == CRef_Undef) {
- d_bvp->startBVConflict(p);
- }
- }
- }
-
- if (decisionLevel() == 0 && !options::proof()) {
+ if (decisionLevel() == 0)
+ {
return;
}
seen[var(p)] = 1;
- int end = options::proof() ? 0 : trail_lim[0];
-
+ int end = trail_lim[0];
+
for (int i = trail.size()-1; i >= end; i--){
Var x = var(trail[i]);
if (seen[x]) {
}
} else {
Clause& clause = ca[reason(x)];
- if(d_bvp){
- if (d_bvp->isAssumptionConflict() &&
- trail[i] == p) {
- d_bvp->startBVConflict(reason(x));
- } else {
- d_bvp->getSatProof()->addResolutionStep(trail[i], reason(x), sign(trail[i]));
- }
- }
for (int j = 1; j < clause.size(); j++)
{
if (level(var(clause[j])) > 0)
{
seen[var(clause[j])] = 1;
}
- if(d_bvp){
- if (level(var(clause[j])) == 0)
- {
- d_bvp->getSatProof()->resolveOutUnit(clause[j]);
- }
- }
}
}
seen[x] = 0;
lbool Solver::assertAssumption(Lit p, bool propagate) {
// TODO need to somehow mark the assumption as unit in the current context?
// it's not always unit though, but this would be useful for debugging
-
+
// assert(marker[var(p)] == 1);
-
if (decisionLevel() > assumptions.size()) {
cancelUntil(assumptions.size());
}
// run the propagation
if (propagate) {
only_bcp = true;
- ccmin_mode = 0;
+ ccmin_mode = 0;
lbool result = search(-1);
- return result;
+ return result;
} else {
return l_True;
}
// make sure it wasn't already marked
Assert(marker[var] == 0);
marker[var] = 1;
- if(d_bvp){d_bvp->getSatProof()->registerAssumption(var);}
}
-
/*_________________________________________________________________________________________________
|
| propagate : [void] -> [Clause*]
-|
+|
| Description:
-| Propagates all enqueued facts. If a conflict arises, the conflicting clause is returned,
-| otherwise CRef_Undef.
-|
+| Propagates all enqueued facts. If a conflict arises, the conflicting clause
+is returned, | otherwise CRef_Undef.
+|
| Post-conditions:
| * the propagation queue is empty, even if there was a conflict.
|________________________________________________________________________________________________@*/
return confl;
}
-
/*_________________________________________________________________________________________________
|
| reduceDB : () -> [void]
-|
+|
| Description:
-| Remove half of the learnt clauses, minus the clauses locked by the current assignment. Locked
-| clauses are clauses that are reason to some assignment. Binary clauses are never removed.
+| Remove half of the learnt clauses, minus the clauses locked by the current
+assignment. Locked | clauses are clauses that are reason to some assignment.
+Binary clauses are never removed.
|________________________________________________________________________________________________@*/
-struct reduceDB_lt {
- ClauseAllocator& ca;
- reduceDB_lt(ClauseAllocator& ca_) : ca(ca_) {}
- bool operator () (CRef x, CRef y) {
- return ca[x].size() > 2 && (ca[y].size() == 2 || ca[x].activity() < ca[y].activity()); }
+struct reduceDB_lt
+{
+ ClauseAllocator& ca;
+ reduceDB_lt(ClauseAllocator& ca_) : ca(ca_) {}
+ bool operator()(CRef x, CRef y)
+ {
+ return ca[x].size() > 2
+ && (ca[y].size() == 2 || ca[x].activity() < ca[y].activity());
+ }
};
void Solver::reduceDB()
{
Clause& clause = ca[cs[i]];
if (satisfied(clause))
{
- if (locked(clause))
- {
- // store a resolution of the literal clause propagated
- if (d_bvp)
- {
- d_bvp->getSatProof()->storeUnitResolution(clause[0]);
- }
- }
removeClause(cs[i]);
}
else
order_heap.build(vs);
}
-
/*_________________________________________________________________________________________________
|
| simplify : [void] -> [bool]
-|
+|
| Description:
-| Simplify the clause database according to the current top-level assigment. Currently, the only
-| thing done here is the removal of satisfied clauses, but more things can be put here.
+| Simplify the clause database according to the current top-level assigment.
+Currently, the only | thing done here is the removal of satisfied clauses,
+but more things can be put here.
|________________________________________________________________________________________________@*/
bool Solver::simplify()
{
return true;
}
-
/*_________________________________________________________________________________________________
|
| search : (nof_conflicts : int) (params : const SearchParams&) -> [lbool]
-|
+|
| Description:
-| Search for a model the specified number of conflicts.
+| Search for a model the specified number of conflicts.
| NOTE! Use negative value for 'nof_conflicts' indicate infinity.
-|
+|
| Output:
-| 'l_True' if a partial assigment that is consistent with respect to the clauseset is found. If
-| all variables are decision variables, this means that the clause set is satisfiable. 'l_False'
-| if the clause set is unsatisfiable. 'l_Undef' if the bound on number of conflicts is reached.
+| 'l_True' if a partial assigment that is consistent with respect to the
+clauseset is found. If | all variables are decision variables, this means
+that the clause set is satisfiable. 'l_False' | if the clause set is
+unsatisfiable. 'l_Undef' if the bound on number of conflicts is reached.
|________________________________________________________________________________________________@*/
lbool Solver::search(int nof_conflicts, UIP uip)
{
if (decisionLevel() == 0) {
// can this happen for bv?
- if(d_bvp){ d_bvp->getSatProof()->finalizeProof(confl);}
return l_False;
}
learnts.push(cr);
attachClause(cr);
claBumpActivity(ca[cr]);
- if(d_bvp){
- ClauseId id = d_bvp->getSatProof()->registerClause(cr, LEARNT);
- PSTATS(
- std::unordered_set<int> cl_levels;
- for (int i = 0; i < learnt_clause.size(); ++i) {
- cl_levels.insert(level(var(learnt_clause[i])));
- }
- if( d_bvp ){ d_bvp->getSatProof()->storeClauseGlue(id, cl_levels.size()); }
- )
- d_bvp->getSatProof()->endResChain(id);
- }
}
-
+
if (learnt_clause.size() == 1) {
// learning a unit clause
- if(d_bvp){ d_bvp->getSatProof()->endResChain(learnt_clause[0]);}
}
-
+
// if the uip was an assumption we are unsat
if (level(var(p)) <= assumptions.size()) {
for (int i = 0; i < learnt_clause.size(); ++i) {
- assert (level(var(learnt_clause[i])) <= decisionLevel());
+ assert(level(var(learnt_clause[i])) <= decisionLevel());
seen[var(learnt_clause[i])] = 1;
}
- // Starting new resolution chain for bit-vector proof
- if( d_bvp ){
- if (cr == CRef_Undef) {
- d_bvp->startBVConflict(learnt_clause[0]);
- }
- else {
- d_bvp->startBVConflict(cr);
- }
- }
analyzeFinal(p, conflict);
- if(d_bvp){ d_bvp->endBVConflict(conflict); }
Debug("bvminisat::search") << OUTPUT_TAG << " conflict on assumptions " << std::endl;
return l_False;
}
if (!CVC4::options::bvEagerExplanations()) {
- // check if uip leads to a conflict
+ // check if uip leads to a conflict
if (backtrack_level < assumptions.size()) {
cancelUntil(assumptions.size());
uncheckedEnqueue(p, cr);
-
+
CRef new_confl = propagate();
if (new_confl != CRef_Undef) {
// we have a conflict we now need to explain it
- // TODO: proof for analyzeFinal2
- if(d_bvp){ d_bvp->startBVConflict(new_confl); }
analyzeFinal2(p, new_confl, conflict);
- if(d_bvp){ d_bvp->endBVConflict(conflict); }
return l_False;
}
}
cancelUntil(backtrack_level);
uncheckedEnqueue(p, cr);
-
-
+
varDecayActivity();
claDecayActivity();
max_learnts *= learntsize_inc;
if (verbosity >= 1)
- printf("| %9d | %7d %8d %8d | %8d %8d %6.0f | %6.3f %% |\n",
- (int)conflicts,
- (int)dec_vars - (trail_lim.size() == 0 ? trail.size() : trail_lim[0]), nClauses(), (int)clauses_literals,
- (int)max_learnts, nLearnts(), (double)learnts_literals/nLearnts(), progressEstimate()*100);
+ printf("| %9d | %7d %8d %8d | %8d %8d %6.0f | %6.3f %% |\n",
+ (int)conflicts,
+ (int)dec_vars
+ - (trail_lim.size() == 0 ? trail.size()
+ : trail_lim[0]),
+ nClauses(),
+ (int)clauses_literals,
+ (int)max_learnts,
+ nLearnts(),
+ (double)learnts_literals / nLearnts(),
+ progressEstimate() * 100);
}
}else{
withinBudget(ResourceManager::Resource::BvSatConflictsStep);
}
catch (const CVC4::theory::Interrupted& e) {
- // do some clean-up and rethrow
- cancelUntil(assumptions.size());
- throw e;
+ // do some clean-up and rethrow
+ cancelUntil(assumptions.size());
+ throw e;
}
if ((decisionLevel() > assumptions.size() && nof_conflicts >= 0
newDecisionLevel();
}else if (value(p) == l_False){
marker[var(p)] = 2;
-
- if(d_bvp){ d_bvp->markAssumptionConflict(); }
+
analyzeFinal(~p, conflict);
- if(d_bvp){ d_bvp->endBVConflict(conflict); }
Debug("bvminisat::search") << OUTPUT_TAG << " assumption false, we're unsat" << std::endl;
return l_False;
}else{
conflict.clear();
ccmin_mode = 0;
-
+
if (!ok) return l_False;
solves++;
//=================================================================================================
// Bitvector propagations
-//
+//
void Solver::explain(Lit p, std::vector<Lit>& explanation) {
Debug("bvminisat::explain") << OUTPUT_TAG << "starting explain of " << p << std::endl;
// top level fact, no explanation necessary
if (level(var(p)) == 0) {
- if(d_bvp){
- // the only way a marker variable is
- if (reason(var(p)) == CRef_Undef) {
- d_bvp->startBVConflict(p);
- vec<Lit> confl;
- confl.push(p);
- d_bvp->endBVConflict(confl);
- return;
- }
- }
- if (!THEORY_PROOF_ON())
- return;
+ return;
}
-
+
seen[var(p)] = 1;
// if we are called at decisionLevel = 0 trail_lim is empty
- int bottom = options::proof() ? 0 : trail_lim[0];
+ int bottom = trail_lim[0];
for (int i = trail.size()-1; i >= bottom; i--){
Var x = var(trail[i]);
if (seen[x]) {
explanation.push_back(trail[i]);
} else {
Assert(level(x) == 0);
- if(d_bvp){ d_bvp->getSatProof()->resolveOutUnit(~(trail[i])); }
}
-
} else {
Clause& clause = ca[reason(x)];
- if(d_bvp){
- if (p == trail[i]) {
- d_bvp->startBVConflict(reason(var(p)));
- } else {
- d_bvp->getSatProof()->addResolutionStep(trail[i], reason(x), sign(trail[i]));
- }
- }
for (int j = 1; j < clause.size(); j++)
{
- if (level(var(clause[j])) > 0 || options::proof())
+ if (level(var(clause[j])) > 0)
{
seen[var(clause[j])] = 1;
}
}
}
seen[var(p)] = 0;
-
- if(d_bvp){
- vec<Lit> conflict_clause;
- conflict_clause.push(p);
- for(unsigned i = 0; i < explanation.size(); ++i) {
- conflict_clause.push(~explanation[i]);
- }
- d_bvp->endBVConflict(conflict_clause);
- }
-}
-
-void Solver::setProofLog(proof::ResolutionBitVectorProof* bvp)
-{
- d_bvp = bvp;
- d_bvp->initSatProof(this);
- d_bvp->getSatProof()->registerTrueLit(mkLit(varTrue, false));
- d_bvp->getSatProof()->registerFalseLit(mkLit(varFalse, true));
}
//=================================================================================================
// Writing CNF to DIMACS:
-//
+//
// FIXME: this needs to be rewritten completely.
static Var mapVar(Var x, vec<Var>& map, Var& max)
for (int i = 0; i < clauses.size(); i++)
if (!satisfied(ca[clauses[i]]))
cnt++;
-
+
for (int i = 0; i < clauses.size(); i++)
if (!satisfied(ca[clauses[i]])){
Clause& clause = ca[clauses[i]];
Lit p = mkLit(v, s);
// printf(" >>> RELOCING: %s%d\n", sign(p)?"-":"", var(p)+1);
vec<Watcher>& ws = watches[p];
- for (int j = 0; j < ws.size(); j++)
- ca.reloc(ws[j].cref, to, d_bvp ? d_bvp->getSatProof() : NULL);
+ for (int j = 0; j < ws.size(); j++) ca.reloc(ws[j].cref, to);
}
// All reasons:
Var v = var(trail[i]);
if (reason(v) != CRef_Undef && (ca[reason(v)].reloced() || locked(ca[reason(v)])))
- ca.reloc(vardata[v].reason, to, d_bvp ? d_bvp->getSatProof() : NULL);
+ ca.reloc(vardata[v].reason, to);
}
// All learnt:
//
- for (int i = 0; i < learnts.size(); i++)
- ca.reloc(learnts[i], to, d_bvp ? d_bvp->getSatProof() : NULL);
+ for (int i = 0; i < learnts.size(); i++) ca.reloc(learnts[i], to);
// All original:
//
- for (int i = 0; i < clauses.size(); i++)
- ca.reloc(clauses[i], to, d_bvp ? d_bvp->getSatProof() : NULL);
-
- if(d_bvp){ d_bvp->getSatProof()->finishUpdateCRef(); }
+ for (int i = 0; i < clauses.size(); i++) ca.reloc(clauses[i], to);
}
{
// Initialize the next region to a size corresponding to the estimated utilization degree. This
// is not precise but should avoid some unnecessary reallocations for the new region:
- ClauseAllocator to(ca.size() - ca.wasted());
- Debug("bvminisat") << " BVMinisat::Garbage collection \n";
+ ClauseAllocator to(ca.size() - ca.wasted());
+ Debug("bvminisat") << " BVMinisat::Garbage collection \n";
relocAll(to);
if (verbosity >= 2)
- printf("| Garbage collection: %12d bytes => %12d bytes |\n",
- ca.size()*ClauseAllocator::Unit_Size, to.size()*ClauseAllocator::Unit_Size);
+ printf(
+ "| Garbage collection: %12d bytes => %12d bytes |\n",
+ ca.size() * ClauseAllocator::Unit_Size,
+ to.size() * ClauseAllocator::Unit_Size);
to.moveTo(ca);
}
-void ClauseAllocator::reloc(CRef& cr,
- ClauseAllocator& to,
- CVC4::TSatProof<Solver>* proof)
+void ClauseAllocator::reloc(CRef& cr, ClauseAllocator& to)
{
- CRef old = cr; // save the old reference
-
Clause& c = operator[](cr);
if (c.reloced()) { cr = c.relocation(); return; }
-
+
cr = to.alloc(c, c.learnt());
c.relocate(cr);
- if (proof)
- {
- proof->updateCRef(old, cr);
- }
-
- // Copy extra data-fields:
- // (This could be cleaned-up. Generalize Clause-constructor to be applicable here instead?)
+
+ // Copy extra data-fields:
+ // (This could be cleaned-up. Generalize Clause-constructor to be applicable
+ // here instead?)
to[cr].mark(c.mark());
if (to[cr].learnt()) to[cr].activity() = c.activity();
else if (to[cr].has_extra()) to[cr].calcAbstraction();
#include "context/context.h"
#include "proof/clause_id.h"
-#include "proof/sat_proof.h"
#include "prop/bvminisat/core/SolverTypes.h"
#include "prop/bvminisat/mtl/Alg.h"
#include "prop/bvminisat/mtl/Heap.h"
class Solver;
}
-// TODO (aozdemir) replace this forward declaration with an include
-namespace proof {
-class ResolutionBitVectorProof;
-}
-
namespace BVMinisat {
/** Interface for minisat callbacks */
//=================================================================================================
// Solver -- the main class:
class Solver {
- friend class CVC4::TSatProof< CVC4::BVMinisat::Solver>;
public:
typedef Var TVar;
typedef Lit TLit;
- typedef Clause TClause;
+ typedef Clause TClause;
typedef CRef TCRef;
typedef vec<Lit> TLitVec;
Var trueVar() const { return varTrue; }
Var falseVar() const { return varFalse; }
-
- bool addClause (const vec<Lit>& ps, ClauseId& id); // Add a clause to the solver.
+ bool addClause(const vec<Lit>& ps,
+ ClauseId& id); // Add a clause to the solver.
bool addEmptyClause(); // Add the empty clause, making the solver contradictory.
- bool addClause (Lit p, ClauseId& id); // Add a unit clause to the solver.
- bool addClause (Lit p, Lit q, ClauseId& id); // Add a binary clause to the solver.
- bool addClause (Lit p, Lit q, Lit r, ClauseId& id); // Add a ternary clause to the solver.
+ bool addClause(Lit p, ClauseId& id); // Add a unit clause to the solver.
+ bool addClause(Lit p,
+ Lit q,
+ ClauseId& id); // Add a binary clause to the solver.
+ bool addClause(Lit p,
+ Lit q,
+ Lit r,
+ ClauseId& id); // Add a ternary clause to the solver.
bool addClause_( vec<Lit>& ps, ClauseId& id); // Add a clause to the solver without making superflous internal copy. Will
// change the passed vector 'ps'.
void toDimacs (const char* file, Lit p);
void toDimacs (const char* file, Lit p, Lit q);
void toDimacs (const char* file, Lit p, Lit q, Lit r);
-
+
// Variable mode:
- //
+ //
void setPolarity (Var v, bool b); // Declare which polarity the decision heuristic should use for a variable. Requires mode 'polarity_user'.
void setDecisionVar (Var v, bool b); // Declare if a variable should be eligible for selection in the decision heuristic.
void addMarkerLiteral(Var var);
- bool need_to_propagate; // true if we added new clauses, set to true in propagation
+ bool need_to_propagate; // true if we added new clauses, set to true in
+ // propagation
bool only_bcp; // solving mode in which only boolean constraint propagation is done
void setOnlyBCP (bool val) { only_bcp = val;}
void explain(Lit l, std::vector<Lit>& explanation);
- void setProofLog(CVC4::proof::ResolutionBitVectorProof* bvp);
-
protected:
// has a clause been added
int64_t conflict_budget; // -1 means no budget.
int64_t propagation_budget; // -1 means no budget.
bool asynch_interrupt;
-
- //proof log
- CVC4::proof::ResolutionBitVectorProof* d_bvp;
// Main internal methods:
//
inline int Solver::nVars () const { return vardata.size(); }
inline int Solver::nFreeVars () const { return (int)dec_vars - (trail_lim.size() == 0 ? trail.size() : trail_lim[0]); }
inline void Solver::setPolarity (Var v, bool b) { polarity[v] = b; }
-inline void Solver::setDecisionVar(Var v, bool b)
-{
- if ( b && !decision[v]) dec_vars++;
- else if (!b && decision[v]) dec_vars--;
+inline void Solver::setDecisionVar(Var v, bool b)
+{
+ if (b && !decision[v])
+ dec_vars++;
+ else if (!b && decision[v])
+ dec_vars--;
- decision[v] = b;
- insertVarOrder(v);
+ decision[v] = b;
+ insertVarOrder(v);
}
inline void Solver::setConfBudget(int64_t x){ conflict_budget = conflicts + x; }
inline void Solver::setPropBudget(int64_t x){ propagation_budget = propagations + x; }
const Lit lit_Undef = { -2 }; // }- Useful special constants.
const Lit lit_Error = { -1 }; // }
-
//=================================================================================================
// Lifted booleans:
//
-// NOTE: this implementation is optimized for the case when comparisons between values are mostly
-// between one variable and one constant. Some care had to be taken to make sure that gcc
-// does enough constant propagation to produce sensible code, and this appears to be somewhat
-// fragile unfortunately.
-
+// NOTE: this implementation is optimized for the case when comparisons between
+// values are mostly
+// between one variable and one constant. Some care had to be taken to
+// make sure that gcc does enough constant propagation to produce sensible
+// code, and this appears to be somewhat fragile unfortunately.
#ifndef l_True
#define l_True (lbool((uint8_t)0)) // gcc does not do constant propagation if these are real constants.
bool operator != (lbool b) const { return !(*this == b); }
lbool operator ^ (bool b) const { return lbool((uint8_t)(value^(uint8_t)b)); }
- lbool operator && (lbool b) const {
- uint8_t sel = (this->value << 1) | (b.value << 3);
- uint8_t v = (0xF7F755F4 >> sel) & 3;
- return lbool(v); }
+ lbool operator&&(lbool b) const
+ {
+ uint8_t sel = (this->value << 1) | (b.value << 3);
+ uint8_t v = (0xF7F755F4 >> sel) & 3;
+ return lbool(v);
+ }
lbool operator || (lbool b) const {
uint8_t sel = (this->value << 1) | (b.value << 3);
header.reloced = 0;
header.size = ps.size();
- for (int i = 0; i < ps.size(); i++)
- data[i].lit = ps[i];
+ for (int i = 0; i < ps.size(); i++) data[i].lit = ps[i];
if (header.has_extra){
if (header.learnt)
- data[header.size].act = 0;
- else
- calcAbstraction(); }
+ data[header.size].act = 0;
+ else
+ calcAbstraction();
+ }
}
public:
RegionAllocator<uint32_t>::free(clauseWord32Size(c.size(), c.has_extra()));
}
- void reloc(CRef& cr,
- ClauseAllocator& to,
- CVC4::TSatProof<Solver>* proof = NULL);
+ void reloc(CRef& cr, ClauseAllocator& to);
};
public:
OccLists(const Deleted& d) : deleted(d) {}
-
+
void init (const Idx& idx){ occs.growTo(toInt(idx)+1); dirty.growTo(toInt(idx)+1, 0); }
// Vec& operator[](const Idx& idx){ return occs[toInt(idx)]; }
Vec& operator[](const Idx& idx){ return occs[toInt(idx)]; }
typedef Map<CRef, T, CRefHash> HashTable;
HashTable map;
-
+
public:
// Size-operations:
void clear () { map.clear(); }
int size () const { return map.elems(); }
-
// Insert/Remove/Test mapping:
void insert (CRef cr, const T& t){ map.insert(cr, t); }
void growTo (CRef cr, const T& t){ map.insert(cr, t); } // NOTE: for compatibility
printf(" --- size = %d, bucket_count = %d\n", size(), map.bucket_count()); }
};
-
/*_________________________________________________________________________________________________
|
| subsumes : (other : const Clause&) -> Lit
-|
+|
| Description:
-| Checks if clause subsumes 'other', and at the same time, if it can be used to simplify 'other'
-| by subsumption resolution.
-|
+| Checks if clause subsumes 'other', and at the same time, if it can be
+used to simplify 'other' | by subsumption resolution.
+|
| Result:
| lit_Error - No subsumption or simplification
| lit_Undef - Clause subsumes 'other'
#include "options/bv_options.h"
#include "options/smt_options.h"
#include "proof/clause_id.h"
-#include "proof/proof.h"
#include "prop/bvminisat/mtl/Sort.h"
#include "prop/bvminisat/utils/System.h"
asymm_lits(0),
eliminated_vars(0),
elimorder(1),
- use_simplification(!PROOF_ON()),
+ use_simplification(true),
occurs(ClauseDeleted(ca)),
elim_heap(ElimLt(n_occ)),
bwdsub_assigns(0),
SimpSolver::~SimpSolver()
{
- // CVC4::StatisticsRegistry::unregisterStat(&total_eliminate_time);
+ // CVC4::StatisticsRegistry::unregisterStat(&total_eliminate_time);
}
touched .push(0);
elim_heap .insert(v);
if (freeze) {
- setFrozen(v, true);
+ setFrozen(v, true);
}
}
return v;
lbool SimpSolver::solve_(bool do_simp, bool turn_off_simp)
{
only_bcp = false;
-
+
vec<Var> extra_frozen;
lbool result = l_True;
const Clause& clause = ca[cr];
if (use_simplification)
+ {
for (int i = 0; i < clause.size(); i++)
{
n_occ[toInt(clause[i])]--;
updateElimHeap(var(clause[i]));
occurs.smudge(var(clause[i]));
}
-
- Solver::removeClause(cr);
+ }
+ Solver::removeClause(cr);
}
for (int i = 0; i < pos.size(); i++)
for (int j = 0; j < neg.size(); j++)
- if (merge(ca[pos[i]], ca[neg[j]], v, clause_size) &&
- (++cnt > cls.size() + grow || (clause_lim != -1 && clause_size > clause_lim)))
- return true;
+ if (merge(ca[pos[i]], ca[neg[j]], v, clause_size)
+ && (++cnt > cls.size() + grow
+ || (clause_lim != -1 && clause_size > clause_lim)))
+ return true;
// Delete and store old clauses:
eliminated[v] = true;
mkElimClause(elimclauses, ~mkLit(v));
}
- for (int i = 0; i < cls.size(); i++)
- removeClause(cls[i]);
+ for (int i = 0; i < cls.size(); i++) removeClause(cls[i]);
// Produce clauses in cross product:
vec<Lit>& resolvent = add_tmp;
// Free occurs list for this variable:
occurs[v].clear(true);
-
+
// Free watchers lists for this variable, if possible:
if (watches[ mkLit(v)].size() == 0) watches[ mkLit(v)].clear(true);
if (watches[~mkLit(v)].size() == 0) watches[~mkLit(v)].clear(true);
eliminated[v] = true;
setDecisionVar(v, false);
const vec<CRef>& cls = occurs.lookup(v);
-
+
vec<Lit>& subst_clause = add_tmp;
for (int i = 0; i < cls.size(); i++){
Clause& clause = ca[cls[i]];
{
// CVC4::TimerStat::CodeTimer codeTimer(total_eliminate_time);
-
+
if (!simplify())
return false;
else if (!use_simplification)
gatherTouchedClauses();
// printf(" ## (time = %6.2f s) BWD-SUB: queue = %d, trail = %d\n", cpuTime(), subsumption_queue.size(), trail.size() - bwdsub_assigns);
- if ((subsumption_queue.size() > 0 || bwdsub_assigns < trail.size()) &&
- !backwardSubsumptionCheck(true)){
- ok = false; goto cleanup; }
+ if ((subsumption_queue.size() > 0 || bwdsub_assigns < trail.size())
+ && !backwardSubsumptionCheck(true))
+ {
+ ok = false;
+ goto cleanup;
+ }
// Empty elim_heap and return immediately on user-interrupt:
if (asynch_interrupt){
// printf(" ## (time = %6.2f s) ELIM: vars = %d\n", cpuTime(), elim_heap.size());
for (int cnt = 0; !elim_heap.empty(); cnt++){
Var elim = elim_heap.removeMin();
-
+
if (asynch_interrupt) break;
if (isEliminated(elim) || value(elim) != l_Undef) continue;
}
if (verbosity >= 1 && elimclauses.size() > 0)
- printf("| Eliminated clauses: %10.2f Mb |\n",
- double(elimclauses.size() * sizeof(uint32_t)) / (1024*1024));
+ printf(
+ "| Eliminated clauses: %10.2f Mb "
+ " |\n",
+ double(elimclauses.size() * sizeof(uint32_t)) / (1024 * 1024));
return ok;
{
// Initialize the next region to a size corresponding to the estimated utilization degree. This
// is not precise but should avoid some unnecessary reallocations for the new region:
- ClauseAllocator to(ca.size() - ca.wasted());
+ ClauseAllocator to(ca.size() - ca.wasted());
cleanUpClauses();
to.extra_clause_field = ca.extra_clause_field; // NOTE: this is important to keep (or lose) the extra fields.
relocAll(to);
Solver::relocAll(to);
if (verbosity >= 2)
- printf("| Garbage collection: %12d bytes => %12d bytes |\n",
- ca.size()*ClauseAllocator::Unit_Size, to.size()*ClauseAllocator::Unit_Size);
+ printf(
+ "| Garbage collection: %12d bytes => %12d bytes |\n",
+ ca.size() * ClauseAllocator::Unit_Size,
+ to.size() * ClauseAllocator::Unit_Size);
to.moveTo(ca);
}
#ifdef CVC4_USE_CADICAL
#include "base/check.h"
-#include "proof/sat_proof.h"
namespace CVC4 {
namespace prop {
}
}
- if (PROOF_ON() && d_cnfProof)
- {
- d_cnfProof->pushCurrentDefinition(node);
- }
-
ClauseId clause_id = d_satSolver->addClause(c, d_removable);
if (clause_id == ClauseIdUndef) return; // nothing to store (no clause was added)
- if (PROOF_ON() && d_cnfProof)
+ if (d_cnfProof && clause_id != ClauseIdError)
{
- if (clause_id != ClauseIdError)
- {
- d_cnfProof->registerConvertedClause(clause_id);
- }
- d_cnfProof->popCurrentDefinition();
- };
+ d_cnfProof->registerConvertedClause(clause_id);
+ }
}
void CnfStream::assertClause(TNode node, SatLiteral a) {
// non-empty and that we are not associating a bogus assertion with the
// clause. This should be ok because we use the mapping back to assertions
// for clauses from input assertions only.
- PROOF(if (d_cnfProof) { d_cnfProof->pushCurrentAssertion(Node::null()); });
+ if (d_cnfProof)
+ {
+ d_cnfProof->pushCurrentAssertion(Node::null());
+ }
lit = toCNF(n, false);
- PROOF(if (d_cnfProof) { d_cnfProof->popCurrentAssertion(); });
+ if (d_cnfProof)
+ {
+ d_cnfProof->popCurrentAssertion();
+ }
// Store backward-mappings
// These may already exist
// If the node is a conjunction, we handle each conjunct separately
for(TNode::const_iterator conjunct = node.begin(), node_end = node.end();
conjunct != node_end; ++conjunct ) {
- PROOF(if (d_cnfProof) d_cnfProof->setCnfDependence(*conjunct, node););
convertAndAssert(*conjunct, false);
}
} else {
// If the node is a conjunction, we handle each conjunct separately
for(TNode::const_iterator conjunct = node.begin(), node_end = node.end();
conjunct != node_end; ++conjunct ) {
- PROOF(if (d_cnfProof) d_cnfProof->setCnfDependence((*conjunct).negate(), node.negate()););
convertAndAssert(*conjunct, true);
}
}
clause[1] = q;
assertClause(node, clause);
} else {// Construct the
- PROOF(if (d_cnfProof) d_cnfProof->setCnfDependence(node[0], node.negate()););
- PROOF(if (d_cnfProof) d_cnfProof->setCnfDependence(node[1].negate(), node.negate()););
// !(p => q) is the same as (p && ~q)
convertAndAssert(node[0], false);
convertAndAssert(node[1], true);
void TseitinCnfStream::convertAndAssert(TNode node,
bool removable,
bool negated,
- ProofRule proof_id,
- TNode from) {
+ bool input)
+{
Debug("cnf") << "convertAndAssert(" << node
<< ", removable = " << (removable ? "true" : "false")
<< ", negated = " << (negated ? "true" : "false") << ")" << endl;
d_removable = removable;
- PROOF
- (if (d_cnfProof) {
- Node assertion = negated ? node.notNode() : (Node)node;
- Node from_assertion = negated? from.notNode() : (Node) from;
-
- if (proof_id != RULE_INVALID) {
- d_cnfProof->pushCurrentAssertion(from.isNull() ? assertion : from_assertion);
- d_cnfProof->registerAssertion(from.isNull() ? assertion : from_assertion, proof_id);
- }
- else {
- d_cnfProof->pushCurrentAssertion(assertion);
- d_cnfProof->registerAssertion(assertion, proof_id);
- }
- });
+ if (d_cnfProof)
+ {
+ d_cnfProof->pushCurrentAssertion(negated ? node.notNode() : (Node)node,
+ input);
+ }
convertAndAssert(node, negated);
- PROOF
- (if (d_cnfProof) {
- d_cnfProof->popCurrentAssertion();
- });
+ if (d_cnfProof)
+ {
+ d_cnfProof->popCurrentAssertion();
+ }
}
void TseitinCnfStream::convertAndAssert(TNode node, bool negated) {
* @param node node to convert and assert
* @param removable whether the sat solver can choose to remove the clauses
* @param negated whether we are asserting the node negated
+ * @param input whether it is an input assertion (rather than a lemma). This
+ * information is only relevant for unsat core tracking.
*/
- virtual void convertAndAssert(TNode node, bool removable, bool negated,
- ProofRule proof_id,
- TNode from = TNode::null()) = 0;
+ virtual void convertAndAssert(TNode node,
+ bool removable,
+ bool negated,
+ bool input = false) = 0;
/**
* Get the node that is represented by the given SatLiteral.
* @param node the formula to assert
* @param removable is this something that can be erased
* @param negated true if negated
+ * @param input whether it is an input assertion (rather than a lemma). This
+ * information is only relevant for unsat core tracking.
*/
void convertAndAssert(TNode node,
bool removable,
bool negated,
- ProofRule rule,
- TNode from = TNode::null()) override;
+ bool input = false) override;
private:
/**
#include "prop/cryptominisat.h"
#include "base/check.h"
-#include "proof/clause_id.h"
-#include "proof/sat_proof.h"
#include <cryptominisat5/cryptominisat.h>
CryptoMinisatSolver::~CryptoMinisatSolver() {}
ClauseId CryptoMinisatSolver::addXorClause(SatClause& clause,
- bool rhs,
- bool removable) {
+ bool rhs,
+ bool removable)
+{
Debug("sat::cryptominisat") << "Add xor clause " << clause <<" = " << rhs << "\n";
if (!d_okay) {
}
++(d_statistics.d_xorClausesAdded);
-
+
// ensure all sat literals have positive polarity by pushing
// the negation on the result
std::vector<CMSatVar> xor_clause;
}
++(d_statistics.d_clausesAdded);
-
+
std::vector<CMSat::Lit> internal_clause;
toInternalClause(clause, internal_clause);
bool nowOkay = d_solver->add_clause(internal_clause);
ClauseId freshId;
- if (THEORY_PROOF_ON())
- {
- freshId = ClauseId(ProofManager::currentPM()->nextId());
- // If this clause results in a conflict, then `nowOkay` may be false, but
- // we still need to register this clause as used. Thus, we look at
- // `d_okay` instead
- if (d_bvp && d_okay)
- {
- d_bvp->registerUsedClause(freshId, clause);
- }
- }
- else
- {
- freshId = ClauseIdError;
- }
+ freshId = ClauseIdError;
d_okay &= nowOkay;
return freshId;
}
-bool CryptoMinisatSolver::ok() const {
- return d_okay;
-}
-
+bool CryptoMinisatSolver::ok() const { return d_okay; }
SatVariable CryptoMinisatSolver::newVar(bool isTheoryAtom, bool preRegister, bool canErase){
d_solver->new_var();
return toSatLiteralValue(value);
}
-SatValue CryptoMinisatSolver::modelValue(SatLiteral l){
- return value(l);
-}
+SatValue CryptoMinisatSolver::modelValue(SatLiteral l) { return value(l); }
unsigned CryptoMinisatSolver::getAssertionLevel() const {
Unreachable() << "No interface to get assertion level in Cryptominisat";
- return -1;
-}
-
-void CryptoMinisatSolver::setClausalProofLog(proof::ClausalBitVectorProof* bvp)
-{
- d_bvp = bvp;
- d_solver->set_drat(&bvp->getDratOstream(), false);
+ return -1;
}
// Satistics for CryptoMinisatSolver
#ifdef CVC4_USE_CRYPTOMINISAT
-#include "proof/clausal_bitvector_proof.h"
#include "prop/sat_solver.h"
// Cryptominisat has name clashes with the other Minisat implementations since
SatValue modelValue(SatLiteral l) override;
unsigned getAssertionLevel() const override;
- void setClausalProofLog(proof::ClausalBitVectorProof* bvp) override;
private:
class Statistics
void init();
std::unique_ptr<CMSat::SATSolver> d_solver;
- proof::ClausalBitVectorProof* d_bvp;
unsigned d_numVariables;
bool d_okay;
SatVariable d_true;
#ifdef CVC4_USE_KISSAT
#include "base/check.h"
-#include "proof/sat_proof.h"
namespace CVC4 {
namespace prop {
#include "options/prop_options.h"
#include "options/smt_options.h"
#include "proof/clause_id.h"
+#include "proof/cnf_proof.h"
#include "proof/proof_manager.h"
#include "proof/sat_proof.h"
#include "proof/sat_proof_implementation.h"
propagation_budget(-1),
asynch_interrupt(false)
{
- PROOF(ProofManager::currentPM()->initSatProof(this);)
+ if (options::unsatCores())
+ {
+ ProofManager::currentPM()->initSatProof(this);
+ }
// Create the constant variables
varTrue = newVar(true, false, false);
uncheckedEnqueue(mkLit(varTrue, false));
uncheckedEnqueue(mkLit(varFalse, true));
// FIXME: these should be axioms I believe
- PROOF
- (
- ProofManager::getSatProof()->registerTrueLit(mkLit(varTrue, false));
- ProofManager::getSatProof()->registerFalseLit(mkLit(varFalse, true));
- );
+ if (options::unsatCores())
+ {
+ ProofManager::getSatProof()->registerTrueLit(mkLit(varTrue, false));
+ ProofManager::getSatProof()->registerFalseLit(mkLit(varFalse, true));
+ }
}
// FIXME: at some point will need more information about where this explanation
// came from (ie. the theory/sharing)
Debug("pf::sat") << "Minisat::Solver registering a THEORY_LEMMA (1)" << std::endl;
- PROOF(ClauseId id = ProofManager::getSatProof()->registerClause(
- real_reason, THEORY_LEMMA);
- ProofManager::getCnfProof()->registerConvertedClause(id, true);
- // explainPropagation() pushes the explanation on the assertion stack
- // in CnfProof, so we need to pop it here. This is important because
- // reason() may be called indirectly while adding a clause, which can
- // lead to a wrong assertion being associated with the clause being
- // added (see issue #2137).
- ProofManager::getCnfProof()->popCurrentAssertion(););
+ if (options::unsatCores())
+ {
+ ClauseId id = ProofManager::getSatProof()->registerClause(real_reason,
+ THEORY_LEMMA);
+ // map id to assertion, which may be required if looking for
+ // lemmas in unsat core
+ ProofManager::getCnfProof()->registerConvertedClause(id);
+ // explainPropagation() pushes the explanation on the assertion stack
+ // in CnfProof, so we need to pop it here. This is important because
+ // reason() may be called indirectly while adding a clause, which can
+ // lead to a wrong assertion being associated with the clause being
+ // added (see issue #2137).
+ ProofManager::getCnfProof()->popCurrentAssertion();
+ }
vardata[x] = VarData(real_reason, level(x), user_level(x), intro_level(x), trail_index(x));
clauses_removable.push(real_reason);
attachClause(real_reason);
}
// If a literal is false at 0 level (both sat and user level) we also ignore it
if (value(ps[i]) == l_False) {
- if (!PROOF_ON() && level(var(ps[i])) == 0 && user_level(var(ps[i])) == 0) {
+ if (!options::unsatCores() && level(var(ps[i])) == 0
+ && user_level(var(ps[i])) == 0)
+ {
continue;
- } else {
+ }
+ else
+ {
// If we decide to keep it, we count it into the false literals
falseLiteralsCount ++;
}
lemmas.push();
ps.copyTo(lemmas.last());
lemmas_removable.push(removable);
- PROOF(
- // Store the expression being converted to CNF until
- // the clause is actually created
- Node assertion = ProofManager::getCnfProof()->getCurrentAssertion();
- Node def = ProofManager::getCnfProof()->getCurrentDefinition();
- lemmas_cnf_assertion.push_back(std::make_pair(assertion, def));
- id = ClauseIdUndef;
- );
- // does it have to always be a lemma?
- // PROOF(id = ProofManager::getSatProof()->registerUnitClause(ps[0], THEORY_LEMMA););
- // PROOF(id = ProofManager::getSatProof()->registerTheoryLemma(ps););
- // Debug("cores") << "lemma push " << proof_id << " " << (proof_id & 0xffffffff) << std::endl;
- // lemmas_proof_id.push(proof_id);
+ if (options::unsatCores())
+ {
+ // Store the expression being converted to CNF until
+ // the clause is actually created
+ lemmas_cnf_assertion.push_back(
+ ProofManager::getCnfProof()->getCurrentAssertion());
+ id = ClauseIdUndef;
+ }
} else {
assert(decisionLevel() == 0);
// If all false, we're in conflict
if (ps.size() == falseLiteralsCount) {
- if(PROOF_ON()) {
+ if (options::unsatCores())
+ {
// Take care of false units here; otherwise, we need to
// construct the clause below to give to the proof manager
// as the final conflict.
if(falseLiteralsCount == 1) {
- PROOF( id = ProofManager::getSatProof()->storeUnitConflict(ps[0], INPUT); )
- PROOF( ProofManager::getSatProof()->finalizeProof(CVC4::Minisat::CRef_Lazy); )
+ if (options::unsatCores())
+ {
+ ClauseKind ck =
+ ProofManager::getCnfProof()->getCurrentAssertionKind()
+ ? INPUT
+ : THEORY_LEMMA;
+ id = ProofManager::getSatProof()->storeUnitConflict(ps[0], ck);
+ // map id to assertion, which may be required if looking for
+ // lemmas in unsat core
+ if (ck == THEORY_LEMMA)
+ {
+ ProofManager::getCnfProof()->registerConvertedClause(id);
+ }
+ ProofManager::getSatProof()->finalizeProof(
+ CVC4::Minisat::CRef_Lazy);
+ }
return ok = false;
}
- } else {
+ }
+ else
+ {
return ok = false;
}
}
cr = ca.alloc(clauseLevel, ps, false);
clauses_persistent.push(cr);
- attachClause(cr);
-
- if(PROOF_ON()) {
- PROOF(
- id = ProofManager::getSatProof()->registerClause(cr, INPUT);
- )
- if(ps.size() == falseLiteralsCount) {
- PROOF( ProofManager::getSatProof()->finalizeProof(cr); )
+ attachClause(cr);
+
+ if (options::unsatCores())
+ {
+ ClauseKind ck = ProofManager::getCnfProof()->getCurrentAssertionKind()
+ ? INPUT
+ : THEORY_LEMMA;
+ id = ProofManager::getSatProof()->registerClause(cr, ck);
+ // map id to assertion, which may be required if looking for
+ // lemmas in unsat core
+ if (ck == THEORY_LEMMA)
+ {
+ ProofManager::getCnfProof()->registerConvertedClause(id);
+ }
+ if (ps.size() == falseLiteralsCount)
+ {
+ ProofManager::getSatProof()->finalizeProof(cr);
return ok = false;
}
}
if(assigns[var(ps[0])] == l_Undef) {
assert(assigns[var(ps[0])] != l_False);
uncheckedEnqueue(ps[0], cr);
- Debug("cores") << "i'm registering a unit clause, input" << std::endl;
- PROOF(
- if(ps.size() == 1) {
- id = ProofManager::getSatProof()->registerUnitClause(ps[0], INPUT);
- }
- );
+ Debug("cores") << "i'm registering a unit clause, maybe input"
+ << std::endl;
+ if (options::unsatCores() && ps.size() == 1)
+ {
+ ClauseKind ck =
+ ProofManager::getCnfProof()->getCurrentAssertionKind()
+ ? INPUT
+ : THEORY_LEMMA;
+ id = ProofManager::getSatProof()->registerUnitClause(ps[0], ck);
+ // map id to assertion, which may be required if looking for
+ // lemmas in unsat core
+ if (ck == THEORY_LEMMA)
+ {
+ ProofManager::getCnfProof()->registerConvertedClause(id);
+ }
+ }
CRef confl = propagate(CHECK_WITHOUT_THEORY);
if(! (ok = (confl == CRef_Undef)) ) {
- if (PROOF_ON())
+ if (options::unsatCores())
{
if (ca[confl].size() == 1)
{
}
return ok;
} else {
- PROOF(id = ClauseIdUndef;);
+ if (options::unsatCores())
+ {
+ id = ClauseIdUndef;
+ }
return ok;
}
}
void Solver::detachClause(CRef cr, bool strict) {
const Clause& c = ca[cr];
- PROOF( ProofManager::getSatProof()->markDeleted(cr); );
+ if (options::unsatCores())
+ {
+ ProofManager::getSatProof()->markDeleted(cr);
+ }
Debug("minisat") << "Solver::detachClause(" << c << ")" << std::endl;
assert(c.size() > 1);
int max_resolution_level = 0; // Maximal level of the resolved clauses
- PROOF( ProofManager::getSatProof()->startResChain(confl); )
+ if (options::unsatCores())
+ {
+ ProofManager::getSatProof()->startResChain(confl);
+ }
do{
assert(confl != CRef_Undef); // (otherwise should be UIP)
}
// FIXME: can we do it lazily if we actually need the proof?
- if (level(var(q)) == 0)
+ if (options::unsatCores() && level(var(q)) == 0)
{
- PROOF(ProofManager::getSatProof()->resolveOutUnit(q);)
+ ProofManager::getSatProof()->resolveOutUnit(q);
}
}
}
seen[var(p)] = 0;
pathC--;
- if ( pathC > 0 && confl != CRef_Undef ) {
- PROOF( ProofManager::getSatProof()->addResolutionStep(p, confl, sign(p)); )
+ if (options::unsatCores() && pathC > 0 && confl != CRef_Undef)
+ {
+ ProofManager::getSatProof()->addResolutionStep(p, confl, sign(p));
}
}while (pathC > 0);
// Literal is not redundant
out_learnt[j++] = out_learnt[i];
} else {
- PROOF( ProofManager::getSatProof()->storeLitRedundant(out_learnt[i]); )
+ if (options::unsatCores())
+ {
+ ProofManager::getSatProof()->storeLitRedundant(out_learnt[i]);
+ }
// Literal is redundant, to be safe, mark the level as current assertion level
// TODO: maybe optimize
max_resolution_level = std::max(max_resolution_level, user_level(var(out_learnt[i])));
addClause(explanation, true, id);
// explainPropagation() pushes the explanation on the assertion
// stack in CnfProof, so we need to pop it here.
- PROOF(ProofManager::getCnfProof()->popCurrentAssertion();)
+ if (options::unsatCores())
+ {
+ ProofManager::getCnfProof()->popCurrentAssertion();
+ }
}
}
}
for (i = j = 0; i < cs.size(); i++){
Clause& c = ca[cs[i]];
if (satisfied(c)) {
- if (locked(c)) {
+ if (options::unsatCores() && locked(c))
+ {
// store a resolution of the literal c propagated
- PROOF( ProofManager::getSatProof()->storeUnitResolution(c[0]); )
+ ProofManager::getSatProof()->storeUnitResolution(c[0]);
}
removeClause(cs[i]);
}
conflicts++; conflictC++;
if (decisionLevel() == 0) {
- PROOF( ProofManager::getSatProof()->finalizeProof(confl); )
- return l_False;
+ if (options::unsatCores())
+ {
+ ProofManager::getSatProof()->finalizeProof(confl);
+ }
+ return l_False;
}
// Analyze the conflict
if (learnt_clause.size() == 1) {
uncheckedEnqueue(learnt_clause[0]);
- PROOF( ProofManager::getSatProof()->endResChain(learnt_clause[0]); )
-
+ if (options::unsatCores())
+ {
+ ProofManager::getSatProof()->endResChain(learnt_clause[0]);
+ }
} else {
CRef cr =
ca.alloc(assertionLevelOnly() ? assertionLevel : max_level,
attachClause(cr);
claBumpActivity(ca[cr]);
uncheckedEnqueue(learnt_clause[0], cr);
- PROOF(ClauseId id =
- ProofManager::getSatProof()->registerClause(cr, LEARNT);
- PSTATS(std::unordered_set<int> cl_levels;
- for (int i = 0; i < learnt_clause.size(); ++i) {
- cl_levels.insert(level(var(learnt_clause[i])));
- } ProofManager::getSatProof()
- ->storeClauseGlue(id, cl_levels.size());)
- ProofManager::getSatProof()
- ->endResChain(id););
+ if (options::unsatCores())
+ {
+ ClauseId id =
+ ProofManager::getSatProof()->registerClause(cr, LEARNT);
+ ProofManager::getSatProof()->endResChain(id);
+ }
}
varDecayActivity();
}
} else {
-
- // If this was a final check, we are satisfiable
- if (check_type == CHECK_FINAL) {
- bool decisionEngineDone = d_proxy->isDecisionEngineDone();
- // Unless a lemma has added more stuff to the queues
- if (!decisionEngineDone &&
- (!order_heap.empty() || qhead < trail.size()) ) {
- check_type = CHECK_WITH_THEORY;
- continue;
- } else if (recheck) {
- // There some additional stuff added, so we go for another full-check
- continue;
- } else {
- // Yes, we're truly satisfiable
- return l_True;
- }
- } else if (check_type == CHECK_FINAL_FAKE) {
+ // If this was a final check, we are satisfiable
+ if (check_type == CHECK_FINAL)
+ {
+ bool decisionEngineDone = d_proxy->isDecisionEngineDone();
+ // Unless a lemma has added more stuff to the queues
+ if (!decisionEngineDone
+ && (!order_heap.empty() || qhead < trail.size()))
+ {
check_type = CHECK_WITH_THEORY;
+ continue;
+ }
+ else if (recheck)
+ {
+ // There some additional stuff added, so we go for another
+ // full-check
+ continue;
}
+ else
+ {
+ // Yes, we're truly satisfiable
+ return l_True;
+ }
+ }
+ else if (check_type == CHECK_FINAL_FAKE)
+ {
+ check_type = CHECK_WITH_THEORY;
+ }
if ((nof_conflicts >= 0 && conflictC >= nof_conflicts)
|| !withinBudget(ResourceManager::Resource::SatConflictStep))
// printf(" >>> RELOCING: %s%d\n", sign(p)?"-":"", var(p)+1);
vec<Watcher>& ws = watches[p];
for (int j = 0; j < ws.size(); j++)
- ca.reloc(ws[j].cref, to, NULLPROOF(ProofManager::getSatProof()));
+ ca.reloc(ws[j].cref,
+ to,
+ CVC4::options::unsatCores() ? ProofManager::getSatProof()
+ : nullptr);
}
// All reasons:
Var v = var(trail[i]);
if (hasReasonClause(v) && (ca[reason(v)].reloced() || locked(ca[reason(v)])))
- ca.reloc(
- vardata[v].d_reason, to, NULLPROOF(ProofManager::getSatProof()));
+ ca.reloc(vardata[v].d_reason,
+ to,
+ CVC4::options::unsatCores() ? ProofManager::getSatProof()
+ : nullptr);
}
// All learnt:
//
for (int i = 0; i < clauses_removable.size(); i++)
ca.reloc(
- clauses_removable[i], to, NULLPROOF(ProofManager::getSatProof()));
+ clauses_removable[i],
+ to,
+ CVC4::options::unsatCores() ? ProofManager::getSatProof() : nullptr);
// All original:
//
for (int i = 0; i < clauses_persistent.size(); i++)
ca.reloc(
- clauses_persistent[i], to, NULLPROOF(ProofManager::getSatProof()));
+ clauses_persistent[i],
+ to,
+ CVC4::options::unsatCores() ? ProofManager::getSatProof() : nullptr);
- PROOF(ProofManager::getSatProof()->finishUpdateCRef();)
+ if (options::unsatCores())
+ {
+ ProofManager::getSatProof()->finishUpdateCRef();
+ }
}
// If it's an empty lemma, we have a conflict at zero level
if (lemma.size() == 0) {
- Assert(!PROOF_ON());
+ Assert(!options::unsatCores());
conflict = CRef_Lazy;
backtrackLevel = 0;
Debug("minisat::lemmas") << "Solver::updateLemmas(): found empty clause" << std::endl;
// Last index in the trail
int backtrack_index = trail.size();
- PROOF(Assert(lemmas.size() == (int)lemmas_cnf_assertion.size()););
+ Assert(!options::unsatCores()
+ || lemmas.size() == (int)lemmas_cnf_assertion.size());
// Attach all the clauses and enqueue all the propagations
for (int j = 0; j < lemmas.size(); ++j)
}
lemma_ref = ca.alloc(clauseLevel, lemma, removable);
- PROOF(TNode cnf_assertion = lemmas_cnf_assertion[j].first;
- TNode cnf_def = lemmas_cnf_assertion[j].second;
-
- Debug("pf::sat")
- << "Minisat::Solver registering a THEORY_LEMMA (2)" << std::endl;
- ClauseId id = ProofManager::getSatProof()->registerClause(
- lemma_ref, THEORY_LEMMA);
- ProofManager::getCnfProof()->setClauseAssertion(id, cnf_assertion);
- ProofManager::getCnfProof()->setClauseDefinition(id, cnf_def););
+ if (options::unsatCores())
+ {
+ TNode cnf_assertion = lemmas_cnf_assertion[j];
+
+ Debug("pf::sat") << "Minisat::Solver registering a THEORY_LEMMA (2)"
+ << std::endl;
+ ClauseId id = ProofManager::getSatProof()->registerClause(lemma_ref,
+ THEORY_LEMMA);
+ ProofManager::getCnfProof()->setClauseAssertion(id, cnf_assertion);
+ }
if (removable) {
clauses_removable.push(lemma_ref);
} else {
// If the lemma is propagating enqueue its literal (or set the conflict)
if (conflict == CRef_Undef && value(lemma[0]) != l_True) {
if (lemma.size() == 1 || (value(lemma[1]) == l_False && trail_index(var(lemma[1])) < backtrack_index)) {
- if (PROOF_ON() && lemma.size() == 1)
+ if (options::unsatCores() && lemma.size() == 1)
{
- Node cnf_assertion = lemmas_cnf_assertion[j].first;
- Node cnf_def = lemmas_cnf_assertion[j].second;
+ Node cnf_assertion = lemmas_cnf_assertion[j];
Debug("pf::sat") << "Minisat::Solver registering a THEORY_LEMMA (3) "
<< cnf_assertion << value(lemma[0]) << std::endl;
ClauseId id = ProofManager::getSatProof()->registerUnitClause(
lemma[0], THEORY_LEMMA);
ProofManager::getCnfProof()->setClauseAssertion(id, cnf_assertion);
- ProofManager::getCnfProof()->setClauseDefinition(id, cnf_def);
}
if (value(lemma[0]) == l_False) {
} else {
Debug("minisat::lemmas") << "Solver::updateLemmas(): unit conflict or empty clause" << std::endl;
conflict = CRef_Lazy;
- PROOF( ProofManager::getSatProof()->storeUnitConflict(lemma[0], LEARNT); );
+ if (options::unsatCores())
+ {
+ ProofManager::getSatProof()->storeUnitConflict(lemma[0], LEARNT);
+ }
}
} else {
Debug("minisat::lemmas") << "lemma size is " << lemma.size() << std::endl;
}
}
- PROOF(Assert(lemmas.size() == (int)lemmas_cnf_assertion.size()););
+ Assert(!options::unsatCores()
+ || lemmas.size() == (int)lemmas_cnf_assertion.size());
// Clear the lemmas
lemmas.clear();
lemmas_cnf_assertion.clear();
typedef Var TVar;
typedef Lit TLit;
- typedef Clause TClause;
+ typedef Clause TClause;
typedef CRef TCRef;
typedef vec<Lit> TLitVec;
vec<bool> lemmas_removable;
/** Nodes being converted to CNF */
- std::vector<std::pair<CVC4::Node, CVC4::Node> > lemmas_cnf_assertion;
+ std::vector<CVC4::Node> lemmas_cnf_assertion;
/** Do a another check if FULL_EFFORT was the last one */
bool recheck;
lbool solve (Lit p, Lit q, Lit r); // Search for a model that respects three assumptions.
bool okay () const; // FALSE means solver is in a conflicting state
- void toDimacs ();
+ void toDimacs();
void toDimacs (FILE* f, const vec<Lit>& assumps); // Write CNF to file in DIMACS-format.
void toDimacs (const char *file, const vec<Lit>& assumps);
void toDimacs (FILE* f, Clause& c, vec<Var>& map, Var& max);
inline int var (Lit p) { return p.x >> 1; }
// Mapping Literals to and from compact integers suitable for array indexing:
-inline int toInt (Var v) { return v; }
-inline int toInt (Lit p) { return p.x; }
-inline Lit toLit (int i) { Lit p; p.x = i; return p; }
+inline int toInt(Var v) { return v; }
+inline int toInt(Lit p) { return p.x; }
+inline Lit toLit(int i)
+{
+ Lit p;
+ p.x = i;
+ return p;
+}
//const Lit lit_Undef = mkLit(var_Undef, false); // }- Useful special constants.
//const Lit lit_Error = mkLit(var_Undef, true ); // }
const Lit lit_Undef = { -2 }; // }- Useful special constants.
const Lit lit_Error = { -1 }; // }
-
//=================================================================================================
// Lifted booleans:
//
-// NOTE: this implementation is optimized for the case when comparisons between values are mostly
-// between one variable and one constant. Some care had to be taken to make sure that gcc
-// does enough constant propagation to produce sensible code, and this appears to be somewhat
-// fragile unfortunately.
+// NOTE: this implementation is optimized for the case when comparisons between
+// values are mostly
+// between one variable and one constant. Some care had to be taken to
+// make sure that gcc does enough constant propagation to produce sensible
+// code, and this appears to be somewhat fragile unfortunately.
/*
- This is to avoid multiple definitions of l_True, l_False and l_Undef if using multiple copies of
- Minisat.
- IMPORTANT: if we you change the value of the constants so that it is not the same in all copies
- of Minisat this breaks!
+ This is to avoid multiple definitions of l_True, l_False and l_Undef if using
+ multiple copies of Minisat. IMPORTANT: if we you change the value of the
+ constants so that it is not the same in all copies of Minisat this breaks!
*/
#ifndef l_True
bool operator != (lbool b) const { return !(*this == b); }
lbool operator ^ (bool b) const { return lbool((uint8_t)(value^(uint8_t)b)); }
- lbool operator && (lbool b) const {
- uint8_t sel = (this->value << 1) | (b.value << 3);
- uint8_t v = (0xF7F755F4 >> sel) & 3;
- return lbool(v); }
+ lbool operator&&(lbool b) const
+ {
+ uint8_t sel = (this->value << 1) | (b.value << 3);
+ uint8_t v = (0xF7F755F4 >> sel) & 3;
+ return lbool(v);
+ }
lbool operator || (lbool b) const {
uint8_t sel = (this->value << 1) | (b.value << 3);
}
inline std::ostream& operator <<(std::ostream& out, Minisat::lbool val) {
- std::string val_str;
+ std::string val_str;
if( val == l_False ) {
val_str = "0";
} else if (val == l_True ) {
header.size = ps.size();
header.level = level;
- for (int i = 0; i < ps.size(); i++)
- data[i].lit = ps[i];
+ for (int i = 0; i < ps.size(); i++) data[i].lit = ps[i];
if (header.has_extra){
if (header.removable)
- data[header.size].act = 0;
- else
- calcAbstraction(); }
+ data[header.size].act = 0;
+ else
+ calcAbstraction();
+ }
}
public:
public:
OccLists(const Deleted& d) : deleted(d) {}
-
+
void init (const Idx& idx){ occs.growTo(toInt(idx)+1); dirty.growTo(toInt(idx)+1, 0); }
void resizeTo (const Idx& idx);
// Vec& operator[](const Idx& idx){ return occs[toInt(idx)]; }
typedef Map<CRef, T, CRefHash> HashTable;
HashTable map;
-
+
public:
// Size-operations:
void clear () { map.clear(); }
int size () const { return map.elems(); }
-
// Insert/Remove/Test mapping:
void insert (CRef cr, const T& t){ map.insert(cr, t); }
void growTo (CRef cr, const T& t){ map.insert(cr, t); } // NOTE: for compatibility
printf(" --- size = %d, bucket_count = %d\n", size(), map.bucket_count()); }
};
-
/*_________________________________________________________________________________________________
|
| subsumes : (other : const Clause&) -> Lit
-|
+|
| Description:
-| Checks if clause subsumes 'other', and at the same time, if it can be used to simplify 'other'
-| by subsumption resolution.
-|
+| Checks if clause subsumes 'other', and at the same time, if it can be
+used to simplify 'other' | by subsumption resolution.
+|
| Result:
| lit_Error - No subsumption or simplification
| lit_Undef - Clause subsumes 'other'
return ClauseIdUndef;
}
d_minisat->addClause(minisat_clause, removable, clause_id);
- PROOF(Assert(clause_id != ClauseIdError););
+ Assert(!CVC4::options::unsatCores() || clause_id != ClauseIdError);
return clause_id;
}
#include "prop/minisat/simp/SimpSolver.h"
#include "options/prop_options.h"
+#include "options/smt_options.h"
#include "proof/clause_id.h"
-#include "proof/proof.h"
#include "prop/minisat/mtl/Sort.h"
#include "prop/minisat/utils/System.h"
//=================================================================================================
// Constructor/Destructor:
-
-SimpSolver::SimpSolver(CVC4::prop::TheoryProxy* proxy, CVC4::context::Context* context, bool enableIncremental) :
- Solver(proxy, context, enableIncremental)
- , grow (opt_grow)
- , clause_lim (opt_clause_lim)
- , subsumption_lim (opt_subsumption_lim)
- , simp_garbage_frac (opt_simp_garbage_frac)
- , use_asymm (opt_use_asymm)
- , use_rcheck (opt_use_rcheck)
- , use_elim (options::minisatUseElim() && !enableIncremental)
- , merges (0)
- , asymm_lits (0)
- , eliminated_vars (0)
- , elimorder (1)
- , use_simplification (!enableIncremental && !PROOF_ON()) // TODO: turn off simplifications if proofs are on initially
- , occurs (ClauseDeleted(ca))
- , elim_heap (ElimLt(n_occ))
- , bwdsub_assigns (0)
- , n_touched (0)
+SimpSolver::SimpSolver(CVC4::prop::TheoryProxy* proxy,
+ CVC4::context::Context* context,
+ bool enableIncremental)
+ : Solver(proxy, context, enableIncremental),
+ grow(opt_grow),
+ clause_lim(opt_clause_lim),
+ subsumption_lim(opt_subsumption_lim),
+ simp_garbage_frac(opt_simp_garbage_frac),
+ use_asymm(opt_use_asymm),
+ use_rcheck(opt_use_rcheck),
+ use_elim(options::minisatUseElim() && !enableIncremental),
+ merges(0),
+ asymm_lits(0),
+ eliminated_vars(0),
+ elimorder(1),
+ use_simplification(
+ !enableIncremental
+ && !options::unsatCores()) // TODO: turn off simplifications if
+ // proofs are on initially
+ ,
+ occurs(ClauseDeleted(ca)),
+ elim_heap(ElimLt(n_occ)),
+ bwdsub_assigns(0),
+ n_touched(0)
{
if(options::minisatUseElim() &&
options::minisatUseElim.wasSetByUser() &&
lbool SimpSolver::solve_(bool do_simp, bool turn_off_simp)
{
if (options::minisatDumpDimacs()) {
- toDimacs();
- return l_Undef;
+ toDimacs();
+ return l_Undef;
}
assert(decisionLevel() == 0);
for (int i = 0; i < pos.size(); i++)
for (int j = 0; j < neg.size(); j++)
- if (merge(ca[pos[i]], ca[neg[j]], v, clause_size) &&
- (++cnt > cls.size() + grow || (clause_lim != -1 && clause_size > clause_lim)))
- return true;
+ if (merge(ca[pos[i]], ca[neg[j]], v, clause_size)
+ && (++cnt > cls.size() + grow
+ || (clause_lim != -1 && clause_size > clause_lim)))
+ return true;
// Delete and store old clauses:
eliminated[v] = true;
mkElimClause(elimclauses, ~mkLit(v));
}
- for (int i = 0; i < cls.size(); i++)
- removeClause(cls[i]);
+ for (int i = 0; i < cls.size(); i++) removeClause(cls[i]);
- ClauseId id = ClauseIdUndef;
+ ClauseId id = ClauseIdUndef;
// Produce clauses in cross product:
vec<Lit>& resolvent = add_tmp;
for (int i = 0; i < pos.size(); i++)
// Free occurs list for this variable:
occurs[v].clear(true);
-
+
// Free watchers lists for this variable, if possible:
if (watches[ mkLit(v)].size() == 0) watches[ mkLit(v)].clear(true);
if (watches[~mkLit(v)].size() == 0) watches[~mkLit(v)].clear(true);
eliminated[v] = true;
setDecisionVar(v, false);
const vec<CRef>& cls = occurs.lookup(v);
-
+
vec<Lit>& subst_clause = add_tmp;
for (int i = 0; i < cls.size(); i++){
Clause& c = ca[cls[i]];
gatherTouchedClauses();
// printf(" ## (time = %6.2f s) BWD-SUB: queue = %d, trail = %d\n", cpuTime(), subsumption_queue.size(), trail.size() - bwdsub_assigns);
- if ((subsumption_queue.size() > 0 || bwdsub_assigns < trail.size()) &&
- !backwardSubsumptionCheck(true)){
- ok = false; goto cleanup; }
+ if ((subsumption_queue.size() > 0 || bwdsub_assigns < trail.size())
+ && !backwardSubsumptionCheck(true))
+ {
+ ok = false;
+ goto cleanup;
+ }
// Empty elim_heap and return immediately on user-interrupt:
if (asynch_interrupt){
// printf(" ## (time = %6.2f s) ELIM: vars = %d\n", cpuTime(), elim_heap.size());
for (int cnt = 0; !elim_heap.empty(); cnt++){
Var elim = elim_heap.removeMin();
-
+
if (asynch_interrupt) break;
if (isEliminated(elim) || value(elim) != l_Undef) continue;
}
if (verbosity >= 1 && elimclauses.size() > 0)
- printf("| Eliminated clauses: %10.2f Mb |\n",
- double(elimclauses.size() * sizeof(uint32_t)) / (1024*1024));
+ printf(
+ "| Eliminated clauses: %10.2f Mb "
+ " |\n",
+ double(elimclauses.size() * sizeof(uint32_t)) / (1024 * 1024));
return ok;
}
//
for (int i = 0; i < subsumption_queue.size(); i++)
ca.reloc(subsumption_queue[i], to);
- // TODO reloc now takes the proof form the core solver
+ // TODO reloc now takes the proof form the core solver
// Temporary clause:
//
ca.reloc(bwdsub_tmpunit, to);
- // TODO reloc now takes the proof form the core solver
+ // TODO reloc now takes the proof form the core solver
}
{
// Initialize the next region to a size corresponding to the estimated utilization degree. This
// is not precise but should avoid some unnecessary reallocations for the new region:
- ClauseAllocator to(ca.size() - ca.wasted());
+ ClauseAllocator to(ca.size() - ca.wasted());
cleanUpClauses();
to.extra_clause_field = ca.extra_clause_field; // NOTE: this is important to keep (or lose) the extra fields.
relocAll(to);
Solver::relocAll(to);
if (verbosity >= 2)
- printf("| Garbage collection: %12d bytes => %12d bytes |\n",
- ca.size()*ClauseAllocator::Unit_Size, to.size()*ClauseAllocator::Unit_Size);
+ printf(
+ "| Garbage collection: %12d bytes => %12d bytes |\n",
+ ca.size() * ClauseAllocator::Unit_Size,
+ to.size() * ClauseAllocator::Unit_Size);
to.moveTo(ca);
- // TODO: proof.finalizeUpdateId();
+ // TODO: proof.finalizeUpdateId();
}
d_decisionEngine->setSatSolver(d_satSolver);
d_decisionEngine->setCnfStream(d_cnfStream);
- PROOF (
- ProofManager::currentPM()->initCnfProof(d_cnfStream, userContext);
- );
+ if (options::unsatCores())
+ {
+ ProofManager::currentPM()->initCnfProof(d_cnfStream, userContext);
+ }
}
void PropEngine::finishInit()
{
NodeManager* nm = NodeManager::currentNM();
- d_cnfStream->convertAndAssert(nm->mkConst(true), false, false, RULE_GIVEN);
- d_cnfStream->convertAndAssert(
- nm->mkConst(false).notNode(), false, false, RULE_GIVEN);
+ d_cnfStream->convertAndAssert(nm->mkConst(true), false, false);
+ d_cnfStream->convertAndAssert(nm->mkConst(false).notNode(), false, false);
}
PropEngine::~PropEngine() {
Assert(!d_inCheckSat) << "Sat solver in solve()!";
Debug("prop") << "assertFormula(" << node << ")" << endl;
// Assert as non-removable
- d_cnfStream->convertAndAssert(node, false, false, RULE_GIVEN);
+ d_cnfStream->convertAndAssert(node, false, false, true);
}
-void PropEngine::assertLemma(TNode node, bool negated,
- bool removable,
- ProofRule rule,
- TNode from) {
- //Assert(d_inCheckSat, "Sat solver should be in solve()!");
+void PropEngine::assertLemma(TNode node, bool negated, bool removable)
+{
Debug("prop::lemmas") << "assertLemma(" << node << ")" << endl;
// Assert as (possibly) removable
- d_cnfStream->convertAndAssert(node, removable, negated, rule, from);
+ d_cnfStream->convertAndAssert(node, removable, negated);
}
void PropEngine::addAssertionsToDecisionEngine(
* @param removable whether this lemma can be quietly removed based
* on an activity heuristic (or not)
*/
- void assertLemma(TNode node,
- bool negated,
- bool removable,
- ProofRule rule,
- TNode from = TNode::null());
+ void assertLemma(TNode node, bool negated, bool removable);
/**
* Pass a list of assertions from an AssertionPipeline to the decision engine.
namespace CVC4 {
-namespace proof {
-class ClausalBitVectorProof;
-class ResolutionBitVectorProof;
-} // namespace proof
-
namespace prop {
class TheoryProxy;
/** Add a clause corresponding to rhs = l1 xor .. xor ln */
virtual ClauseId addXorClause(SatClause& clause, bool rhs, bool removable) = 0;
-
+
/**
* Create a new boolean variable in the solver.
* @param isTheoryAtom is this a theory atom that needs to be asserted to theory
virtual SatValue solve(const std::vector<SatLiteral>& assumptions)
{
Unimplemented() << "Solving under assumptions not implemented";
+ return SAT_VALUE_UNKNOWN;
};
/** Interrupt the solver */
/** Check if the solver is in an inconsistent state */
virtual bool ok() const = 0;
- virtual void setResolutionProofLog(proof::ResolutionBitVectorProof* bvp) {}
-
- virtual void setClausalProofLog(proof::ClausalBitVectorProof* drat_proof) {}
-
};/* class SatSolver */
TNode lNode = d_cnfStream->getNode(l);
Debug("prop-explain") << "explainPropagation(" << lNode << ")" << std::endl;
- LemmaProofRecipe* proofRecipe = NULL;
- PROOF(proofRecipe = new LemmaProofRecipe;);
+ Node theoryExplanation = d_theoryEngine->getExplanation(lNode);
- Node theoryExplanation = d_theoryEngine->getExplanationAndRecipe(lNode, proofRecipe);
-
- PROOF({
- ProofManager::getCnfProof()->pushCurrentAssertion(theoryExplanation);
- ProofManager::getCnfProof()->setProofRecipe(proofRecipe);
-
- Debug("pf::sat") << "TheoryProxy::explainPropagation: setting lemma recipe to: "
- << std::endl;
- proofRecipe->dump("pf::sat");
-
- delete proofRecipe;
- proofRecipe = NULL;
- });
+ if (options::unsatCores())
+ {
+ ProofManager::getCnfProof()->pushCurrentAssertion(theoryExplanation);
+ }
Debug("prop-explain") << "explainPropagation() => " << theoryExplanation << std::endl;
if (theoryExplanation.getKind() == kind::AND) {
#include "expr/node_algorithm.h"
#include "options/base_options.h"
#include "options/language.h"
-#include "options/proof_options.h"
#include "options/smt_options.h"
#include "proof/proof_manager.h"
#include "smt/smt_engine.h"
}
// Give it to proof manager
- PROOF(if (inInput) {
- // n is an input assertion
- if (inUnsatCore || options::unsatCores() || options::dumpUnsatCores()
- || options::checkUnsatCores() || options::fewerPreprocessingHoles())
+ if (options::unsatCores())
+ {
+ if (inInput)
+ { // n is an input assertion
+ if (inUnsatCore || options::unsatCores() || options::dumpUnsatCores()
+ || options::checkUnsatCores())
+ {
+ ProofManager::currentPM()->addCoreAssertion(n.toExpr());
+ }
+ }
+ else
{
- ProofManager::currentPM()->addCoreAssertion(n.toExpr());
+ // n is the result of an unknown preprocessing step, add it to dependency
+ // map to null
+ ProofManager::currentPM()->addDependence(n, Node::null());
}
- } else {
- // n is the result of an unknown preprocessing step, add it to dependency
- // map to null
- ProofManager::currentPM()->addDependence(n, Node::null());
- });
+ }
// Add the normalized formula to the queue
d_assertions.push_back(n, isAssumption);
* formula might be pushed out to the propositional layer
* immediately, or it might be simplified and kept, or it might not
* even be simplified.
- * The arguments isInput and isAssumption are used for bookkeeping for proofs.
+ * The arguments isInput and isAssumption are used for bookkeeping for unsat
+ * cores.
* The argument maybeHasFv should be set to true if the assertion may have
* free variables. By construction, assertions from the smt2 parser are
* guaranteed not to have free variables. However, other cases such as
/* class GetProofCommand */
/* -------------------------------------------------------------------------- */
-GetProofCommand::GetProofCommand() : d_smtEngine(nullptr), d_result(nullptr) {}
+GetProofCommand::GetProofCommand() {}
void GetProofCommand::invoke(SmtEngine* smtEngine)
{
- try
- {
- d_smtEngine = smtEngine;
- d_result = &smtEngine->getProof();
- d_commandStatus = CommandSuccess::instance();
- }
- catch (RecoverableModalException& e)
- {
- d_commandStatus = new CommandRecoverableFailure(e.what());
- }
- catch (UnsafeInterruptException& e)
- {
- d_commandStatus = new CommandInterrupted();
- }
- catch (exception& e)
- {
- d_commandStatus = new CommandFailure(e.what());
- }
-}
-
-const Proof& GetProofCommand::getResult() const { return *d_result; }
-void GetProofCommand::printResult(std::ostream& out, uint32_t verbosity) const
-{
- if (!ok())
- {
- this->Command::printResult(out, verbosity);
- }
- else
- {
- smt::SmtScope scope(d_smtEngine);
- d_result->toStream(out);
- }
+ Unimplemented() << "Unimplemented get-proof\n";
}
Command* GetProofCommand::exportTo(ExprManager* exprManager,
ExprManagerMapCollection& variableMap)
{
GetProofCommand* c = new GetProofCommand();
- c->d_result = d_result;
- c->d_smtEngine = d_smtEngine;
return c;
}
Command* GetProofCommand::clone() const
{
GetProofCommand* c = new GetProofCommand();
- c->d_result = d_result;
- c->d_smtEngine = d_smtEngine;
return c;
}
#include "expr/type.h"
#include "expr/variable_type_map.h"
#include "proof/unsat_core.h"
-#include "util/proof.h"
#include "util/result.h"
#include "util/sexpr.h"
public:
GetProofCommand();
- const Proof& getResult() const;
void invoke(SmtEngine* smtEngine) override;
- void printResult(std::ostream& out, uint32_t verbosity = 2) const override;
Command* exportTo(ExprManager* exprManager,
ExprManagerMapCollection& variableMap) override;
Command* clone() const override;
bool types = false,
size_t dag = 1,
OutputLanguage language = language::output::LANG_AUTO) const override;
-
- protected:
- SmtEngine* d_smtEngine;
- // d_result is owned by d_smtEngine.
- const Proof* d_result;
}; /* class GetProofCommand */
class CVC4_PUBLIC GetInstantiationsCommand : public Command
#include "options/arith_options.h"
#include "options/base_options.h"
#include "options/bv_options.h"
-#include "options/proof_options.h"
#include "options/quantifiers_options.h"
#include "options/sep_options.h"
#include "options/smt_options.h"
<< endl;
dumpAssertions("post-definition-expansion", assertions);
- // save the assertions now
- THEORY_PROOF(
- for (size_t i = 0, nasserts = assertions.size(); i < nasserts; ++i) {
- ProofManager::currentPM()->addAssertion(assertions[i].toExpr());
- });
-
Debug("smt") << " assertions : " << assertions.size() << endl;
if (options::globalNegate())
if (options::simplificationMode() != options::SimplificationMode::NONE)
{
- if (!options::unsatCores() && !options::fewerPreprocessingHoles())
+ if (!options::unsatCores())
{
// Perform non-clausal simplification
PreprocessingPassResult res =
if (options::repeatSimp()
&& options::simplificationMode() != options::SimplificationMode::NONE
- && !options::unsatCores() && !options::fewerPreprocessingHoles())
+ && !options::unsatCores())
{
PreprocessingPassResult res =
d_passes["non-clausal-simp"]->apply(&assertions);
#include "options/open_ostream.h"
#include "options/option_exception.h"
#include "options/printer_options.h"
-#include "options/proof_options.h"
#include "options/prop_options.h"
#include "options/quantifiers_options.h"
#include "options/sep_options.h"
Notice() << "SmtEngine: setting unsatCores" << std::endl;
options::unsatCores.set(true);
}
- if (options::checkProofs() || options::dumpProofs())
- {
- Notice() << "SmtEngine: setting proof" << std::endl;
- options::proof.set(true);
- }
if (options::bitvectorAigSimplifications.wasSetByUser())
{
Notice() << "SmtEngine: setting bitvectorAig" << std::endl;
<< std::endl;
}
}
- // !!!!!!!!!!!!!!!! temporary, to support CI check for old proof system
- if (options::proof())
- {
- options::proofNew.set(false);
- }
-
if (options::arraysExp())
{
if (!logic.isQuantified())
options::produceAssertions.set(true);
}
- // Disable options incompatible with incremental solving, unsat cores, and
- // proofs or output an error if enabled explicitly. It is also currently
- // incompatible with arithmetic, force the option off.
- if (options::incrementalSolving() || options::unsatCores()
- || options::proof())
+ // Disable options incompatible with incremental solving, unsat cores or
+ // output an error if enabled explicitly. It is also currently incompatible
+ // with arithmetic, force the option off.
+ if (options::incrementalSolving() || options::unsatCores())
{
if (options::unconstrainedSimp())
{
{
throw OptionException(
"unconstrained simplification not supported with unsat "
- "cores/proofs/incremental solving");
+ "cores/incremental solving");
}
Notice() << "SmtEngine: turning off unconstrained simplification to "
- "support unsat cores/proofs/incremental solving"
+ "support unsat cores/incremental solving"
<< std::endl;
options::unconstrainedSimp.set(false);
}
}
}
- if (options::incrementalSolving() || options::proof())
+ if (options::incrementalSolving())
{
if (options::sygusInference())
{
if (options::sygusInference.wasSetByUser())
{
throw OptionException(
- "sygus inference not supported with proofs/incremental solving");
+ "sygus inference not supported with incremental solving");
}
Notice() << "SmtEngine: turning off sygus inference to support "
- "proofs/incremental solving"
+ "incremental solving"
<< std::endl;
options::sygusInference.set(false);
}
options::bitvectorToBool.set(true);
}
- // Disable options incompatible with unsat cores and proofs or output an
- // error if enabled explicitly
- if (options::unsatCores() || options::proof())
+ // Disable options incompatible with unsat cores or output an error if enabled
+ // explicitly
+ if (options::unsatCores())
{
if (options::simplificationMode() != options::SimplificationMode::NONE)
{
if (options::simplificationMode.wasSetByUser())
{
- throw OptionException(
- "simplification not supported with unsat cores/proofs");
+ throw OptionException("simplification not supported with unsat cores");
}
Notice() << "SmtEngine: turning off simplification to support unsat "
- "cores/proofs"
+ "cores"
<< std::endl;
options::simplificationMode.set(options::SimplificationMode::NONE);
}
if (options::pbRewrites.wasSetByUser())
{
throw OptionException(
- "pseudoboolean rewrites not supported with unsat cores/proofs");
+ "pseudoboolean rewrites not supported with unsat cores");
}
Notice() << "SmtEngine: turning off pseudoboolean rewrites to support "
- "unsat cores/proofs"
+ "unsat cores"
<< std::endl;
options::pbRewrites.set(false);
}
{
if (options::sortInference.wasSetByUser())
{
- throw OptionException(
- "sort inference not supported with unsat cores/proofs");
+ throw OptionException("sort inference not supported with unsat cores");
}
Notice() << "SmtEngine: turning off sort inference to support unsat "
- "cores/proofs"
+ "cores"
<< std::endl;
options::sortInference.set(false);
}
if (options::preSkolemQuant.wasSetByUser())
{
throw OptionException(
- "pre-skolemization not supported with unsat cores/proofs");
+ "pre-skolemization not supported with unsat cores");
}
Notice() << "SmtEngine: turning off pre-skolemization to support unsat "
- "cores/proofs"
+ "cores"
<< std::endl;
options::preSkolemQuant.set(false);
}
{
if (options::bitvectorToBool.wasSetByUser())
{
- throw OptionException(
- "bv-to-bool not supported with unsat cores/proofs");
+ throw OptionException("bv-to-bool not supported with unsat cores");
}
Notice() << "SmtEngine: turning off bitvector-to-bool to support unsat "
- "cores/proofs"
+ "cores"
<< std::endl;
options::bitvectorToBool.set(false);
}
if (options::boolToBitvector.wasSetByUser())
{
throw OptionException(
- "bool-to-bv != off not supported with unsat cores/proofs");
+ "bool-to-bv != off not supported with unsat cores");
}
Notice() << "SmtEngine: turning off bool-to-bv to support unsat "
- "cores/proofs"
+ "cores"
<< std::endl;
options::boolToBitvector.set(options::BoolToBVMode::OFF);
}
{
if (options::bvIntroducePow2.wasSetByUser())
{
- throw OptionException(
- "bv-intro-pow2 not supported with unsat cores/proofs");
+ throw OptionException("bv-intro-pow2 not supported with unsat cores");
}
Notice() << "SmtEngine: turning off bv-intro-pow2 to support "
- "unsat-cores/proofs"
+ "unsat-cores"
<< std::endl;
options::bvIntroducePow2.set(false);
}
{
if (options::repeatSimp.wasSetByUser())
{
- throw OptionException(
- "repeat-simp not supported with unsat cores/proofs");
+ throw OptionException("repeat-simp not supported with unsat cores");
}
Notice() << "SmtEngine: turning off repeat-simp to support unsat "
- "cores/proofs"
+ "cores"
<< std::endl;
options::repeatSimp.set(false);
}
{
if (options::globalNegate.wasSetByUser())
{
- throw OptionException(
- "global-negate not supported with unsat cores/proofs");
+ throw OptionException("global-negate not supported with unsat cores");
}
Notice() << "SmtEngine: turning off global-negate to support unsat "
- "cores/proofs"
+ "cores"
<< std::endl;
options::globalNegate.set(false);
}
if (options::bitvectorAig())
{
- throw OptionException(
- "bitblast-aig not supported with unsat cores/proofs");
+ throw OptionException("bitblast-aig not supported with unsat cores");
}
}
else
if (!options::ufSymmetryBreaker.wasSetByUser())
{
bool qf_uf_noinc = logic.isPure(THEORY_UF) && !logic.isQuantified()
- && !options::incrementalSolving() && !options::proof()
+ && !options::incrementalSolving()
&& !options::unsatCores();
Trace("smt") << "setting uf symmetry breaker to " << qf_uf_noinc
<< std::endl;
// Do we need to track instantiations?
// Needed for sygus due to single invocation techniques.
if (options::cegqiNestedQE()
- || (options::proof() && !options::trackInstLemmas.wasSetByUser())
+ || (options::unsatCores() && !options::trackInstLemmas.wasSetByUser())
|| is_sygus)
{
options::trackInstLemmas.set(true);
options::arraysOptimizeLinear.set(false);
}
- if (options::proof())
- {
- if (options::incrementalSolving())
- {
- if (options::incrementalSolving.wasSetByUser())
- {
- throw OptionException("--incremental is not supported with proofs");
- }
- Warning()
- << "SmtEngine: turning off incremental solving mode (not yet "
- "supported with --proof, try --tear-down-incremental instead)"
- << std::endl;
- options::incrementalSolving.set(false);
- }
- if (logic > LogicInfo("QF_AUFBVLRA"))
- {
- throw OptionException(
- "Proofs are only supported for sub-logics of QF_AUFBVLIA.");
- }
- if (options::bitvectorAlgebraicSolver())
- {
- if (options::bitvectorAlgebraicSolver.wasSetByUser())
- {
- throw OptionException(
- "--bv-algebraic-solver is not supported with proofs");
- }
- Notice() << "SmtEngine: turning off bv algebraic solver to support proofs"
- << std::endl;
- options::bitvectorAlgebraicSolver.set(false);
- }
- if (options::bitvectorEqualitySolver())
- {
- if (options::bitvectorEqualitySolver.wasSetByUser())
- {
- throw OptionException("--bv-eq-solver is not supported with proofs");
- }
- Notice() << "SmtEngine: turning off bv eq solver to support proofs"
- << std::endl;
- options::bitvectorEqualitySolver.set(false);
- }
- if (options::bitvectorInequalitySolver())
- {
- if (options::bitvectorInequalitySolver.wasSetByUser())
- {
- throw OptionException(
- "--bv-inequality-solver is not supported with proofs");
- }
- Notice() << "SmtEngine: turning off bv ineq solver to support proofs"
- << std::endl;
- options::bitvectorInequalitySolver.set(false);
- }
- }
-
if (!options::bitvectorEqualitySolver())
{
if (options::bvLazyRewriteExtf())
#include "options/open_ostream.h"
#include "options/option_exception.h"
#include "options/printer_options.h"
-#include "options/proof_options.h"
#include "options/prop_options.h"
#include "options/quantifiers_options.h"
#include "options/sep_options.h"
#include "preprocessing/preprocessing_pass_context.h"
#include "preprocessing/preprocessing_pass_registry.h"
#include "printer/printer.h"
-#include "proof/proof.h"
#include "proof/proof_manager.h"
-#include "proof/theory_proof.h"
#include "proof/unsat_core.h"
#include "smt/abduction_solver.h"
#include "smt/abstract_values.h"
#include "theory/theory_model.h"
#include "theory/theory_traits.h"
#include "util/hash.h"
-#include "util/proof.h"
#include "util/random.h"
#include "util/resource_manager.h"
-#if (IS_LFSC_BUILD && IS_PROOFS_BUILD)
-#include "lfscc.h"
-#endif
-
using namespace std;
using namespace CVC4;
using namespace CVC4::smt;
namespace CVC4 {
-namespace proof {
-extern const char* const plf_signatures;
-} // namespace proof
-
namespace smt {
}/* namespace CVC4::smt */
d_abductSolver.reset(new AbductionSolver(this));
}
- PROOF( ProofManager::currentPM()->setLogic(d_logic); );
- PROOF({
- TheoryEngine* te = d_smtSolver->getTheoryEngine();
- for (TheoryId id = theory::THEORY_FIRST; id < theory::THEORY_LAST; ++id)
- {
- ProofManager::currentPM()->getTheoryProofEngine()->finishRegisterTheory(
- te->theoryOf(id));
- }
- });
d_pp->finishInit();
AlwaysAssert(getPropEngine()->getAssertionLevel() == 0)
checkModel();
}
}
- // Check that UNSAT results generate a proof correctly.
- if(options::checkProofs()) {
- if(r.asSatisfiabilityResult().isSat() == Result::UNSAT) {
- checkProof();
- }
- }
// Check that UNSAT results generate an unsat core correctly.
if(options::checkUnsatCores()) {
if(r.asSatisfiabilityResult().isSat() == Result::UNSAT) {
Expr SmtEngine::getSepNilExpr() { return getSepHeapAndNilExpr().second; }
-void SmtEngine::checkProof()
-{
-#if (IS_LFSC_BUILD && IS_PROOFS_BUILD)
-
- Chat() << "generating proof..." << endl;
-
- const Proof& pf = getProof();
-
- Chat() << "checking proof..." << endl;
-
- std::string logicString = d_logic.getLogicString();
-
- std::stringstream pfStream;
-
- pfStream << proof::plf_signatures << endl;
- int64_t sizeBeforeProof = static_cast<int64_t>(pfStream.tellp());
-
- pf.toStream(pfStream);
- d_stats->d_proofsSize +=
- static_cast<int64_t>(pfStream.tellp()) - sizeBeforeProof;
-
- {
- TimerStat::CodeTimer checkProofTimer(d_stats->d_lfscCheckProofTime);
- lfscc_init();
- lfscc_check_file(pfStream, false, false, false, false, false, false, false);
- }
- // FIXME: we should actually call lfscc_cleanup here, but lfscc_cleanup
- // segfaults on regress0/bv/core/bitvec7.smt
- // lfscc_cleanup();
-
-#else /* (IS_LFSC_BUILD && IS_PROOFS_BUILD) */
- Unreachable()
- << "This version of CVC4 was built without proof support; cannot check "
- "proofs.";
-#endif /* (IS_LFSC_BUILD && IS_PROOFS_BUILD) */
-}
-
UnsatCore SmtEngine::getUnsatCoreInternal()
{
#if IS_PROOFS_BUILD
coreChecker.setIsInternalSubsolver();
coreChecker.setLogic(getLogicInfo());
coreChecker.getOptions().set(options::checkUnsatCores, false);
- coreChecker.getOptions().set(options::checkProofs, false);
Notice() << "SmtEngine::checkUnsatCore(): pushing core assertions (size == " << core.size() << ")" << endl;
for(UnsatCore::iterator i = core.begin(); i != core.end(); ++i) {
return getUnsatCoreInternal();
}
-// TODO(#1108): Simplify the error reporting of this method.
-const Proof& SmtEngine::getProof()
-{
- Trace("smt") << "SMT getProof()" << endl;
- SmtScope smts(this);
- finishInit();
- if(Dump.isOn("benchmark")) {
- Dump("benchmark") << GetProofCommand();
- }
-#if IS_PROOFS_BUILD
- if(!options::proof()) {
- throw ModalException("Cannot get a proof when produce-proofs option is off.");
- }
- if (d_state->getMode() != SmtMode::UNSAT)
- {
- throw RecoverableModalException(
- "Cannot get a proof unless immediately preceded by UNSAT/ENTAILED "
- "response.");
- }
-
- return ProofManager::getProof(this);
-#else /* IS_PROOFS_BUILD */
- throw ModalException("This build of CVC4 doesn't have proof support.");
-#endif /* IS_PROOFS_BUILD */
-}
-
void SmtEngine::printInstantiations( std::ostream& out ) {
SmtScope smts(this);
finishInit();
#include "smt/smt_mode.h"
#include "theory/logic_info.h"
#include "util/hash.h"
-#include "util/proof.h"
#include "util/result.h"
#include "util/sexpr.h"
#include "util/statistics.h"
*/
std::vector<std::pair<Expr, Expr> > getAssignment();
- /**
- * Get the last proof (only if immediately preceded by an UNSAT or ENTAILED
- * query). Only permitted if CVC4 was built with proof support and
- * produce-proofs is on.
- *
- * The Proof object is owned by this SmtEngine until the SmtEngine is
- * destroyed.
- */
- const Proof& getProof();
-
/** Print all instantiations made by the quantifiers module. */
void printInstantiations(std::ostream& out);
return d_statisticsRegistry.get();
};
- /**
- * Check that a generated proof (via getProof()) checks.
- */
- void checkProof();
-
/**
* Internal method to get an unsatisfiable core (only if immediately preceded
* by an UNSAT or ENTAILED query). Only permitted if CVC4 was built with
#include "base/check.h"
#include "base/configuration_private.h"
#include "base/output.h"
-#include "proof/proof.h"
#include "smt/smt_engine.h"
namespace CVC4 {
d_cnfConversionTime("smt::SmtEngine::cnfConversionTime"),
d_numAssertionsPre("smt::SmtEngine::numAssertionsPreITERemoval", 0),
d_numAssertionsPost("smt::SmtEngine::numAssertionsPostITERemoval", 0),
- d_proofsSize("smt::SmtEngine::proofsSize", 0),
d_checkModelTime("smt::SmtEngine::checkModelTime"),
- d_lfscCheckProofTime("smt::SmtEngine::lfscCheckProofTime"),
d_checkUnsatCoreTime("smt::SmtEngine::checkUnsatCoreTime"),
d_solveTime("smt::SmtEngine::solveTime"),
d_pushPopTime("smt::SmtEngine::pushPopTime"),
smtStatisticsRegistry()->registerStat(&d_cnfConversionTime);
smtStatisticsRegistry()->registerStat(&d_numAssertionsPre);
smtStatisticsRegistry()->registerStat(&d_numAssertionsPost);
- smtStatisticsRegistry()->registerStat(&d_proofsSize);
smtStatisticsRegistry()->registerStat(&d_checkModelTime);
- smtStatisticsRegistry()->registerStat(&d_lfscCheckProofTime);
smtStatisticsRegistry()->registerStat(&d_checkUnsatCoreTime);
smtStatisticsRegistry()->registerStat(&d_solveTime);
smtStatisticsRegistry()->registerStat(&d_pushPopTime);
smtStatisticsRegistry()->unregisterStat(&d_cnfConversionTime);
smtStatisticsRegistry()->unregisterStat(&d_numAssertionsPre);
smtStatisticsRegistry()->unregisterStat(&d_numAssertionsPost);
- smtStatisticsRegistry()->unregisterStat(&d_proofsSize);
smtStatisticsRegistry()->unregisterStat(&d_checkModelTime);
- smtStatisticsRegistry()->unregisterStat(&d_lfscCheckProofTime);
smtStatisticsRegistry()->unregisterStat(&d_checkUnsatCoreTime);
smtStatisticsRegistry()->unregisterStat(&d_solveTime);
smtStatisticsRegistry()->unregisterStat(&d_pushPopTime);
IntStat d_numAssertionsPre;
/** Number of assertions after ite removal */
IntStat d_numAssertionsPost;
- /** Size of all proofs generated */
- IntStat d_proofsSize;
/** time spent in checkModel() */
TimerStat d_checkModelTime;
- /** time spent checking the proof with LFSC */
- TimerStat d_lfscCheckProofTime;
/** time spent in checkUnsatCore() */
TimerStat d_checkUnsatCoreTime;
/** time spent in PropEngine::checkSat() */
#include "smt/smt_solver.h"
-#include "proof/theory_proof.h"
#include "prop/prop_engine.h"
#include "smt/assertions.h"
#include "smt/preprocessor.h"
++id)
{
theory::TheoryConstructor::addTheory(d_theoryEngine.get(), id);
- // register with proof engine if applicable
-#ifdef CVC4_PROOF
- ProofManager::currentPM()->getTheoryProofEngine()->registerTheory(
- d_theoryEngine->theoryOf(id));
-#endif
}
Trace("smt-debug") << "Making prop engine..." << std::endl;
// set the filename on the result
Result r = Result(result, filename);
-
+
// notify our state of the check-sat result
d_state.notifyCheckSatResult(hasAssumptions, r);
#include "expr/node_algorithm.h"
#include "expr/skolem_manager.h"
-#include "options/proof_options.h"
+#include "options/smt_options.h"
#include "proof/proof_manager.h"
using namespace std;
{
Node itesRemoved = run(assertion, newAsserts, newSkolems, false, false);
// In some calling contexts, not necessary to report dependence information.
- if (reportDeps
- && (options::unsatCores() || options::fewerPreprocessingHoles()))
+ if (reportDeps && options::unsatCores())
{
// new assertions have a dependence on the node
- PROOF(ProofManager::currentPM()->addDependence(itesRemoved, assertion);)
+ if (options::unsatCores())
+ {
+ ProofManager::currentPM()->addDependence(itesRemoved, assertion);
+ }
unsigned n = 0;
while (n < newAsserts.size())
{
- PROOF(ProofManager::currentPM()->addDependence(newAsserts[n].getProven(),
- assertion);)
+ if (options::unsatCores())
+ {
+ ProofManager::currentPM()->addDependence(newAsserts[n].getProven(),
+ assertion);
+ }
++n;
}
}
}else if( !inTerm && hasNestedTermChildren( node ) ){
// Remember if we're inside a term
inTerm = true;
- }
+ }
vector<Node> newChildren;
bool somethingChanged = false;
}
}
-// returns true if the children of node should be considered nested terms
+// returns true if the children of node should be considered nested terms
bool RemoveTermFormulas::hasNestedTermChildren( TNode node ) {
- return theory::kindToTheoryId(node.getKind())!=theory::THEORY_BOOL &&
- node.getKind()!=kind::EQUAL && node.getKind()!=kind::SEP_STAR &&
- node.getKind()!=kind::SEP_WAND && node.getKind()!=kind::SEP_LABEL &&
- node.getKind()!=kind::BITVECTOR_EAGER_ATOM;
- // dont' worry about FORALL or EXISTS (handled separately)
+ return theory::kindToTheoryId(node.getKind()) != theory::THEORY_BOOL
+ && node.getKind() != kind::EQUAL && node.getKind() != kind::SEP_STAR
+ && node.getKind() != kind::SEP_WAND
+ && node.getKind() != kind::SEP_LABEL
+ && node.getKind() != kind::BITVECTOR_EAGER_ATOM;
+ // dont' worry about FORALL or EXISTS (handled separately)
}
Node RemoveTermFormulas::getAxiomFor(Node n)
**/
#include "theory/arith/callbacks.h"
+
+#include "theory/arith/proof_macros.h"
#include "theory/arith/theory_arith_private.h"
namespace CVC4 {
d_consequent = NullConstraint;
d_constraints.clear();
d_consequentSet = false;
- PROOF(d_farkas.clear());
+ ARITH_PROOF(d_farkas.clear());
Assert(!underConstruction());
}
/* Adds a constraint to the constraint under construction. */
void FarkasConflictBuilder::addConstraint(ConstraintCP c, const Rational& fc){
Assert(
- !PROOF_ON()
+ !ARITH_PROOF_ON()
|| (!underConstruction() && d_constraints.empty() && d_farkas.empty())
|| (underConstruction() && d_constraints.size() + 1 == d_farkas.size()));
- Assert(PROOF_ON() || d_farkas.empty());
+ Assert(ARITH_PROOF_ON() || d_farkas.empty());
Assert(c->isTrue());
if(d_consequent == NullConstraint){
} else {
d_constraints.push_back(c);
}
- PROOF(d_farkas.push_back(fc););
- Assert(!PROOF_ON() || d_constraints.size() + 1 == d_farkas.size());
- Assert(PROOF_ON() || d_farkas.empty());
+ ARITH_PROOF(d_farkas.push_back(fc));
+ Assert(!ARITH_PROOF_ON() || d_constraints.size() + 1 == d_farkas.size());
+ Assert(ARITH_PROOF_ON() || d_farkas.empty());
}
void FarkasConflictBuilder::addConstraint(ConstraintCP c, const Rational& fc, const Rational& mult){
Assert(!mult.isZero());
- if(PROOF_ON() && !mult.isOne()){
+ if (ARITH_PROOF_ON() && !mult.isOne())
+ {
Rational prod = fc * mult;
addConstraint(c, prod);
- }else{
+ }
+ else
+ {
addConstraint(c, fc);
}
}
ConstraintCP last = d_constraints.back();
d_constraints.back() = d_consequent;
d_consequent = last;
- PROOF( std::swap( d_farkas.front(), d_farkas.back() ) );
+ ARITH_PROOF(std::swap(d_farkas.front(), d_farkas.back()));
d_consequentSet = true;
}
Assert(underConstruction());
Assert(!d_constraints.empty());
Assert(
- !PROOF_ON()
+ !ARITH_PROOF_ON()
|| (!underConstruction() && d_constraints.empty() && d_farkas.empty())
|| (underConstruction() && d_constraints.size() + 1 == d_farkas.size()));
- Assert(PROOF_ON() || d_farkas.empty());
+ Assert(ARITH_PROOF_ON() || d_farkas.empty());
Assert(d_consequentSet);
ConstraintP not_c = d_consequent->getNegation();
- RationalVectorCP coeffs = NULLPROOF(&d_farkas);
+ RationalVectorCP coeffs = ARITH_NULLPROOF(&d_farkas);
not_c->impliedByFarkas(d_constraints, coeffs, true );
reset();
#include <unordered_set>
#include "base/output.h"
-#include "proof/proof.h"
#include "smt/smt_statistics_registry.h"
#include "theory/arith/arith_utilities.h"
#include "theory/arith/normal_form.h"
void Constraint::printProofTree(std::ostream& out, size_t depth) const
{
-#if IS_PROOFS_BUILD
- const ConstraintRule& rule = getConstraintRule();
- out << std::string(2 * depth, ' ') << "* " << getVariable() << " [";
- if (hasLiteral())
+ if (ARITH_PROOF_ON())
{
- out << getLiteral();
- }
- else
- {
- out << "NOLIT";
- };
- out << "]" << ' ' << getType() << ' ' << getValue() << " (" << getProofType()
- << ")";
- if (getProofType() == FarkasAP)
- {
- out << " [";
- bool first = true;
- for (const auto& coeff : *rule.d_farkasCoefficients)
+ const ConstraintRule& rule = getConstraintRule();
+ out << std::string(2 * depth, ' ') << "* " << getVariable() << " [";
+ if (hasLiteral())
{
- if (not first)
+ out << getLiteral();
+ }
+ else
+ {
+ out << "NOLIT";
+ };
+ out << "]" << ' ' << getType() << ' ' << getValue() << " ("
+ << getProofType() << ")";
+ if (getProofType() == FarkasAP)
+ {
+ out << " [";
+ bool first = true;
+ for (const auto& coeff : *rule.d_farkasCoefficients)
{
- out << ", ";
+ if (not first)
+ {
+ out << ", ";
+ }
+ first = false;
+ out << coeff;
}
- first = false;
- out << coeff;
+ out << "]";
}
- out << "]";
- }
- out << endl;
+ out << endl;
- for (AntecedentId i = rule.d_antecedentEnd; i != AntecedentIdSentinel; --i) {
- ConstraintCP antecdent = d_database->getAntecedent(i);
- if (antecdent == NullConstraint) {
- break;
+ for (AntecedentId i = rule.d_antecedentEnd; i != AntecedentIdSentinel; --i)
+ {
+ ConstraintCP antecdent = d_database->getAntecedent(i);
+ if (antecdent == NullConstraint)
+ {
+ break;
+ }
+ antecdent->printProofTree(out, depth + 1);
}
- antecdent->printProofTree(out, depth + 1);
+ return;
}
-#else /* IS_PROOFS_BUILD */
out << "Cannot print proof. This is not a proof build." << endl;
-#endif /* IS_PROOFS_BUILD */
}
bool Constraint::sanityChecking(Node n) const {
void ConstraintRule::print(std::ostream& out) const {
-
- RationalVectorCP coeffs = NULLPROOF(d_farkasCoefficients);
+ RationalVectorCP coeffs = ARITH_NULLPROOF(d_farkasCoefficients);
out << "{ConstraintRule, ";
out << d_constraint << std::endl;
out << "d_proofType= " << d_proofType << ", " << std::endl;
if (d_constraint != NullConstraint && d_antecedentEnd != AntecedentIdSentinel)
{
const ConstraintDatabase& database = d_constraint->getDatabase();
-
+
size_t coeffIterator = (coeffs != RationalVectorCPSentinel) ? coeffs->size()-1 : 0;
AntecedentId p = d_antecedentEnd;
// must have at least one antecedent
ConstraintCP antecedent = d_database->d_antecedents[p];
if(antecedent == NullConstraint) { return false; }
-#if IS_PROOFS_BUILD
- if(!PROOF_ON()){ return cr.d_farkasCoefficients == RationalVectorCPSentinel; }
- Assert(PROOF_ON());
+ if (!ARITH_PROOF_ON())
+ {
+ return cr.d_farkasCoefficients == RationalVectorCPSentinel;
+ }
+ Assert(ARITH_PROOF_ON());
if(cr.d_farkasCoefficients == RationalVectorCPSentinel){ return false; }
if(cr.d_farkasCoefficients->size() < 2){ return false; }
default:
return false;
}
-
+
if(coeffIterator == coeffBegin){ return false; }
--coeffIterator;
--p;
// 0 = lhs <= rhs < 0
return (lhs.isNull() || (Constant::isMember(lhs) && Constant(lhs).isZero()))
&& rhs.sgn() < 0;
-
-#else /* IS_PROOFS_BUILD */
- return true;
-#endif /* IS_PROOFS_BUILD */
}
ConstraintP Constraint::makeNegation(ArithVar v, ConstraintType t, const DeltaRational& r){
, d_one(1)
, d_negOne(-1)
{
-
}
SortedConstraintMap& ConstraintDatabase::getVariableSCM(ArithVar v) const{
return isNot ? hit->getNegation(): hit;
}else{
Comparison negCmp = Comparison::parseNormalForm(negationNode);
-
+
ConstraintType negType = Constraint::constraintTypeOfComparison(negCmp);
DeltaRational negDR = negCmp.normalizedDeltaRational();
AntecedentId antecedentEnd = d_database->d_antecedents.size() - 1;
RationalVectorP coeffs;
- if(PROOF_ON()){
+ if (ARITH_PROOF_ON())
+ {
std::pair<int, int> sgns = unateFarkasSigns(getNegation(), imp);
Rational first(sgns.first);
coeffs = new RationalVector();
coeffs->push_back(first);
coeffs->push_back(second);
- } else {
+ }
+ else
+ {
coeffs = RationalVectorPSentinel;
}
-
// no need to delete coeffs the memory is owned by ConstraintRule
d_database->pushConstraintRule(ConstraintRule(this, FarkasAP, antecedentEnd, coeffs));
if(Debug.isOn("constraint::conflictCommit") && inConflict()){
Debug("constraint::conflictCommit") << "inConflict@impliedByUnate " << this << std::endl;
}
-
+
if(Debug.isOn("constraints::wffp") && !wellFormedFarkasProof()){
getConstraintRule().print(Debug("constraints::wffp"));
}
* coeffs != RationalVectorSentinal,
* coeffs->size() = a.size() + 1,
* for i in [0,a.size) : coeff[i] corresponds to a[i], and
- * coeff.back() corresponds to the current constraint.
+ * coeff.back() corresponds to the current constraint.
*/
void Constraint::impliedByFarkas(const ConstraintCPVec& a, RationalVectorCP coeffs, bool nowInConflict){
Debug("constraints::pf") << "impliedByFarkas(" << this;
Assert(negationHasProof() == nowInConflict);
Assert(allHaveProof(a));
- Assert(PROOF_ON() == (coeffs != RationalVectorCPSentinel));
- // !PROOF_ON() => coeffs == RationalVectorCPSentinel
- // PROOF_ON() => coeffs->size() == a.size() + 1
- Assert(!PROOF_ON() || coeffs->size() == a.size() + 1);
+ Assert(ARITH_PROOF_ON() == (coeffs != RationalVectorCPSentinel));
+ Assert(!ARITH_PROOF_ON() || coeffs->size() == a.size() + 1);
+
Assert(a.size() >= 1);
d_database->d_antecedents.push_back(NullConstraint);
AntecedentId antecedentEnd = d_database->d_antecedents.size() - 1;
RationalVectorCP coeffsCopy;
- if(PROOF_ON()){
+ if (ARITH_PROOF_ON())
+ {
Assert(coeffs != RationalVectorCPSentinel);
coeffsCopy = new RationalVector(*coeffs);
- } else {
+ }
+ else
+ {
coeffsCopy = RationalVectorCPSentinel;
}
d_database->pushConstraintRule(ConstraintRule(this, FarkasAP, antecedentEnd, coeffsCopy));
#ifndef CVC4__THEORY__ARITH__CONSTRAINT_H
#define CVC4__THEORY__ARITH__CONSTRAINT_H
-#include <unordered_map>
#include <list>
#include <set>
+#include <unordered_map>
#include <vector>
#include "base/configuration_private.h"
#include "context/cdqueue.h"
#include "context/context.h"
#include "expr/node.h"
-#include "proof/proof.h"
#include "theory/arith/arithvar.h"
#include "theory/arith/callbacks.h"
#include "theory/arith/congruence_manager.h"
#include "theory/arith/constraint_forward.h"
#include "theory/arith/delta_rational.h"
+#include "theory/arith/proof_macros.h"
namespace CVC4 {
namespace theory {
}
};
-
/**
* If proofs are on, there is a vector of rationals for farkas coefficients.
- * This is the owner of the memory for the vector, and calls delete upon cleanup.
- *
+ * This is the owner of the memory for the vector, and calls delete upon
+ * cleanup.
+ *
*/
struct ConstraintRule {
ConstraintP d_constraint;
* We do however use all of the constraints by requiring non-zero
* coefficients.
*/
-#if IS_PROOFS_BUILD
RationalVectorCP d_farkasCoefficients;
-#endif /* IS_PROOFS_BUILD */
ConstraintRule()
: d_constraint(NullConstraint)
, d_proofType(NoAP)
, d_antecedentEnd(AntecedentIdSentinel)
{
-#if IS_PROOFS_BUILD
d_farkasCoefficients = RationalVectorCPSentinel;
-#endif /* IS_PROOFS_BUILD */
}
ConstraintRule(ConstraintP con, ArithProofType pt)
, d_proofType(pt)
, d_antecedentEnd(AntecedentIdSentinel)
{
-#if IS_PROOFS_BUILD
d_farkasCoefficients = RationalVectorCPSentinel;
-#endif /* IS_PROOFS_BUILD */
}
ConstraintRule(ConstraintP con, ArithProofType pt, AntecedentId antecedentEnd)
: d_constraint(con)
, d_proofType(pt)
, d_antecedentEnd(antecedentEnd)
{
-#if IS_PROOFS_BUILD
d_farkasCoefficients = RationalVectorCPSentinel;
-#endif /* IS_PROOFS_BUILD */
}
ConstraintRule(ConstraintP con, ArithProofType pt, AntecedentId antecedentEnd, RationalVectorCP coeffs)
, d_proofType(pt)
, d_antecedentEnd(antecedentEnd)
{
- Assert(PROOF_ON() || coeffs == RationalVectorCPSentinel);
-#if IS_PROOFS_BUILD
+ Assert(ARITH_PROOF_ON() || coeffs == RationalVectorCPSentinel);
d_farkasCoefficients = coeffs;
-#endif /* IS_PROOFS_BUILD */
}
void print(std::ostream& out) const;
/**
* If the constraint
- * canBePropagated() and
+ * canBePropagated() and
* !assertedToTheTheory(),
* the constraint is added to the database's propagation queue.
*
ConstraintP constraint = crp->d_constraint;
Assert(constraint->d_crid != ConstraintRuleIdSentinel);
constraint->d_crid = ConstraintRuleIdSentinel;
-
- PROOF(if (crp->d_farkasCoefficients != RationalVectorCPSentinel) {
- delete crp->d_farkasCoefficients;
+ ARITH_PROOF({
+ if (crp->d_farkasCoefficients != RationalVectorCPSentinel)
+ {
+ delete crp->d_farkasCoefficients;
+ }
});
}
};
return getConstraintRule().d_antecedentEnd;
}
- inline RationalVectorCP getFarkasCoefficients() const {
- return NULLPROOF(getConstraintRule().d_farkasCoefficients);
+ inline RationalVectorCP getFarkasCoefficients() const
+ {
+ return ARITH_NULLPROOF(getConstraintRule().d_farkasCoefficients);
}
-
+
void debugPrint() const;
/**
* The index in this list is the proper ordering of the proofs.
*/
ConstraintRuleList d_constraintProofs;
-
-
+
/**
* Contains the exact list of constraints that can be used for propagation.
*/
const Rational d_one;
const Rational d_negOne;
-
+
friend class Constraint;
-
+
public:
ConstraintDatabase( context::Context* satContext,
/** AntecendentID must be in range. */
ConstraintCP getAntecedent(AntecedentId p) const;
-
+
private:
/** returns true if cons is now in conflict. */
bool handleUnateProp(ConstraintP ant, ConstraintP cons);
RowIndex ridx = d_tableau.basicToRowIndex(basic);
ConstraintCPVec bounds;
- RationalVectorP coeffs = NULLPROOF(new RationalVector());
+ RationalVectorP coeffs = ARITH_NULLPROOF(new RationalVector());
propagateRow(bounds, ridx, upperBound, c, coeffs);
c->impliedByFarkas(bounds, coeffs, false);
c->tryToPropagate();
-
+
if(coeffs != RationalVectorPSentinel) { delete coeffs; }
}
* The proof is in terms of the other constraints and the negation of c, ~c.
*
* A row has the form:
- * sum a_i * x_i = 0
+ * sum a_i * x_i = 0
* or
- * sx + sum r y + sum q z = 0
+ * sx + sum r y + sum q z = 0
* where r > 0 and q < 0.
*
* If rowUp, we are proving c
Assert(farkas->empty());
farkas->push_back(Rational(0));
}
-
+
ArithVar v = c->getVariable();
Debug("arith::propagateRow") << "LinearEqualityModule::propagateRow("
<< ridx << ", " << rowUp << ", " << v << ") start" << endl;
const Rational& multiple = rowUp ? d_one : d_negOne;
Debug("arith::propagateRow") << "multiple: " << multiple << endl;
-
+
Tableau::RowIterator iter = d_tableau.ridRowIterator(ridx);
for(; !iter.atEnd(); ++iter){
const Tableau::Entry& entry = *iter;
if(farkas != RationalVectorPSentinel){
Assert(farkas->front().isZero());
Rational multAij = multiple * a_ij;
- Debug("arith::propagateRow") << "("<<multAij<<") ";
- farkas->front() = multAij;
+ Debug("arith::propagateRow") << "(" << multAij << ") ";
+ farkas->front() = multAij;
}
Debug("arith::propagateRow") << c << endl;
ConstraintCP bound = selectUb
? d_variables.getUpperBoundConstraint(nonbasic)
: d_variables.getLowerBoundConstraint(nonbasic);
-
+
if(farkas != RationalVectorPSentinel){
Rational multAij = multiple * a_ij;
- Debug("arith::propagateRow") << "("<<multAij<<") ";
+ Debug("arith::propagateRow") << "(" << multAij << ") ";
farkas->push_back(multAij);
}
Assert(bound != NullConstraint);
* If !aboveUpper, then the conflict is with the constraint c : x_b >= l_b.
*
* A row has the form:
- * -x_b sum a_i * x_i = 0
+ * -x_b sum a_i * x_i = 0
* or
* -x_b + sum r y + sum q z = 0,
* x_b = sum r y + sum q z
Assert(assignment < d_variables.getLowerBound(basicVar));
surplus = d_variables.getLowerBound(basicVar) - assignment;
}
-
+
bool anyWeakenings = false;
for(Tableau::RowIterator i = d_tableau.basicRowIterator(basicVar); !i.atEnd(); ++i){
const Tableau::Entry& entry = *i;
#include "expr/node_algorithm.h"
#include "options/arith_options.h"
+#include "options/smt_options.h"
#include "options/theory_options.h"
#include "theory/arith/arith_msum.h"
#include "theory/arith/arith_utilities.h"
d_internal(
new TheoryArithPrivate(*this, c, u, out, valuation, logicInfo, pnm)),
d_ppRewriteTimer("theory::arith::ppRewriteTimer"),
- d_proofRecorder(nullptr),
d_astate(*d_internal, c, u, valuation)
{
smtStatisticsRegistry()->registerStat(&d_ppRewriteTimer);
#pragma once
#include "expr/node.h"
-#include "proof/arith_proof_recorder.h"
#include "theory/arith/arith_state.h"
#include "theory/arith/theory_arith_private_forward.h"
#include "theory/theory.h"
TimerStat d_ppRewriteTimer;
- /**
- * @brief Where to store Farkas proofs of lemmas
- */
- proof::ArithProofRecorder * d_proofRecorder;
-
public:
TheoryArith(context::Context* c,
context::UserContext* u,
std::pair<bool, Node> entailmentCheck(TNode lit) override;
- void setProofRecorder(proof::ArithProofRecorder* proofRecorder)
- {
- d_proofRecorder = proofRecorder;
- }
-
private:
/** The state object wrapping TheoryArithPrivate */
ArithState d_astate;
ConstraintP ubc = d_partialModel.getUpperBoundConstraint(x_i);
ConstraintP negation = constraint->getNegation();
negation->impliedByUnate(ubc, true);
-
+
raiseConflict(constraint);
++(d_statistics.d_statAssertLowerConflicts);
if(d_partialModel.greaterThanUpperBound(x_i, c_i) ){ // \upperbound(x_i) <= c_i
return false; //sat
}
-
+
// cmpToLb = \lowerbound(x_i).cmp(c_i)
int cmpToLB = d_partialModel.cmpToLowerBound(x_i, c_i);
if( cmpToLB < 0 ){ // \upperbound(x_i) < \lowerbound(x_i)
++(d_statistics.d_statDisequalityConflicts);
raiseConflict(eq);
return true;
- }
+ }
}
}else if(cmpToLB > 0){
// l <= x <= u and l < u
}else{
if (d_nonlinearExtension == nullptr)
{
- if( vlNode.getKind()==kind::EXPONENTIAL || vlNode.getKind()==kind::SINE ||
- vlNode.getKind()==kind::COSINE || vlNode.getKind()==kind::TANGENT ){
+ if (vlNode.getKind() == kind::EXPONENTIAL
+ || vlNode.getKind() == kind::SINE || vlNode.getKind() == kind::COSINE
+ || vlNode.getKind() == kind::TANGENT)
+ {
d_nlIncomplete = true;
}
}
} else {
Debug("arith::constraint") << "already has proof: " << constraint->externalExplainByAssertions() << endl;
}
-
if(Debug.isOn("arith::negatedassumption") && inConflict){
ConstraintP negation = constraint->getNegation();
Debug("arith::conflict") << "outputting conflicts" << std::endl;
Assert(anyConflict());
static unsigned int conflicts = 0;
-
+
if(!conflictQueueEmpty()){
Assert(!d_conflicts.empty());
for(size_t i = 0, i_end = d_conflicts.size(); i < i_end; ++i){
++conflicts;
Debug("arith::conflict") << "d_conflicts[" << i << "] " << conflict
<< " has proof: " << hasProof << endl;
- PROOF(if (d_containing.d_proofRecorder && confConstraint->hasFarkasProof()
- && pf.d_farkasCoefficients->size()
- == conflict.getNumChildren()) {
- // The Farkas coefficients and the children of `conflict` seem to be in
- // opposite orders... There is some relevant documentation in the
- // comment for the d_farkasCoefficients field in "constraint.h"
- //
- // Anyways, we reverse the children in `conflict` here.
- NodeBuilder<> conflictInFarkasCoefficientOrder(kind::AND);
- for (size_t j = 0, nchildren = conflict.getNumChildren(); j < nchildren;
- ++j)
- {
- conflictInFarkasCoefficientOrder
- << conflict[conflict.getNumChildren() - j - 1];
- }
-
- if (Debug.isOn("arith::pf::tree")) {
- confConstraint->printProofTree(Debug("arith::pf::tree"));
- confConstraint->getNegation()->printProofTree(Debug("arith::pf::tree"));
- }
-
- Assert(conflict.getNumChildren() == pf.d_farkasCoefficients->size());
- if (confConstraint->hasSimpleFarkasProof()
- && confConstraint->getNegation()->isPossiblyTightenedAssumption())
- {
- d_containing.d_proofRecorder->saveFarkasCoefficients(
- conflictInFarkasCoefficientOrder, pf.d_farkasCoefficients);
- }
- })
if(Debug.isOn("arith::normalize::external")){
conflict = flattenAndSort(conflict);
Debug("arith::conflict") << "(normalized to) " << conflict << endl;
return make_pair(imp, added);
}
}
-
ConstraintP newc = d_constraintDatabase.getConstraint(v, t, dr);
d_replayConstraints.push_back(newc);
// ConstraintCPVec& back = conflicts.back();
// back.push_back(conflicting);
// back.push_back(negConflicting);
-
+
// // remove the floor/ceiling contraint implied by bcneg
// Constraint::assertionFringe(back);
}
}else{
Debug("approx::replayAssert") << "replayAssert " << c << " has explanation" << endl;
}
- Debug("approx::replayAssert") << "replayAssertion " << c << endl;
+ Debug("approx::replayAssert") << "replayAssertion " << c << endl;
if(inConflict){
raiseConflict(c);
}else{
assertionCases(c);
}
}else{
- Debug("approx::replayAssert") << "replayAssert " << c << " already asserted" << endl;
+ Debug("approx::replayAssert")
+ << "replayAssert " << c << " already asserted" << endl;
}
}
SimplexDecisionProcedure& simplex = selectSimplex(true);
simplex.findModel(false);
- // can change d_qflraStatus
+ // can change d_qflraStatus
d_linEq.stopTrackingBoundCounts();
d_partialModel.startQueueingBoundCounts();
<< " " << useApprox
<< " " << safeToCallApprox()
<< endl;
-
+
bool noPivotLimitPass1 = noPivotLimit && !useApprox;
d_qflraStatus = simplex.findModel(noPivotLimitPass1);
Debug("TheoryArithPrivate::solveRealRelaxation")
<< "solveRealRelaxation()" << " pass1 " << d_qflraStatus << endl;
-
+
if(d_qflraStatus == Result::SAT_UNKNOWN && useApprox && safeToCallApprox()){
// pass2: fancy-final
static const int32_t relaxationLimit = 10000;
// if(!useFancyFinal){
// d_qflraStatus = simplex.findModel(noPivotLimit);
// }else{
-
// if(d_qflraStatus == Result::SAT_UNKNOWN){
// //Message() << "got sat unknown" << endl;
Integer ceil_d = d.ceiling();
Rational f = r - floor_d;
// Multiply by -1 to get abs value.
- Rational c = (r - ceil_d) * (-1);
+ Rational c = (r - ceil_d) * (-1);
Integer nearest = (c > f) ? floor_d : ceil_d;
// Prioritize trying a simple rounding of the real solution first,
ConstraintP implied = d_constraintDatabase.getBestImpliedBound(v, t, bound);
if(implied != NullConstraint){
-
return rowImplicationCanBeApplied(ridx, rowUp, implied);
}
}
if( !assertedToTheTheory && canBePropagated && !hasProof ){
ConstraintCPVec explain;
-
- PROOF(d_farkasBuffer.clear());
- RationalVectorP coeffs = NULLPROOF(&d_farkasBuffer);
+ ARITH_PROOF(d_farkasBuffer.clear());
+ RationalVectorP coeffs = ARITH_NULLPROOF(&d_farkasBuffer);
// After invoking `propegateRow`:
// * coeffs[0] is for implied
}
Node implication = implied->externalImplication(explain);
Node clause = flattenImplication(implication);
- PROOF(if (d_containing.d_proofRecorder
- && coeffs != RationalVectorCPSentinel
- && coeffs->size() == clause.getNumChildren()) {
- Debug("arith::prop") << "implied : " << implied << std::endl;
- Debug("arith::prop") << "implication: " << implication << std::endl;
- Debug("arith::prop") << "coeff len: " << coeffs->size() << std::endl;
- Debug("arith::prop") << "exp : " << explain << std::endl;
- Debug("arith::prop") << "clause : " << clause << std::endl;
- Debug("arith::prop")
- << "clause len: " << clause.getNumChildren() << std::endl;
- Debug("arith::prop") << "exp len: " << explain.size() << std::endl;
- // Using the information from the above comment we assemble a conflict
- // AND in coefficient order
- NodeBuilder<> conflictInFarkasCoefficientOrder(kind::AND);
- conflictInFarkasCoefficientOrder << implication[1].negate();
- for (const Node& antecedent : implication[0])
- {
- Debug("arith::prop") << " ante: " << antecedent << std::endl;
- conflictInFarkasCoefficientOrder << antecedent;
- }
-
- Assert(coeffs != RationalVectorPSentinel);
- Assert(conflictInFarkasCoefficientOrder.getNumChildren()
- == coeffs->size());
- if (std::all_of(explain.begin(), explain.end(), [](ConstraintCP c) {
- return c->isAssumption() || c->hasIntTightenProof();
- }))
- {
- d_containing.d_proofRecorder->saveFarkasCoefficients(
- conflictInFarkasCoefficientOrder, coeffs);
- }
- })
outputLemma(clause);
}else{
Assert(!implied->negationHasProof());
+++ /dev/null
-/********************* */
-/*! \file array_proof_reconstruction.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Guy Katz, 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
- **
- ** [[ Add lengthier description here ]]
-
- ** \todo document this file
-
-**/
-
-#include "theory/arrays/array_proof_reconstruction.h"
-
-#include <memory>
-
-namespace CVC4 {
-namespace theory {
-namespace arrays {
-
-ArrayProofReconstruction::ArrayProofReconstruction(const eq::EqualityEngine* equalityEngine)
- : d_equalityEngine(equalityEngine) {
-}
-
-void ArrayProofReconstruction::setRowMergeTag(unsigned tag) {
- d_reasonRow = tag;
-}
-
-void ArrayProofReconstruction::setRow1MergeTag(unsigned tag) {
- d_reasonRow1 = tag;
-}
-
-void ArrayProofReconstruction::setExtMergeTag(unsigned tag) {
- d_reasonExt = tag;
-}
-
-void ArrayProofReconstruction::notify(
- unsigned reasonType, Node reason, Node a, Node b,
- std::vector<TNode>& equalities, eq::EqProof* proof) const {
- Debug("pf::array") << "ArrayProofReconstruction::notify( "
- << reason << ", " << a << ", " << b << std::endl;
-
-
- if (reasonType == d_reasonExt) {
- if (proof) {
- // Todo: here we assume that a=b is an assertion. We should probably call
- // explain() recursively, to explain this.
- std::shared_ptr<eq::EqProof> childProof = std::make_shared<eq::EqProof>();
- childProof->d_node = reason;
- proof->d_children.push_back(childProof);
- }
- }
-
- else if (reasonType == d_reasonRow) {
- // ROW rules mean that (i==k) OR ((a[i]:=t)[k] == a[k])
- // The equality here will be either (i == k) because ((a[i]:=t)[k] != a[k]),
- // or ((a[i]:=t)[k] == a[k]) because (i != k).
-
- if (proof) {
- if (a.getKind() == kind::SELECT) {
- // This is the case of ((a[i]:=t)[k] == a[k]) because (i != k).
-
- // The edge is ((a[i]:=t)[k], a[k]), or (a[k], (a[i]:=t)[k]). This flag should be
- // false in the first case and true in the second case.
- bool currentNodeIsUnchangedArray;
-
- Assert(a.getNumChildren() == 2);
- Assert(b.getNumChildren() == 2);
-
- if (a[0].getKind() == kind::VARIABLE || a[0].getKind() == kind::SKOLEM) {
- currentNodeIsUnchangedArray = true;
- } else if (b[0].getKind() == kind::VARIABLE || b[0].getKind() == kind::SKOLEM) {
- currentNodeIsUnchangedArray = false;
- } else {
- Assert(a[0].getKind() == kind::STORE);
- Assert(b[0].getKind() == kind::STORE);
-
- if (a[0][0] == b[0]) {
- currentNodeIsUnchangedArray = false;
- } else if (b[0][0] == a[0]) {
- currentNodeIsUnchangedArray = true;
- } else {
- Unreachable();
- }
- }
-
- Node indexOne = currentNodeIsUnchangedArray ? a[1] : a[0][1];
- Node indexTwo = currentNodeIsUnchangedArray ? b[0][1] : b[1];
-
- // Some assertions to ensure that the theory of arrays behaves as expected
- Assert(a[1] == b[1]);
- if (currentNodeIsUnchangedArray) {
- Assert(a[0] == b[0][0]);
- } else {
- Assert(a[0][0] == b[0]);
- }
-
- Debug("pf::ee") << "Getting explanation for ROW guard: "
- << indexOne << " != " << indexTwo << std::endl;
-
- std::shared_ptr<eq::EqProof> childProof =
- std::make_shared<eq::EqProof>();
- d_equalityEngine->explainEquality(indexOne, indexTwo, false, equalities,
- childProof.get());
-
- // It could be that the guard condition is a constant disequality. In
- // this case, we need to change it to a different format.
- bool haveNegChild = false;
- for (unsigned i = 0; i < childProof->d_children.size(); ++i) {
- if (childProof->d_children[i]->d_node.getKind() == kind::NOT)
- haveNegChild = true;
- }
-
- if ((childProof->d_children.size() != 0) &&
- (childProof->d_id == theory::eq::MERGED_THROUGH_CONSTANTS || !haveNegChild)) {
- // The proof has two children, explaining why each index is a (different) constant.
- Assert(childProof->d_children.size() == 2);
-
- Node constantOne, constantTwo;
- // Each subproof explains why one of the indices is constant.
-
- if (childProof->d_children[0]->d_id == theory::eq::MERGED_THROUGH_REFLEXIVITY) {
- constantOne = childProof->d_children[0]->d_node;
- } else {
- Assert(childProof->d_children[0]->d_node.getKind() == kind::EQUAL);
- if ((childProof->d_children[0]->d_node[0] == indexOne) ||
- (childProof->d_children[0]->d_node[0] == indexTwo)) {
- constantOne = childProof->d_children[0]->d_node[1];
- } else {
- constantOne = childProof->d_children[0]->d_node[0];
- }
- }
-
- if (childProof->d_children[1]->d_id == theory::eq::MERGED_THROUGH_REFLEXIVITY) {
- constantTwo = childProof->d_children[1]->d_node;
- } else {
- Assert(childProof->d_children[1]->d_node.getKind() == kind::EQUAL);
- if ((childProof->d_children[1]->d_node[0] == indexOne) ||
- (childProof->d_children[1]->d_node[0] == indexTwo)) {
- constantTwo = childProof->d_children[1]->d_node[1];
- } else {
- constantTwo = childProof->d_children[1]->d_node[0];
- }
- }
-
- std::shared_ptr<eq::EqProof> constantDisequalityProof =
- std::make_shared<eq::EqProof>();
- constantDisequalityProof->d_id = theory::eq::MERGED_THROUGH_CONSTANTS;
- constantDisequalityProof->d_node =
- NodeManager::currentNM()->mkNode(kind::EQUAL, constantOne, constantTwo).negate();
-
- // Middle is where we need to insert the new disequality
- std::vector<std::shared_ptr<eq::EqProof>>::iterator middle =
- childProof->d_children.begin();
- ++middle;
-
- childProof->d_children.insert(middle, constantDisequalityProof);
-
- childProof->d_id = theory::eq::MERGED_THROUGH_TRANS;
- childProof->d_node =
- NodeManager::currentNM()->mkNode(kind::EQUAL, indexOne, indexTwo).negate();
- }
-
- proof->d_children.push_back(childProof);
- } else {
- // This is the case of (i == k) because ((a[i]:=t)[k] != a[k]),
-
- Node indexOne = a;
- Node indexTwo = b;
-
- Debug("pf::ee") << "The two indices are: " << indexOne << ", " << indexTwo << std::endl
- << "The reason for the edge is: " << reason << std::endl;
-
- Assert(reason.getNumChildren() == 2);
- Debug("pf::ee") << "Getting explanation for ROW guard: " << reason[1] << std::endl;
-
- std::shared_ptr<eq::EqProof> childProof =
- std::make_shared<eq::EqProof>();
- d_equalityEngine->explainEquality(reason[1][0], reason[1][1], false,
- equalities, childProof.get());
- proof->d_children.push_back(childProof);
- }
- }
-
- }
-
- else if (reasonType == d_reasonRow1) {
- // No special handling required at this time
- }
-}
-
-}/* CVC4::theory::arrays namespace */
-}/* CVC4::theory namespace */
-}/* CVC4 namespace */
+++ /dev/null
-/********************* */
-/*! \file array_proof_reconstruction.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Paul Meng, Mathias Preiner, 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 Array-specific proof construction logic to be used during the
- ** equality engine's path reconstruction
- **/
-
-#include "cvc4_private.h"
-
-#ifndef CVC4__THEORY__ARRAYS__ARRAY_PROOF_RECONSTRUCTION_H
-#define CVC4__THEORY__ARRAYS__ARRAY_PROOF_RECONSTRUCTION_H
-
-#include "theory/uf/equality_engine.h"
-
-namespace CVC4 {
-namespace theory {
-namespace arrays {
-
-/**
- * A callback class to be invoked whenever the equality engine traverses
- * an "array-owned" edge during path reconstruction.
- */
-
-class ArrayProofReconstruction : public eq::PathReconstructionNotify {
-public:
- ArrayProofReconstruction(const eq::EqualityEngine* equalityEngine);
-
- void notify(unsigned reasonType, Node reason, Node a, Node b,
- std::vector<TNode>& equalities,
- eq::EqProof* proof) const override;
-
- void setRowMergeTag(unsigned tag);
- void setRow1MergeTag(unsigned tag);
- void setExtMergeTag(unsigned tag);
-
-private:
- /** Merge tag for ROW applications */
- unsigned d_reasonRow;
- /** Merge tag for ROW1 applications */
- unsigned d_reasonRow1;
- /** Merge tag for EXT applications */
- unsigned d_reasonExt;
-
- const eq::EqualityEngine* d_equalityEngine;
-}; /* class ArrayProofReconstruction */
-
-}/* CVC4::theory::arrays namespace */
-}/* CVC4::theory namespace */
-}/* CVC4 namespace */
-
-#endif /* CVC4__THEORY__ARRAYS__ARRAY_PROOF_RECONSTRUCTION_H */
#include "expr/node_algorithm.h"
#include "options/arrays_options.h"
#include "options/smt_options.h"
-#include "proof/array_proof.h"
-#include "proof/proof_manager.h"
-#include "proof/theory_proof.h"
#include "smt/command.h"
#include "smt/logic_exception.h"
#include "smt/smt_statistics_registry.h"
d_readTableContext(new context::Context()),
d_arrayMerges(c),
d_inCheckModel(false),
- d_proofReconstruction(nullptr),
d_dstrat(new TheoryArraysDecisionStrategy(this)),
d_dstratInit(false)
{
{
d_equalityEngine->addFunctionKind(kind::ARR_TABLE_FUN);
}
-
- d_proofReconstruction.reset(new ArrayProofReconstruction(d_equalityEngine));
- d_reasonRow = d_equalityEngine->getFreshMergeReasonType();
- d_reasonRow1 = d_equalityEngine->getFreshMergeReasonType();
- d_reasonExt = d_equalityEngine->getFreshMergeReasonType();
-
- d_proofReconstruction->setRowMergeTag(d_reasonRow);
- d_proofReconstruction->setRow1MergeTag(d_reasonRow1);
- d_proofReconstruction->setExtMergeTag(d_reasonExt);
-
- d_equalityEngine->addPathReconstructionTrigger(d_reasonRow,
- d_proofReconstruction.get());
- d_equalityEngine->addPathReconstructionTrigger(d_reasonRow1,
- d_proofReconstruction.get());
- d_equalityEngine->addPathReconstructionTrigger(d_reasonExt,
- d_proofReconstruction.get());
}
/////////////////////////////////////////////////////////////////////////////
}/* TheoryArrays::propagate(TNode) */
-void TheoryArrays::explain(TNode literal, std::vector<TNode>& assumptions,
- eq::EqProof* proof) {
- // Do the work
- bool polarity = literal.getKind() != kind::NOT;
- TNode atom = polarity ? literal : literal[0];
- //eq::EqProof * eqp = new eq::EqProof;
- // eq::EqProof * eqp = NULL;
- if (atom.getKind() == kind::EQUAL) {
- d_equalityEngine->explainEquality(
- atom[0], atom[1], polarity, assumptions, proof);
- } else {
- d_equalityEngine->explainPredicate(atom, polarity, assumptions, proof);
- }
- if (Debug.isOn("pf::array"))
- {
- if (proof)
- {
- Debug("pf::array") << " Proof is : " << std::endl;
- proof->debug_print("pf::array");
- }
-
- Debug("pf::array") << "Array: explain( " << literal << " ):" << std::endl
- << "\t";
- for (unsigned i = 0; i < assumptions.size(); ++i)
- {
- Debug("pf::array") << assumptions[i] << " ";
- }
- Debug("pf::array") << std::endl;
- }
-}
-
TNode TheoryArrays::weakEquivGetRep(TNode node) {
TNode pointer;
while (true) {
}
// Apply RIntro1 Rule
- d_equalityEngine->assertEquality(ni.eqNode(v), true, d_true, d_reasonRow1);
+ d_equalityEngine->assertEquality(
+ ni.eqNode(v), true, d_true, theory::eq::MERGED_THROUGH_ROW1);
d_infoMap.addStore(node, node);
d_infoMap.addInStore(a, node);
}
}
-TrustNode TheoryArrays::explain(TNode literal)
+void TheoryArrays::explain(TNode literal, Node& explanation)
{
- Node explanation = explain(literal, NULL);
- return TrustNode::mkTrustPropExp(literal, explanation, nullptr);
-}
-
-Node TheoryArrays::explain(TNode literal, eq::EqProof* proof) {
++d_numExplain;
Debug("arrays") << spaces(getSatContext()->getLevel())
<< "TheoryArrays::explain(" << literal << ")" << std::endl;
std::vector<TNode> assumptions;
- explain(literal, assumptions, proof);
- return mkAnd(assumptions);
+ // Do the work
+ bool polarity = literal.getKind() != kind::NOT;
+ TNode atom = polarity ? literal : literal[0];
+ if (atom.getKind() == kind::EQUAL)
+ {
+ d_equalityEngine->explainEquality(
+ atom[0], atom[1], polarity, assumptions, nullptr);
+ }
+ else
+ {
+ d_equalityEngine->explainPredicate(atom, polarity, assumptions, nullptr);
+ }
+ explanation = mkAnd(assumptions);
+}
+
+TrustNode TheoryArrays::explain(TNode literal)
+{
+ Node explanation;
+ explain(literal, explanation);
+ return TrustNode::mkTrustPropExp(literal, explanation, nullptr);
}
/////////////////////////////////////////////////////////////////////////////
TNode k;
// k is the skolem for this disequality.
- if (!d_proofsEnabled) {
- Debug("pf::array") << "Check: kind::NOT: array theory making a skolem" << std::endl;
-
- // If not in replay mode, generate a fresh skolem variable
- k = getSkolem(fact,
- "array_ext_index",
- indexType,
- "an extensional lemma index variable from the theory of arrays",
- false);
-
- // Register this skolem for the proof replay phase
- PROOF(ProofManager::getSkolemizationManager()->registerSkolem(fact, k));
- } else {
- if (!ProofManager::getSkolemizationManager()->hasSkolem(fact)) {
- // In the solution pass we didn't need this skolem. Therefore, we don't need it
- // in this reply pass, either.
- break;
- }
-
- // Reuse the same skolem as in the solution pass
- k = ProofManager::getSkolemizationManager()->getSkolem(fact);
- Debug("pf::array") << "Skolem = " << k << std::endl;
- }
-
+ Debug("pf::array")
+ << "Check: kind::NOT: array theory making a skolem"
+ << std::endl;
+ k = getSkolem(
+ fact,
+ "array_ext_index",
+ indexType,
+ "an extensional lemma index variable from the theory of arrays",
+ false);
Node ak = nm->mkNode(kind::SELECT, fact[0][0], k);
Node bk = nm->mkNode(kind::SELECT, fact[0][1], k);
Node eq = ak.eqNode(bk);
Node lemma = fact[0].orNode(eq.notNode());
- // In solve mode we don't care if ak and bk are registered. If they aren't, they'll be registered
- // when we output the lemma. However, in replay need the lemma to be propagated, and so we
- // preregister manually.
- if (d_proofsEnabled) {
- if (!d_equalityEngine->hasTerm(ak))
- {
- preRegisterTermInternal(ak);
- }
- if (!d_equalityEngine->hasTerm(bk))
- {
- preRegisterTermInternal(bk);
- }
- }
-
if (options::arraysPropagate() > 0 && d_equalityEngine->hasTerm(ak)
&& d_equalityEngine->hasTerm(bk))
{
<< "\teq = " << eq << std::endl
<< "\treason = " << fact << std::endl;
- d_equalityEngine->assertEquality(eq, false, fact, d_reasonExt);
+ d_equalityEngine->assertEquality(
+ eq, false, fact, theory::eq::MERGED_THROUGH_EXT);
++d_numProp;
}
- if (!d_proofsEnabled) {
- // If this is the solution pass, generate the lemma. Otherwise, don't generate it -
- // as this is the lemma that we're reproving...
- Trace("arrays-lem")<<"Arrays::addExtLemma " << lemma <<"\n";
- d_out->lemma(lemma);
- ++d_numExt;
- }
+ // If this is the solution pass, generate the lemma. Otherwise,
+ // don't generate it - as this is the lemma that we're reproving...
+ Trace("arrays-lem") << "Arrays::addExtLemma " << lemma << "\n";
+ d_out->lemma(lemma);
+ ++d_numExt;
} else {
Debug("pf::array") << "Check: kind::NOT: array theory NOT making a skolem" << std::endl;
d_modelConstraints.push_back(fact);
lemma = mkAnd(conjunctions, true);
// LSH FIXME: which kind of arrays lemma is this
Trace("arrays-lem") << "Arrays::addExtLemma " << lemma <<"\n";
- d_out->lemma(lemma, RULE_INVALID, LemmaProperty::SEND_ATOMS);
+ d_out->lemma(lemma, LemmaProperty::SEND_ATOMS);
d_readTableContext->pop();
Trace("arrays") << spaces(getSatContext()->getLevel()) << "Arrays::check(): done" << endl;
return;
if (!bjExists) {
preRegisterTermInternal(bj);
}
- d_equalityEngine->assertEquality(aj_eq_bj, true, reason, d_reasonRow);
+ d_equalityEngine->assertEquality(
+ aj_eq_bj, true, reason, theory::eq::MERGED_THROUGH_ROW);
++d_numProp;
return;
}
(aj.isConst() && bj.isConst()) ? d_true : aj.eqNode(bj).notNode();
Node i_eq_j = i.eqNode(j);
d_permRef.push_back(reason);
- d_equalityEngine->assertEquality(i_eq_j, true, reason, d_reasonRow);
+ d_equalityEngine->assertEquality(
+ i_eq_j, true, reason, theory::eq::MERGED_THROUGH_ROW);
++d_numProp;
return;
}
&& !d_equalityEngine->areDisequal(i, j, false))
{
Node i_eq_j;
- if (!d_proofsEnabled) {
- i_eq_j = d_valuation.ensureLiteral(i.eqNode(j)); // TODO: think about this
- } else {
- i_eq_j = i.eqNode(j);
- }
-
+ i_eq_j = d_valuation.ensureLiteral(i.eqNode(j)); // TODO: think about this
+#if 0
+ i_eq_j = i.eqNode(j);
+#endif
getOutputChannel().requirePhase(i_eq_j, true);
d_decisionRequests.push(i_eq_j);
}
// TODO: maybe add triggers here
- if ((options::arraysEagerLemmas() || bothExist) && !d_proofsEnabled) {
+ if (options::arraysEagerLemmas() || bothExist)
+ {
// Make sure that any terms introduced by rewriting are appropriately stored in the equality database
Node aj2 = Rewriter::rewrite(aj);
if (aj != aj2) {
void TheoryArrays::conflict(TNode a, TNode b) {
Debug("pf::array") << "TheoryArrays::Conflict called" << std::endl;
- std::shared_ptr<eq::EqProof> proof = d_proofsEnabled ?
- std::make_shared<eq::EqProof>() : nullptr;
- d_conflictNode = explain(a.eqNode(b), proof.get());
+ explain(a.eqNode(b), d_conflictNode);
if (!d_inCheckModel) {
- std::unique_ptr<ProofArray> proof_array;
-
- if (d_proofsEnabled) {
- proof->debug_print("pf::array");
- proof_array.reset(new ProofArray(proof,
- /*row=*/d_reasonRow,
- /*row1=*/d_reasonRow1,
- /*ext=*/d_reasonExt));
- }
-
- d_out->conflict(d_conflictNode, std::move(proof_array));
+ d_out->conflict(d_conflictNode);
}
d_conflict = true;
#include "context/cdhashset.h"
#include "context/cdqueue.h"
#include "theory/arrays/array_info.h"
-#include "theory/arrays/array_proof_reconstruction.h"
#include "theory/arrays/theory_arrays_rewriter.h"
#include "theory/theory.h"
#include "theory/uf/equality_engine.h"
/** conflicts in setModelVal */
IntStat d_numSetModelValConflicts;
- // Merge reason types
-
- /** Merge tag for ROW applications */
- unsigned d_reasonRow;
- /** Merge tag for ROW1 applications */
- unsigned d_reasonRow1;
- /** Merge tag for EXT applications */
- unsigned d_reasonExt;
-
public:
TheoryArrays(context::Context* c,
context::UserContext* u,
/** Should be called to propagate the literal. */
bool propagateLit(TNode literal);
- /** Explain why this literal is true by adding assumptions */
- void explain(TNode literal, std::vector<TNode>& assumptions,
- eq::EqProof* proof);
+ /** Explain why this literal is true by building an explanation */
+ void explain(TNode literal, Node& exp);
/** For debugging only- checks invariants about when things are preregistered*/
context::CDHashSet<Node, NodeHashFunction > d_isPreRegistered;
public:
void preRegisterTerm(TNode n) override;
- Node explain(TNode n, eq::EqProof* proof);
TrustNode explain(TNode n) override;
/////////////////////////////////////////////////////////////////////////////
bool d_inCheckModel;
int d_topLevel;
- /** An equality-engine callback for proof reconstruction */
- std::unique_ptr<ArrayProofReconstruction> d_proofReconstruction;
-
/**
* The decision strategy for the theory of arrays, which calls the
* getNextDecisionEngineRequest function below.
prop::SatSolver* getSatSolver() override { return d_satSolver.get(); }
- void setProofLog(proof::BitVectorProof* bvp) override
- {
- // Proofs are currently not supported with ABC
- Unimplemented();
- }
-
class Statistics
{
public:
#include <vector>
#include "expr/node.h"
-#include "proof/bitvector_proof.h"
#include "prop/bv_sat_solver_notify.h"
+#include "prop/sat_solver.h"
#include "prop/sat_solver_types.h"
#include "smt/smt_engine_scope.h"
#include "theory/bv/bitblast/bitblast_strategies_template.h"
// sat solver used for bitblasting and associated CnfStream
std::unique_ptr<context::Context> d_nullContext;
std::unique_ptr<prop::CnfStream> d_cnfStream;
- proof::BitVectorProof* d_bvp;
void initAtomBBStrategies();
void initTermBBStrategies();
bool hasBBTerm(TNode node) const;
void getBBTerm(TNode node, Bits& bits) const;
virtual void storeBBTerm(TNode term, const Bits& bits);
- virtual void setProofLog(proof::BitVectorProof* bvp);
/**
* Return a constant representing the value of a in the model.
: d_termCache(),
d_modelCache(),
d_nullContext(new context::Context()),
- d_cnfStream(),
- d_bvp(nullptr)
+ d_cnfStream()
{
initAtomBBStrategies();
initTermBBStrategies();
d_modelCache.clear();
}
-template <class T>
-void TBitblaster<T>::setProofLog(proof::BitVectorProof* bvp)
-{
- if (THEORY_PROOF_ON())
- {
- d_bvp = bvp;
- prop::SatSolver* satSolver = getSatSolver();
- bvp->attachToSatSolver(*satSolver);
- prop::SatVariable t = satSolver->trueVar();
- prop::SatVariable f = satSolver->falseVar();
- bvp->initCnfProof(d_cnfStream.get(), d_nullContext.get(), t, f);
- }
-}
-
template <class T>
Node TBitblaster<T>::getTermModel(TNode node, bool fullModel)
{
d_bitblastingRegistrar.get(),
d_nullContext.get(),
rm,
- options::proof(),
+ false,
"EagerBitblaster"));
}
}
else
{
- d_cnfStream->convertAndAssert(
- node, false, false, RULE_INVALID, TNode::null());
+ d_cnfStream->convertAndAssert(node, false, false);
}
}
? d_atomBBStrategies[normalized.getKind()](normalized, this)
: normalized;
- if (!options::proof())
- {
- atom_bb = Rewriter::rewrite(atom_bb);
- }
+ atom_bb = Rewriter::rewrite(atom_bb);
// asserting that the atom is true iff the definition holds
Node atom_definition =
AlwaysAssert(options::bitblastMode() == options::BitblastMode::EAGER);
storeBBAtom(node, atom_bb);
- d_cnfStream->convertAndAssert(
- atom_definition, false, false, RULE_INVALID, TNode::null());
+ d_cnfStream->convertAndAssert(atom_definition, false, false);
}
void EagerBitblaster::storeBBAtom(TNode atom, Node atom_bb) {
- if (d_bvp) {
- d_bvp->registerAtomBB(atom.toExpr(), atom_bb.toExpr());
- }
d_bbAtoms.insert(atom);
}
void EagerBitblaster::storeBBTerm(TNode node, const Bits& bits) {
- if (d_bvp) {
- d_bvp->registerTermBB(node.toExpr());
- }
d_termCache.insert(std::make_pair(node, bits));
}
#include "theory/bv/bitblast/bitblaster.h"
-#include "proof/bitvector_proof.h"
-#include "proof/resolution_bitvector_proof.h"
#include "prop/cnf_stream.h"
#include "prop/sat_solver.h"
#include "theory/bv/bitblast/lazy_bitblaster.h"
#include "options/bv_options.h"
-#include "proof/proof_manager.h"
#include "prop/cnf_stream.h"
#include "prop/sat_solver.h"
#include "prop/sat_solver_factory.h"
d_nullRegistrar.get(),
d_nullContext.get(),
rm,
- options::proof(),
+ false,
"LazyBitblaster"));
d_satSolverNotify.reset(
Assert(!atom_bb.isNull());
Node atom_definition = nm->mkNode(kind::EQUAL, node, atom_bb);
storeBBAtom(node, atom_bb);
- d_cnfStream->convertAndAssert(
- atom_definition, false, false, RULE_INVALID, TNode::null());
+ d_cnfStream->convertAndAssert(atom_definition, false, false);
return;
}
? d_atomBBStrategies[normalized.getKind()](normalized, this)
: normalized;
- if (!options::proof())
- {
- atom_bb = Rewriter::rewrite(atom_bb);
- }
+ atom_bb = Rewriter::rewrite(atom_bb);
// asserting that the atom is true iff the definition holds
Node atom_definition = nm->mkNode(kind::EQUAL, node, atom_bb);
storeBBAtom(node, atom_bb);
- d_cnfStream->convertAndAssert(
- atom_definition, false, false, RULE_INVALID, TNode::null());
+ d_cnfStream->convertAndAssert(atom_definition, false, false);
}
void TLazyBitblaster::storeBBAtom(TNode atom, Node atom_bb) {
- // No need to store the definition for the lazy bit-blaster (unless proofs are enabled).
- if( d_bvp != NULL ){
- d_bvp->registerAtomBB(atom.toExpr(), atom_bb.toExpr());
- }
d_bbAtoms.insert(atom);
}
void TLazyBitblaster::storeBBTerm(TNode node, const Bits& bits) {
- if( d_bvp ){ d_bvp->registerTermBB(node.toExpr()); }
d_termCache.insert(std::make_pair(node, bits));
}
#ifndef CVC4__THEORY__BV__BITBLAST__LAZY_BITBLASTER_H
#define CVC4__THEORY__BV__BITBLAST__LAZY_BITBLASTER_H
-#include "proof/resolution_bitvector_proof.h"
#include "theory/bv/bitblast/bitblaster.h"
#include "context/cdhashmap.h"
d_bitblaster(),
d_aigBitblaster(),
d_useAig(options::bitvectorAig()),
- d_bv(bv),
- d_bvp(nullptr)
+ d_bv(bv)
{
}
#endif
} else {
d_bitblaster.reset(new EagerBitblaster(d_bv, d_context));
- THEORY_PROOF(if (d_bvp) {
- d_bitblaster->setProofLog(d_bvp);
- d_bvp->setBitblaster(d_bitblaster.get());
- });
}
}
return d_bitblaster->collectModelInfo(m, fullModel);
}
-void EagerBitblastSolver::setProofLog(proof::BitVectorProof* bvp)
-{
- d_bvp = bvp;
-}
-
} // namespace bv
} // namespace theory
} // namespace CVC4
#include <vector>
#include "expr/node.h"
-#include "proof/resolution_bitvector_proof.h"
#include "theory/bv/theory_bv.h"
#include "theory/theory_model.h"
bool isInitialized();
void initialize();
bool collectModelInfo(theory::TheoryModel* m, bool fullModel);
- void setProofLog(proof::BitVectorProof* bvp);
private:
context::CDHashSet<Node, NodeHashFunction> d_assertionSet;
bool d_useAig;
TheoryBV* d_bv;
- proof::BitVectorProof* d_bvp;
}; // class EagerBitblastSolver
} // namespace bv
namespace CVC4 {
-namespace proof {
-class BitVectorProof;
-}
-
namespace theory {
class TheoryModel;
SubtheorySolver(context::Context* c, TheoryBV* bv)
: d_context(c),
d_bv(bv),
- d_bvp(nullptr),
d_assertionQueue(c),
d_assertionIndex(c, 0) {}
virtual ~SubtheorySolver() {}
return res;
}
virtual void assertFact(TNode fact) { d_assertionQueue.push_back(fact); }
- virtual void setProofLog(proof::BitVectorProof* bvp) {}
+
AssertionQueue::const_iterator assertionsBegin() {
return d_assertionQueue.begin();
}
/** The bit-vector theory */
TheoryBV* d_bv;
- /** proof log */
- proof::ResolutionBitVectorProof* d_bvp;
AssertionQueue d_assertionQueue;
context::CDO<uint32_t> d_assertionIndex;
}; /* class SubtheorySolver */
#include "decision/decision_attributes.h"
#include "options/bv_options.h"
#include "options/decision_options.h"
-#include "proof/proof_manager.h"
#include "smt/smt_statistics_registry.h"
#include "theory/bv/abstraction.h"
#include "theory/bv/bitblast/lazy_bitblaster.h"
d_bv->setConflict(final_conflict);
}
-void BitblastSolver::setProofLog(proof::BitVectorProof* bvp)
-{
- d_bitblaster->setProofLog( bvp );
- bvp->setBitblaster(d_bitblaster.get());
-}
-
}/* namespace CVC4::theory::bv */
}/* namespace CVC4::theory */
}/* namespace CVC4 */
namespace CVC4 {
-namespace proof {
-class ResolutionBitVectorProof;
-}
-
namespace theory {
namespace bv {
void bitblastQueue();
void setAbstraction(AbstractionModule* module);
uint64_t computeAtomWeight(TNode atom);
- void setProofLog(proof::BitVectorProof* bvp) override;
};
} /* namespace CVC4::theory::bv */
#include "expr/node_algorithm.h"
#include "options/bv_options.h"
#include "options/smt_options.h"
-#include "proof/proof_manager.h"
-#include "proof/theory_proof.h"
#include "smt/smt_statistics_registry.h"
#include "theory/bv/abstraction.h"
#include "theory/bv/bv_eager_solver.h"
return;
}
- if (options::bitvectorEqualitySolver() && !options::proof())
+ if (options::bitvectorEqualitySolver())
{
d_subtheories.emplace_back(new CoreSolver(c, this, d_extTheory.get()));
d_subtheoryMap[SUB_CORE] = d_subtheories.back().get();
}
- if (options::bitvectorInequalitySolver() && !options::proof())
+ if (options::bitvectorInequalitySolver())
{
d_subtheories.emplace_back(new InequalitySolver(c, u, this));
d_subtheoryMap[SUB_INEQUALITY] = d_subtheories.back().get();
}
- if (options::bitvectorAlgebraicSolver() && !options::proof())
+ if (options::bitvectorAlgebraicSolver())
{
d_subtheories.emplace_back(new AlgebraicSolver(c, this));
d_subtheoryMap[SUB_ALGEBRAIC] = d_subtheories.back().get();
TNode num = node[0], den = node[1];
Node den_eq_0 = nm->mkNode(kind::EQUAL, den, utils::mkZero(width));
- Node divTotalNumDen = nm->mkNode(node.getKind() == kind::BITVECTOR_UDIV ? kind::BITVECTOR_UDIV_TOTAL :
- kind::BITVECTOR_UREM_TOTAL, num, den);
+ Node divTotalNumDen = nm->mkNode(node.getKind() == kind::BITVECTOR_UDIV
+ ? kind::BITVECTOR_UDIV_TOTAL
+ : kind::BITVECTOR_UREM_TOTAL,
+ num,
+ den);
Node divByZero = getBVDivByZero(node.getKind(), width);
Node divByZeroNum = nm->mkNode(kind::APPLY_UF, divByZero, num);
ret = nm->mkNode(kind::ITE, den_eq_0, divByZeroNum, divTotalNumDen);
if (done() && e<Theory::EFFORT_FULL) {
return;
}
-
+
//last call : do reductions on extended bitvector functions
if (e == Theory::EFFORT_LAST_CALL) {
std::vector<Node> nred = d_extTheory->getActive();
break;
}
}
-
+
//check extended functions
if (Theory::fullEffort(e)) {
//do inferences (adds external lemmas) TODO: this can be improved to add internal inferences
if( doExtfReductions( nred ) ){
return;
}
- }else{
+ }
+ else
+ {
d_needsLastCallCheck = true;
}
}
} else if (RewriteRule<UltPlusOne>::applies(t)) {
Node result = RewriteRule<UltPlusOne>::run<false>(t);
res = Rewriter::rewrite(result);
- } else if( res.getKind() == kind::EQUAL &&
- ((res[0].getKind() == kind::BITVECTOR_PLUS &&
- RewriteRule<ConcatToMult>::applies(res[1])) ||
- (res[1].getKind() == kind::BITVECTOR_PLUS &&
- RewriteRule<ConcatToMult>::applies(res[0])))) {
+ }
+ else if (res.getKind() == kind::EQUAL
+ && ((res[0].getKind() == kind::BITVECTOR_PLUS
+ && RewriteRule<ConcatToMult>::applies(res[1]))
+ || (res[1].getKind() == kind::BITVECTOR_PLUS
+ && RewriteRule<ConcatToMult>::applies(res[0]))))
+ {
Node mult = RewriteRule<ConcatToMult>::applies(res[0])?
RewriteRule<ConcatToMult>::run<false>(res[0]) :
RewriteRule<ConcatToMult>::run<true>(res[1]);
} else {
res = t;
}
- } else if (RewriteRule<SignExtendEqConst>::applies(t)) {
+ }
+ else if (RewriteRule<SignExtendEqConst>::applies(t))
+ {
res = RewriteRule<SignExtendEqConst>::run<false>(t);
- } else if (RewriteRule<ZeroExtendEqConst>::applies(t)) {
+ }
+ else if (RewriteRule<ZeroExtendEqConst>::applies(t))
+ {
res = RewriteRule<ZeroExtendEqConst>::run<false>(t);
}
else if (RewriteRule<NormalizeEqPlusNeg>::applies(t))
return changed;
}
-void TheoryBV::setProofLog(proof::BitVectorProof* bvp)
-{
- if (options::bitblastMode() == options::BitblastMode::EAGER)
- {
- d_eagerSolver->setProofLog(bvp);
- }
- else
- {
- for( unsigned i=0; i< d_subtheories.size(); i++ ){
- d_subtheories[i]->setProofLog( bvp );
- }
- }
-}
-
void TheoryBV::setConflict(Node conflict)
{
if (options::bvAbstraction())
#include "util/hash.h"
#include "util/statistics_registry.h"
-// Forward declarations, needed because the BV theory and the BV Proof classes
-// are cyclically dependent
namespace CVC4 {
-namespace proof {
-class BitVectorProof;
-}
namespace theory {
bool applyAbstraction(const std::vector<Node>& assertions,
std::vector<Node>& new_assertions);
- void setProofLog(proof::BitVectorProof* bvp);
-
private:
class Statistics
{
std::unique_ptr<EagerBitblastSolver> d_eagerSolver;
std::unique_ptr<AbstractionModule> d_abstractionModule;
bool d_calledPreregister;
-
+
//for extended functions
bool d_needsLastCallCheck;
context::CDHashSet<Node, NodeHashFunction> d_extf_range_infer;
* (ite ((_ extract 1 0) x) 1 0)
*/
bool doExtfReductions( std::vector< Node >& terms );
-
+
bool wasPropagatedBySubtheory(TNode literal) const {
return d_propagatedBy.find(literal) != d_propagatedBy.end();
}
void sendConflict();
- void lemma(TNode node) { d_out->lemma(node, RULE_CONFLICT); d_lemmasAdded = true; }
+ void lemma(TNode node)
+ {
+ d_out->lemma(node);
+ d_lemmasAdded = true;
+ }
void checkForLemma(TNode node);
void CombinationEngine::sendLemma(TrustNode trn, TheoryId atomsTo)
{
- d_te.lemma(trn.getNode(), RULE_INVALID, false, LemmaProperty::NONE, atomsTo);
+ d_te.lemma(trn.getNode(), false, LemmaProperty::NONE, atomsTo);
}
void CombinationEngine::resetRound()
#include "theory/engine_output_channel.h"
-#include "proof/cnf_proof.h"
-#include "proof/lemma_proof.h"
-#include "proof/proof_manager.h"
-#include "proof/theory_proof.h"
#include "prop/prop_engine.h"
#include "smt/smt_statistics_registry.h"
#include "theory/theory_engine.h"
}
}
-theory::LemmaStatus EngineOutputChannel::lemma(TNode lemma,
- ProofRule rule,
- LemmaProperty p)
+theory::LemmaStatus EngineOutputChannel::lemma(TNode lemma, LemmaProperty p)
{
Debug("theory::lemma") << "EngineOutputChannel<" << d_theory << ">::lemma("
<< lemma << ")"
++d_statistics.lemmas;
d_engine->d_outputChannelUsed = true;
- PROOF({
- bool preprocess = isLemmaPropertyPreprocess(p);
- registerLemmaRecipe(lemma, lemma, preprocess, d_theory);
- });
-
TrustNode tlem = TrustNode::mkTrustLemma(lemma);
theory::LemmaStatus result = d_engine->lemma(
tlem.getNode(),
- rule,
false,
p,
isLemmaPropertySendAtoms(p) ? d_theory : theory::THEORY_LAST);
return result;
}
-void EngineOutputChannel::registerLemmaRecipe(Node lemma,
- Node originalLemma,
- bool preprocess,
- theory::TheoryId theoryId)
-{
- // During CNF conversion, conjunctions will be broken down into
- // multiple lemmas. In order for the recipes to match, we have to do
- // the same here.
- NodeManager* nm = NodeManager::currentNM();
-
- if (preprocess) lemma = d_engine->preprocess(lemma);
-
- bool negated = (lemma.getKind() == NOT);
- Node nnLemma = negated ? lemma[0] : lemma;
-
- switch (nnLemma.getKind())
- {
- case AND:
- if (!negated)
- {
- for (unsigned i = 0; i < nnLemma.getNumChildren(); ++i)
- registerLemmaRecipe(nnLemma[i], originalLemma, false, theoryId);
- }
- else
- {
- NodeBuilder<> builder(OR);
- for (unsigned i = 0; i < nnLemma.getNumChildren(); ++i)
- builder << nnLemma[i].negate();
-
- Node disjunction =
- (builder.getNumChildren() == 1) ? builder[0] : builder;
- registerLemmaRecipe(disjunction, originalLemma, false, theoryId);
- }
- break;
-
- case EQUAL:
- if (nnLemma[0].getType().isBoolean())
- {
- if (!negated)
- {
- registerLemmaRecipe(nm->mkNode(OR, nnLemma[0], nnLemma[1].negate()),
- originalLemma,
- false,
- theoryId);
- registerLemmaRecipe(nm->mkNode(OR, nnLemma[0].negate(), nnLemma[1]),
- originalLemma,
- false,
- theoryId);
- }
- else
- {
- registerLemmaRecipe(nm->mkNode(OR, nnLemma[0], nnLemma[1]),
- originalLemma,
- false,
- theoryId);
- registerLemmaRecipe(
- nm->mkNode(OR, nnLemma[0].negate(), nnLemma[1].negate()),
- originalLemma,
- false,
- theoryId);
- }
- }
- break;
-
- case ITE:
- if (!negated)
- {
- registerLemmaRecipe(nm->mkNode(OR, nnLemma[0].negate(), nnLemma[1]),
- originalLemma,
- false,
- theoryId);
- registerLemmaRecipe(nm->mkNode(OR, nnLemma[0], nnLemma[2]),
- originalLemma,
- false,
- theoryId);
- }
- else
- {
- registerLemmaRecipe(
- nm->mkNode(OR, nnLemma[0].negate(), nnLemma[1].negate()),
- originalLemma,
- false,
- theoryId);
- registerLemmaRecipe(nm->mkNode(OR, nnLemma[0], nnLemma[2].negate()),
- originalLemma,
- false,
- theoryId);
- }
- break;
-
- default: break;
- }
-
- // Theory lemmas have one step that proves the empty clause
- LemmaProofRecipe proofRecipe;
- Node emptyNode;
- LemmaProofRecipe::ProofStep proofStep(theoryId, emptyNode);
-
- // Remember the original lemma, so we can report this later when asked to
- proofRecipe.setOriginalLemma(originalLemma);
-
- // Record the assertions and rewrites
- Node rewritten;
- if (lemma.getKind() == OR)
- {
- for (unsigned i = 0; i < lemma.getNumChildren(); ++i)
- {
- rewritten = theory::Rewriter::rewrite(lemma[i]);
- if (rewritten != lemma[i])
- {
- proofRecipe.addRewriteRule(lemma[i].negate(), rewritten.negate());
- }
- proofStep.addAssertion(lemma[i]);
- proofRecipe.addBaseAssertion(rewritten);
- }
- }
- else
- {
- rewritten = theory::Rewriter::rewrite(lemma);
- if (rewritten != lemma)
- {
- proofRecipe.addRewriteRule(lemma.negate(), rewritten.negate());
- }
- proofStep.addAssertion(lemma);
- proofRecipe.addBaseAssertion(rewritten);
- }
- proofRecipe.addStep(proofStep);
- ProofManager::getCnfProof()->setProofRecipe(&proofRecipe);
-}
-
theory::LemmaStatus EngineOutputChannel::splitLemma(TNode lemma, bool removable)
{
Debug("theory::lemma") << "EngineOutputChannel<" << d_theory << ">::lemma("
TrustNode tlem = TrustNode::mkTrustLemma(lemma);
LemmaProperty p = removable ? LemmaProperty::REMOVABLE : LemmaProperty::NONE;
theory::LemmaStatus result =
- d_engine->lemma(tlem.getNode(), RULE_SPLIT, false, p, d_theory);
+ d_engine->lemma(tlem.getNode(), false, p, d_theory);
return result;
}
return d_engine->propagate(literal, d_theory);
}
-void EngineOutputChannel::conflict(TNode conflictNode,
- std::unique_ptr<Proof> proof)
+void EngineOutputChannel::conflict(TNode conflictNode)
{
Trace("theory::conflict")
<< "EngineOutputChannel<" << d_theory << ">::conflict(" << conflictNode
<< ")" << std::endl;
- Assert(!proof); // Theory shouldn't be producing proofs yet
++d_statistics.conflicts;
d_engine->d_outputChannelUsed = true;
TrustNode tConf = TrustNode::mkTrustConflict(conflictNode);
Trace("theory::restart") << "EngineOutputChannel<" << d_theory
<< ">::restart(" << restartVar << ")" << std::endl;
++d_statistics.restartDemands;
- lemma(restartVar, RULE_INVALID, LemmaProperty::REMOVABLE);
+ lemma(restartVar, LemmaProperty::REMOVABLE);
}
void EngineOutputChannel::requirePhase(TNode n, bool phase)
// now, call the normal interface for lemma
return d_engine->lemma(
plem.getNode(),
- RULE_INVALID,
false,
p,
isLemmaPropertySendAtoms(p) ? d_theory : theory::THEORY_LAST);
void safePoint(ResourceManager::Resource r) override;
- void conflict(TNode conflictNode,
- std::unique_ptr<Proof> pf = nullptr) override;
+ void conflict(TNode conflictNode) override;
bool propagate(TNode literal) override;
theory::LemmaStatus lemma(TNode lemma,
- ProofRule rule,
LemmaProperty p = LemmaProperty::NONE) override;
theory::LemmaStatus splitLemma(TNode lemma, bool removable = false) override;
#include <map>
#include <set>
+#include "context/cdhashmap.h"
#include "context/cdhashset.h"
#include "context/context.h"
#include "expr/node.h"
unsigned LemmaStatus::getLevel() const { return d_level; }
-LemmaStatus OutputChannel::lemma(TNode n, LemmaProperty p)
-{
- return lemma(n, RULE_INVALID, p);
-}
-
LemmaStatus OutputChannel::split(TNode n)
{
return splitLemma(n.orNode(n.notNode()));
#include <memory>
#include "expr/proof_node.h"
-#include "proof/proof_manager.h"
#include "smt/logic_exception.h"
#include "theory/interrupted.h"
#include "theory/trust_node.h"
-#include "util/proof.h"
#include "util/resource_manager.h"
namespace CVC4 {
* assigned false), or else a literal by itself (in the case of a
* unit conflict) which is assigned TRUE (and T-conflicting) in the
* current assignment.
- * @param pf - a proof of the conflict. This is only non-null if proofs
- * are enabled.
*/
- virtual void conflict(TNode n, std::unique_ptr<Proof> pf = nullptr) = 0;
+ virtual void conflict(TNode n) = 0;
/**
* Propagate a theory literal.
* been detected. (This requests a split.)
*
* @param n - a theory lemma valid at decision level 0
- * @param rule - the proof rule for this lemma
* @param p The properties of the lemma
* @return the "status" of the lemma, including user level at which
* the lemma resides; the lemma will be removed when this user level pops
*/
- virtual LemmaStatus lemma(TNode n,
- ProofRule rule,
- LemmaProperty p = LemmaProperty::NONE) = 0;
-
- /**
- * Variant of the lemma function that does not require providing a proof rule.
- */
- virtual LemmaStatus lemma(TNode n, LemmaProperty p = LemmaProperty::NONE);
+ virtual LemmaStatus lemma(TNode n, LemmaProperty p = LemmaProperty::NONE) = 0;
/**
* Request a split on a new theory atom. This is equivalent to
** This class implements pre-process steps for admissible recursive function definitions (Reynolds et al IJCAR2016)
**/
+#include "theory/quantifiers/fun_def_process.h"
+
#include <vector>
-#include "theory/quantifiers/fun_def_process.h"
+#include "options/smt_options.h"
+#include "proof/proof_manager.h"
#include "theory/quantifiers/quantifiers_attributes.h"
#include "theory/quantifiers/term_database.h"
#include "theory/quantifiers/term_util.h"
-#include "proof/proof_manager.h"
using namespace CVC4;
using namespace std;
Trace("fmf-fun-def") << " to " << std::endl;
Node new_q = NodeManager::currentNM()->mkNode( FORALL, bvl, bd );
new_q = Rewriter::rewrite( new_q );
- PROOF( ProofManager::currentPM()->addDependence(new_q, assertions[i]); );
+ if (options::unsatCores())
+ {
+ ProofManager::currentPM()->addDependence(new_q, assertions[i]);
+ }
assertions[i] = new_q;
Trace("fmf-fun-def") << " " << assertions[i] << std::endl;
fd_assertions.push_back( i );
<< std::endl;
Trace("fmf-fun-def-rewrite") << " to " << std::endl;
Trace("fmf-fun-def-rewrite") << " " << n << std::endl;
- PROOF(ProofManager::currentPM()->addDependence(n, assertions[i]););
+ if (options::unsatCores())
+ {
+ ProofManager::currentPM()->addDependence(n, assertions[i]);
+ }
assertions[i] = n;
}
}
c = simplifyFormula( n[i], newPol, newHasPol, cconstraints, hd, false, visited, visited_cons );
if( branch_pos ){
// if at a branching position, the other constraints don't matter if this is satisfied
- Node bcons = cconstraints.empty() ? NodeManager::currentNM()->mkConst( true ) :
- ( cconstraints.size()==1 ? cconstraints[0] : NodeManager::currentNM()->mkNode( AND, cconstraints ) );
+ Node bcons = cconstraints.empty()
+ ? NodeManager::currentNM()->mkConst(true)
+ : (cconstraints.size() == 1
+ ? cconstraints[0]
+ : NodeManager::currentNM()->mkNode(
+ AND, cconstraints));
branch_constraints.push_back( bcons );
Trace("fmf-fun-def-debug2") << "Branching constraint at arg " << i << " is " << bcons << std::endl;
}
// in the default case, we care about all conditions
branch_cond = constraints.size()==1 ? constraints[0] : NodeManager::currentNM()->mkNode( AND, constraints );
for( unsigned i=0; i<n.getNumChildren(); i++ ){
- // if this child holds with forcing polarity (true child of OR or false child of AND),
- // then we only care about its associated recursive conditions
- branch_cond = NodeManager::currentNM()->mkNode( kind::ITE,
- ( n.getKind()==OR ? n[i] : n[i].negate() ), branch_constraints[i], branch_cond );
+ // if this child holds with forcing polarity (true child of OR or
+ // false child of AND), then we only care about its associated
+ // recursive conditions
+ branch_cond = NodeManager::currentNM()->mkNode(
+ kind::ITE,
+ (n.getKind() == OR ? n[i] : n[i].negate()),
+ branch_constraints[i],
+ branch_cond);
}
}
Trace("fmf-fun-def-debug2") << "Made branching condition " << branch_cond << std::endl;
#include "expr/node_algorithm.h"
#include "options/quantifiers_options.h"
+#include "options/smt_options.h"
+#include "proof/proof_manager.h"
#include "smt/smt_statistics_registry.h"
#include "theory/quantifiers/cegqi/inst_strategy_cegqi.h"
#include "theory/quantifiers/first_order_model.h"
bool Instantiate::getUnsatCoreLemmas(std::vector<Node>& active_lemmas)
{
// only if unsat core available
- if (options::proof())
+ if (options::unsatCores())
{
if (!ProofManager::currentPM()->unsatCoreAvailable())
{
return false;
}
}
+ else
+ {
+ return false;
+ }
Trace("inst-unsat-core") << "Get instantiations in unsat core..."
<< std::endl;
- ProofManager::currentPM()->getLemmasInUnsatCore(theory::THEORY_QUANTIFIERS,
- active_lemmas);
+ ProofManager::currentPM()->getLemmasInUnsatCore(active_lemmas);
if (Trace.isOn("inst-unsat-core"))
{
Trace("inst-unsat-core") << "Quantifiers lemmas in unsat core: "
return true;
}
-bool Instantiate::getUnsatCoreLemmas(std::vector<Node>& active_lemmas,
- std::map<Node, Node>& weak_imp)
-{
- if (getUnsatCoreLemmas(active_lemmas))
- {
- for (unsigned i = 0, size = active_lemmas.size(); i < size; ++i)
- {
- Node n = ProofManager::currentPM()->getWeakestImplicantInUnsatCore(
- active_lemmas[i]);
- if (n != active_lemmas[i])
- {
- Trace("inst-unsat-core") << " weaken : " << active_lemmas[i] << " -> "
- << n << std::endl;
- }
- weak_imp[active_lemmas[i]] = n;
- }
- return true;
- }
- return false;
-}
-
void Instantiate::getInstantiationTermVectors(
Node q, std::vector<std::vector<Node> >& tvecs)
{
* This method returns false if the unsat core is not available.
*/
bool getUnsatCoreLemmas(std::vector<Node>& active_lemmas);
- /** get unsat core lemmas
- *
- * If this method returns true, then it appends to active_lemmas all lemmas
- * that are in the unsat core that originated from the theory of quantifiers.
- * This method returns false if the unsat core is not available.
- *
- * It also computes a weak implicant for each of these lemmas. For each lemma
- * L in active_lemmas, this is a formula L' such that:
- * L => L'
- * and replacing L by L' in the unsat core results in a set that is still
- * unsatisfiable. The map weak_imp stores this formula for each formula in
- * active_lemmas.
- */
- bool getUnsatCoreLemmas(std::vector<Node>& active_lemmas,
- std::map<Node, Node>& weak_imp);
/** get explanation for instantiation lemmas
*
*
if (options::sygus() || options::sygusInst())
{
d_sygus_tdb.reset(new quantifiers::TermDbSygus(c, this));
- }
+ }
d_util.push_back(d_instantiate.get());
if( d_hasAddedLemma ){
return;
}
-
+
double clSet = 0;
if( Trace.isOn("quant-engine") ){
clSet = double(clock())/double(CLOCKS_PER_SEC);
Trace("quant-engine") << ", added lemma = " << d_hasAddedLemma;
Trace("quant-engine") << std::endl;
}
-
+
Trace("quant-engine-debug2") << "Finished quantifiers engine check." << std::endl;
}else{
Trace("quant-engine-debug2") << "Quantifiers Engine does not need check." << std::endl;
void QuantifiersEngine::addRequirePhase( Node lit, bool req ){
d_phase_req_waiting[lit] = req;
}
-
+
void QuantifiersEngine::markRelevant( Node q ) {
d_model->markRelevant( q );
}
return d_te->needCheck();
}
-void QuantifiersEngine::setConflict() {
- d_conflict = true;
- d_conflict_c = true;
+void QuantifiersEngine::setConflict()
+{
+ d_conflict = true;
+ d_conflict_c = true;
}
bool QuantifiersEngine::getInstWhenNeedsCheck( Theory::Effort e ) {
return d_instantiate->getUnsatCoreLemmas(active_lemmas);
}
-bool QuantifiersEngine::getUnsatCoreLemmas( std::vector< Node >& active_lemmas, std::map< Node, Node >& weak_imp ) {
- return d_instantiate->getUnsatCoreLemmas(active_lemmas, weak_imp);
-}
-
void QuantifiersEngine::getInstantiationTermVectors( Node q, std::vector< std::vector< Node > >& tvecs ) {
d_instantiate->getInstantiationTermVectors(q, tvecs);
}
Node getInstantiatedConjunction(Node q);
/** get unsat core lemmas */
bool getUnsatCoreLemmas(std::vector<Node>& active_lemmas);
- bool getUnsatCoreLemmas(std::vector<Node>& active_lemmas,
- std::map<Node, Node>& weak_imp);
/** get explanation for instantiation lemmas */
void getExplanationForInstLemmas(const std::vector<Node>& lems,
std::map<Node, Node>& quant,
~Statistics();
};/* class QuantifiersEngine::Statistics */
Statistics d_statistics;
-
+
private:
/** reference to theory engine object */
TheoryEngine* d_te;
#include "options/quantifiers_options.h"
#include "options/smt_options.h"
#include "options/uf_options.h"
-#include "proof/proof_manager.h"
#include "theory/rewriter.h"
#include "theory/quantifiers/quant_util.h"
#include <stdint.h>
#include "expr/kind.h"
+#include "options/smt_options.h"
#include "options/strings_options.h"
#include "proof/proof_manager.h"
#include "smt/logic_exception.h"
: NodeManager::currentNM()->mkNode(kind::AND, asserts);
if( res!=vec_node[i] ){
res = Rewriter::rewrite( res );
- PROOF( ProofManager::currentPM()->addDependence( res, vec_node[i] ); );
+ if (options::unsatCores())
+ {
+ ProofManager::currentPM()->addDependence(res, vec_node[i]);
+ }
vec_node[i] = res;
}
}
#include "base/check.h"
#include "expr/node_algorithm.h"
+#include "options/smt_options.h"
#include "options/theory_options.h"
#include "smt/smt_statistics_registry.h"
#include "theory/ext_theory.h"
d_equalityEngine(nullptr),
d_allocEqualityEngine(nullptr),
d_theoryState(nullptr),
- d_inferManager(nullptr),
- d_proofsEnabled(false)
+ d_inferManager(nullptr)
{
smtStatisticsRegistry()->registerStat(&d_checkTime);
smtStatisticsRegistry()->registerStat(&d_computeCareGraphTime);
switch (d_valuation.getEqualityStatus(a, b)) {
case EQUALITY_TRUE_AND_PROPAGATED:
case EQUALITY_FALSE_AND_PROPAGATED:
- // If we know about it, we should have propagated it, so we can skip
- break;
+ // If we know about it, we should have propagated it, so we can skip
+ break;
default:
- // Let's split on it
- addCarePair(a, b);
- break;
+ // Let's split on it
+ addCarePair(a, b);
+ break;
}
}
}
* the equality engine are used properly.
*/
TheoryInferenceManager* d_inferManager;
- /**
- * Whether proofs are enabled
- *
- */
- bool d_proofsEnabled;
/**
* Returns the next assertion in the assertFact() queue.
Unimplemented() << "Theory " << identify()
<< " propagated a node but doesn't implement the "
"Theory::explain() interface!";
+ return TrustNode::null();
}
//--------------------------------- check
*
* @return true iff facts have been asserted to this theory.
*/
- bool hasFacts() {
- return !d_facts.empty();
- }
+ bool hasFacts() { return !d_facts.empty(); }
/** Return total number of facts asserted to this theory */
size_t numAssertions() {
return d_facts.size();
}
-
+
typedef context::CDList<TNode>::const_iterator shared_terms_iterator;
/**
/* is extended function reduced */
virtual bool isExtfReduced( int effort, Node n, Node on, std::vector< Node >& exp ) { return n.isConst(); }
-
+
/**
* Get reduction for node
* If return value is not 0, then n is reduced.
* and return value should be <0.
*/
virtual int getReduction( int effort, Node n, Node& nr ) { return 0; }
-
- /** Turn on proof-production mode. */
- void produceProofs() { d_proofsEnabled = true; }
};/* class Theory */
std::ostream& operator<<(std::ostream& os, theory::Theory::Effort level);
#include "expr/node_visitor.h"
#include "options/bv_options.h"
#include "options/options.h"
-#include "options/proof_options.h"
#include "options/quantifiers_options.h"
#include "options/theory_options.h"
#include "preprocessing/assertion_pipeline.h"
-#include "proof/cnf_proof.h"
-#include "proof/lemma_proof.h"
-#include "proof/proof_manager.h"
-#include "proof/theory_proof.h"
#include "smt/logic_exception.h"
#include "smt/term_formula_removal.h"
#include "theory/arith/arith_ite_utils.h"
d_true = NodeManager::currentNM()->mkConst<bool>(true);
d_false = NodeManager::currentNM()->mkConst<bool>(false);
-#ifdef CVC4_PROOF
- ProofManager::currentPM()->initTheoryProofEngine();
-#endif
-
smtStatisticsRegistry()->registerStat(&d_arithSubstitutionsAdded);
}
assertToTheory(literal, literal, /* to */ THEORY_BUILTIN, /* from */ theory);
}
} else {
- // We could be propagating a unit-clause lemma. In this case, we need to provide a
- // recipe.
- // TODO: Consider putting this someplace else? This is the only refence to the proof
- // manager in this class.
-
- PROOF({
- LemmaProofRecipe proofRecipe;
- proofRecipe.addBaseAssertion(literal);
-
- Node emptyNode;
- LemmaProofRecipe::ProofStep proofStep(theory, emptyNode);
- proofStep.addAssertion(literal);
- proofRecipe.addStep(proofStep);
-
- ProofManager::getCnfProof()->setProofRecipe(&proofRecipe);
- });
-
// Just send off to the SAT solver
Assert(d_propEngine->isSatLiteral(literal));
assertToTheory(literal, literal, /* to */ THEORY_SAT_SOLVER, /* from */ theory);
return conjunction;
}
-Node TheoryEngine::getExplanationAndRecipe(TNode node, LemmaProofRecipe* proofRecipe) {
- Debug("theory::explain") << "TheoryEngine::getExplanation(" << node << "): current propagation index = " << d_propagationMapTimestamp << endl;
+Node TheoryEngine::getExplanation(TNode node)
+{
+ Debug("theory::explain") << "TheoryEngine::getExplanation(" << node
+ << "): current propagation index = "
+ << d_propagationMapTimestamp << endl;
bool polarity = node.getKind() != kind::NOT;
TNode atom = polarity ? node : node[0];
// If we're not in shared mode, explanations are simple
- if (!d_logicInfo.isSharingEnabled()) {
- Debug("theory::explain") << "TheoryEngine::getExplanation: sharing is NOT enabled. "
- << " Responsible theory is: "
- << theoryOf(atom)->getId() << std::endl;
+ if (!d_logicInfo.isSharingEnabled())
+ {
+ Debug("theory::explain")
+ << "TheoryEngine::getExplanation: sharing is NOT enabled. "
+ << " Responsible theory is: " << theoryOf(atom)->getId() << std::endl;
TrustNode texplanation = theoryOf(atom)->explain(node);
Node explanation = texplanation.getNode();
- Debug("theory::explain") << "TheoryEngine::getExplanation(" << node << ") => " << explanation << endl;
- PROOF({
- if(proofRecipe) {
- Node emptyNode;
- LemmaProofRecipe::ProofStep proofStep(theoryOf(atom)->getId(), emptyNode);
- proofStep.addAssertion(node);
- proofRecipe->addBaseAssertion(node);
-
- if (explanation.getKind() == kind::AND) {
- // If the explanation is a conjunction, the recipe for the corresponding lemma is
- // the negation of its conjuncts.
- Node flat = flattenAnd(explanation);
- for (unsigned i = 0; i < flat.getNumChildren(); ++i) {
- if (flat[i].isConst() && flat[i].getConst<bool>()) {
- ++ i;
- continue;
- }
- if (flat[i].getKind() == kind::NOT &&
- flat[i][0].isConst() && !flat[i][0].getConst<bool>()) {
- ++ i;
- continue;
- }
- Debug("theory::explain") << "TheoryEngine::getExplanationAndRecipe: adding recipe assertion: "
- << flat[i].negate() << std::endl;
- proofStep.addAssertion(flat[i].negate());
- proofRecipe->addBaseAssertion(flat[i].negate());
- }
- } else {
- // The recipe for proving it is by negating it. "True" is not an acceptable reason.
- if (!((explanation.isConst() && explanation.getConst<bool>()) ||
- (explanation.getKind() == kind::NOT &&
- explanation[0].isConst() && !explanation[0].getConst<bool>()))) {
- proofStep.addAssertion(explanation.negate());
- proofRecipe->addBaseAssertion(explanation.negate());
- }
- }
-
- proofRecipe->addStep(proofStep);
- }
- });
-
+ Debug("theory::explain") << "TheoryEngine::getExplanation(" << node
+ << ") => " << explanation << endl;
return explanation;
}
- Debug("theory::explain") << "TheoryEngine::getExplanation: sharing IS enabled" << std::endl;
+ Debug("theory::explain") << "TheoryEngine::getExplanation: sharing IS enabled"
+ << std::endl;
// Initial thing to explain
NodeTheoryPair toExplain(node, THEORY_SAT_SOLVER, d_propagationMapTimestamp);
<< "TheoryEngine::getExplanation: explainer for node "
<< nodeExplainerPair.d_node
<< " is theory: " << nodeExplainerPair.d_theory << std::endl;
- TheoryId explainer = nodeExplainerPair.d_theory;
// Create the workplace for explanations
std::vector<NodeTheoryPair> explanationVector;
explanationVector.push_back(d_propagationMap[toExplain]);
// Process the explanation
- if (proofRecipe) {
- Node emptyNode;
- LemmaProofRecipe::ProofStep proofStep(explainer, emptyNode);
- proofStep.addAssertion(node);
- proofRecipe->addStep(proofStep);
- proofRecipe->addBaseAssertion(node);
- }
-
- getExplanation(explanationVector, proofRecipe);
+ getExplanation(explanationVector);
Node explanation = mkExplanation(explanationVector);
- Debug("theory::explain") << "TheoryEngine::getExplanation(" << node << ") => " << explanation << endl;
+ Debug("theory::explain") << "TheoryEngine::getExplanation(" << node << ") => "
+ << explanation << endl;
return explanation;
}
-Node TheoryEngine::getExplanation(TNode node) {
- LemmaProofRecipe *dontCareRecipe = NULL;
- return getExplanationAndRecipe(node, dontCareRecipe);
-}
-
struct AtomsCollect {
std::vector<TNode> d_atoms;
}
theory::LemmaStatus TheoryEngine::lemma(TNode node,
- ProofRule rule,
bool negated,
theory::LemmaProperty p,
theory::TheoryId atomsTo)
// assert lemmas to prop engine
for (size_t i = 0, lsize = lemmas.size(); i < lsize; ++i)
{
- d_propEngine->assertLemma(
- lemmas[i], i == 0 && negated, removable, rule, node);
+ d_propEngine->assertLemma(lemmas[i], i == 0 && negated, removable);
}
// WARNING: Below this point don't assume lemmas[0] to be not negated.
<< CheckSatCommand(conflict.toExpr());
}
- LemmaProofRecipe* proofRecipe = NULL;
- PROOF({
- proofRecipe = new LemmaProofRecipe;
- Node emptyNode;
- LemmaProofRecipe::ProofStep proofStep(theoryId, emptyNode);
-
- if (conflict.getKind() == kind::AND) {
- for (unsigned i = 0; i < conflict.getNumChildren(); ++i) {
- proofStep.addAssertion(conflict[i].negate());
- }
- } else {
- proofStep.addAssertion(conflict.negate());
- }
-
- proofRecipe->addStep(proofStep);
- });
-
// In the multiple-theories case, we need to reconstruct the conflict
if (d_logicInfo.isSharingEnabled()) {
// Create the workplace for explanations
explanationVector.push_back(NodeTheoryPair(conflict, theoryId, d_propagationMapTimestamp));
// Process the explanation
- getExplanation(explanationVector, proofRecipe);
- PROOF(ProofManager::getCnfProof()->setProofRecipe(proofRecipe));
+ getExplanation(explanationVector);
Node fullConflict = mkExplanation(explanationVector);
Debug("theory::conflict") << "TheoryEngine::conflict(" << conflict << ", " << theoryId << "): full = " << fullConflict << endl;
Assert(properConflict(fullConflict));
lemma(fullConflict,
- RULE_CONFLICT,
true,
LemmaProperty::REMOVABLE,
THEORY_LAST);
} else {
// When only one theory, the conflict should need no processing
Assert(properConflict(conflict));
- PROOF({
- if (conflict.getKind() == kind::AND) {
- // If the conflict is a conjunction, the corresponding lemma is derived by negating
- // its conjuncts.
- for (unsigned i = 0; i < conflict.getNumChildren(); ++i) {
- if (conflict[i].isConst() && conflict[i].getConst<bool>()) {
- ++ i;
- continue;
- }
- if (conflict[i].getKind() == kind::NOT &&
- conflict[i][0].isConst() && !conflict[i][0].getConst<bool>()) {
- ++ i;
- continue;
- }
- proofRecipe->getStep(0)->addAssertion(conflict[i].negate());
- proofRecipe->addBaseAssertion(conflict[i].negate());
- }
- } else {
- proofRecipe->getStep(0)->addAssertion(conflict.negate());
- proofRecipe->addBaseAssertion(conflict.negate());
- }
-
- ProofManager::getCnfProof()->setProofRecipe(proofRecipe);
- });
-
- lemma(conflict, RULE_CONFLICT, true, LemmaProperty::REMOVABLE, THEORY_LAST);
+ lemma(conflict, true, LemmaProperty::REMOVABLE, THEORY_LAST);
}
-
- PROOF({
- delete proofRecipe;
- proofRecipe = NULL;
- });
}
-void TheoryEngine::getExplanation(std::vector<NodeTheoryPair>& explanationVector, LemmaProofRecipe* proofRecipe) {
+void TheoryEngine::getExplanation(
+ std::vector<NodeTheoryPair>& explanationVector)
+{
Assert(explanationVector.size() > 0);
unsigned i = 0; // Index of the current literal we are processing
unsigned j = 0; // Index of the last literal we are keeping
- std::unique_ptr<std::set<Node>> inputAssertions = nullptr;
- PROOF({
- if (proofRecipe)
- {
- inputAssertions.reset(
- new std::set<Node>(proofRecipe->getStep(0)->getAssertions()));
- }
- });
// cache of nodes we have already explained by some theory
std::unordered_map<Node, size_t, NodeHashFunction> cache;
explanationVector.push_back((*find).second);
++i;
- PROOF({
- if (toExplain.d_node != (*find).second.d_node)
- {
- Debug("pf::explain")
- << "TheoryEngine::getExplanation: Rewrite alert! toAssert = "
- << toExplain.d_node << ", toExplain = " << (*find).second.d_node
- << std::endl;
-
- if (proofRecipe)
- {
- proofRecipe->addRewriteRule(toExplain.d_node,
- (*find).second.d_node);
- }
- }
- })
-
continue;
}
}
explanationVector.push_back(newExplain);
++ i;
-
- PROOF({
- if (proofRecipe && inputAssertions)
- {
- // If we're expanding the target node of the explanation (this is the
- // first expansion...), we don't want to add it as a separate proof
- // step. It is already part of the assertions.
- if (!ContainsKey(*inputAssertions, toExplain.d_node))
- {
- LemmaProofRecipe::ProofStep proofStep(toExplain.d_theory,
- toExplain.d_node);
- if (explanation.getKind() == kind::AND)
- {
- Node flat = flattenAnd(explanation);
- for (unsigned k = 0; k < flat.getNumChildren(); ++k)
- {
- // If a true constant or a negation of a false constant we can
- // ignore it
- if (!((flat[k].isConst() && flat[k].getConst<bool>())
- || (flat[k].getKind() == kind::NOT && flat[k][0].isConst()
- && !flat[k][0].getConst<bool>())))
- {
- proofStep.addAssertion(flat[k].negate());
- }
- }
- }
- else
- {
- if (!((explanation.isConst() && explanation.getConst<bool>())
- || (explanation.getKind() == kind::NOT
- && explanation[0].isConst()
- && !explanation[0].getConst<bool>())))
- {
- proofStep.addAssertion(explanation.negate());
- }
- }
- proofRecipe->addStep(proofStep);
- }
- }
- });
}
// Keep only the relevant literals
explanationVector.resize(j);
-
- PROOF({
- if (proofRecipe) {
- // The remaining literals are the base of the proof
- for (unsigned k = 0; k < explanationVector.size(); ++k) {
- proofRecipe->addBaseAssertion(explanationVector[k].d_node.negate());
- }
- }
- });
}
void TheoryEngine::setUserAttribute(const std::string& attr,
namespace CVC4 {
class ResourceManager;
-class LemmaProofRecipe;
/**
* A pair of a theory and a node. This is used to mark the flow of
* @param p the properties of the lemma.
*/
theory::LemmaStatus lemma(TNode node,
- ProofRule rule,
bool negated,
theory::LemmaProperty p,
theory::TheoryId atomsTo);
bool markPropagation(TNode assertion, TNode originalAssertions, theory::TheoryId toTheoryId, theory::TheoryId fromTheoryId);
/**
- * Computes the explanation by travarsing the propagation graph and
+ * Computes the explanation by traversing the propagation graph and
* asking relevant theories to explain the propagations. Initially
* the explanation vector should contain only the element (node, theory)
* where the node is the one to be explained, and the theory is the
- * theory that sent the literal. The lemmaProofRecipe will contain a list
- * of the explanation steps required to produce the original node.
+ * theory that sent the literal.
*/
- void getExplanation(std::vector<NodeTheoryPair>& explanationVector, LemmaProofRecipe* lemmaProofRecipe);
+ void getExplanation(std::vector<NodeTheoryPair>& explanationVector);
public:
/**
*/
Node getExplanation(TNode node);
- /**
- * Returns an explanation of the node propagated to the SAT solver and the theory
- * that propagated it.
- */
- Node getExplanationAndRecipe(TNode node, LemmaProofRecipe* proofRecipe);
-
/**
* Get the pointer to the model object used by this theory engine.
*/
/**
* Get instantiation methods
* first inputs forall x.q[x] and returns ( q[a], ..., q[z] )
- * second inputs forall x.q[x] and returns ( a, ..., z )
- * third and fourth return mappings e.g. forall x.q1[x] -> ( q1[a]...q1[z] ) , ... , forall x.qn[x] -> ( qn[a]...qn[z] )
+ * second inputs forall x.q[x] and returns ( a, ..., z )
+ * third and fourth return mappings e.g. forall x.q1[x] -> ( q1[a]...q1[z] )
+ * , ... , forall x.qn[x] -> ( qn[a]...qn[z] )
*/
void getInstantiations( Node q, std::vector< Node >& insts );
void getInstantiationTermVectors( Node q, std::vector< std::vector< Node > >& tvecs );
void getInstantiations( std::map< Node, std::vector< Node > >& insts );
void getInstantiationTermVectors( std::map< Node, std::vector< std::vector< Node > > >& insts );
-
+
/**
* Get instantiated conjunction, returns q[t1] ^ ... ^ q[tn] where t1...tn are current set of instantiations for q.
* Can be used for quantifier elimination when satisfiable and q[t1] ^ ... ^ q[tn] |= q
public:
/** Set user attribute.
- *
+ *
* This function is called when an attribute is set by a user. In SMT-LIBv2
* this is done via the syntax (! n :attr)
*/
const std::string& str_value);
/** Handle user attribute.
- *
+ *
* Associates theory t with the attribute attr. Theory t will be
* notified whenever an attribute of name attr is set.
*/
#include "expr/node.h"
#include "theory/interrupted.h"
#include "theory/output_channel.h"
-#include "util/proof.h"
#include "util/resource_manager.h"
#include "util/unsafe_interrupt_exception.h"
~TestOutputChannel() override {}
void safePoint(ResourceManager::Resource r) override {}
- void conflict(TNode n, std::unique_ptr<Proof> pf) override
- {
- push(CONFLICT, n);
- }
+ void conflict(TNode n) override { push(CONFLICT, n); }
bool propagate(TNode n) override {
push(PROPAGATE, n);
return true;
}
- LemmaStatus lemma(TNode n, ProofRule rule, LemmaProperty p) override
+ LemmaStatus lemma(TNode n, LemmaProperty p) override
{
push(LEMMA, n);
return LemmaStatus(Node::null(), 0);
namespace theory {
namespace eq {
-void EqProof::debug_print(const char* c,
- unsigned tb,
- PrettyPrinter* prettyPrinter) const
+void EqProof::debug_print(const char* c, unsigned tb) const
{
std::stringstream ss;
- debug_print(ss, tb, prettyPrinter);
+ debug_print(ss, tb);
Debug(c) << ss.str();
}
-void EqProof::debug_print(std::ostream& os,
- unsigned tb,
- PrettyPrinter* prettyPrinter) const
+void EqProof::debug_print(std::ostream& os, unsigned tb) const
{
for (unsigned i = 0; i < tb; i++)
{
os << " ";
}
-
- if (prettyPrinter)
- {
- os << prettyPrinter->printTag(d_id);
- }
- else
- {
- os << static_cast<MergeReasonType>(d_id);
- }
- os << "(";
+ os << d_id << "(";
if (d_children.empty() && d_node.isNull())
{
os << ")";
for (unsigned i = 0; i < size; ++i)
{
os << std::endl;
- d_children[i]->debug_print(os, tb + 1, prettyPrinter);
+ d_children[i]->debug_print(os, tb + 1);
if (i < size - 1)
{
for (unsigned j = 0; j < tb + 1; ++j)
<< ", returning " << it->second << "\n";
return it->second;
}
- Trace("eqproof-conv") << "EqProof::addToProof: adding step for "
- << static_cast<MergeReasonType>(d_id)
+ Trace("eqproof-conv") << "EqProof::addToProof: adding step for " << d_id
<< " with conclusion " << d_node << "\n";
// Assumption
if (d_id == MERGED_THROUGH_EQUALITY)
{
Assert(!d_node.isNull() && d_node.getKind() == kind::EQUAL
&& d_node[1].isConst())
- << ". Conclusion " << d_node << " from "
- << static_cast<MergeReasonType>(d_id)
+ << ". Conclusion " << d_node << " from " << d_id
<< " was expected to be (= (f t1 ... tn) c)\n";
Assert(!assumptions.count(d_node))
- << "Conclusion " << d_node << " from "
- << static_cast<MergeReasonType>(d_id) << " is an assumption\n";
+ << "Conclusion " << d_node << " from " << d_id << " is an assumption\n";
// The step has the form
// [(= t1 c1)] ... [(= tn cn)]
// ------------------------
class EqProof
{
public:
- /** A custom pretty printer used for custom rules being those in
- * MergeReasonType. */
- class PrettyPrinter
- {
- public:
- virtual ~PrettyPrinter() {}
- virtual std::string printTag(unsigned tag) = 0;
- };
-
EqProof() : d_id(MERGED_THROUGH_REFLEXIVITY) {}
/** The proof rule for concluding d_node */
- unsigned d_id;
+ MergeReasonType d_id;
/** The conclusion of this EqProof */
Node d_node;
/** The proofs of the premises for deriving d_node with d_id */
std::vector<std::shared_ptr<EqProof>> d_children;
/**
- * Debug print this proof on debug trace c with tabulation tb and pretty
- * printer prettyPrinter.
+ * Debug print this proof on debug trace c with tabulation tb.
*/
- void debug_print(const char* c,
- unsigned tb = 0,
- PrettyPrinter* prettyPrinter = nullptr) const;
+ void debug_print(const char* c, unsigned tb = 0) const;
/**
- * Debug print this proof on output stream os with tabulation tb and pretty
- * printer prettyPrinter.
+ * Debug print this proof on output stream os with tabulation tb.
*/
- void debug_print(std::ostream& os,
- unsigned tb = 0,
- PrettyPrinter* prettyPrinter = nullptr) const;
+ void debug_print(std::ostream& os, unsigned tb = 0) const;
/** Add to proof
*
d_trueId = getNodeId(d_true);
d_falseId = getNodeId(d_false);
-
- d_freshMergeReasonType = eq::NUMBER_OF_MERGE_REASONS;
}
EqualityEngine::~EqualityEngine() {
getExplanation(t1Id, t2Id, equalities, cache, eqp);
} else {
if (eqp) {
- eqp->d_id = eq::MERGED_THROUGH_TRANS;
+ eqp->d_id = MERGED_THROUGH_TRANS;
eqp->d_node = d_nodes[t1Id].eqNode(d_nodes[t2Id]).notNode();
}
Debug("pf::ee") << "Child proof is:" << std::endl;
eqpc->debug_print("pf::ee", 1);
}
- if (eqpc->d_id == eq::MERGED_THROUGH_TRANS) {
+ if (eqpc->d_id == MERGED_THROUGH_TRANS)
+ {
std::vector<std::shared_ptr<EqProof>> orderedChildren;
bool nullCongruenceFound = false;
for (const auto& child : eqpc->d_children)
{
- if (child->d_id == eq::MERGED_THROUGH_CONGRUENCE
+ if (child->d_id == MERGED_THROUGH_CONGRUENCE
&& child->d_node.isNull())
{
nullCongruenceFound = true;
#endif
// If the nodes are the same, we're done
- if (t1Id == t2Id){
- if( eqp ) {
- if (options::proofNew())
- {
- // ignore equalities between function symbols, i.e. internal nullary
- // non-constant nodes.
- //
- // Note that this is robust for HOL because in that case function
- // symbols are not internal nodes
- if (d_isInternal[t1Id] && d_nodes[t1Id].getNumChildren() == 0
- && !d_isConstant[t1Id])
- {
- eqp->d_node = Node::null();
- }
- else
- {
- Assert(d_nodes[t1Id].getKind() != kind::BUILTIN);
- eqp->d_node = d_nodes[t1Id].eqNode(d_nodes[t1Id]);
- }
- }
- else if ((d_nodes[t1Id].getKind() == kind::BUILTIN)
- && (d_nodes[t1Id].getConst<Kind>() == kind::SELECT))
+ if (t1Id == t2Id)
+ {
+ if (eqp)
+ {
+ // ignore equalities between function symbols, i.e. internal nullary
+ // non-constant nodes.
+ //
+ // Note that this is robust for HOL because in that case function
+ // symbols are not internal nodes
+ if (d_isInternal[t1Id] && d_nodes[t1Id].getNumChildren() == 0
+ && !d_isConstant[t1Id])
{
- std::vector<Node> no_children;
- eqp->d_node = NodeManager::currentNM()->mkNode(kind::PARTIAL_SELECT_0, no_children);
+ eqp->d_node = Node::null();
}
else
{
- eqp->d_node = ProofManager::currentPM()->mkOp(d_nodes[t1Id]);
+ Assert(d_nodes[t1Id].getKind() != kind::BUILTIN);
+ eqp->d_node = d_nodes[t1Id].eqNode(d_nodes[t1Id]);
}
}
return;
// The current node
currentNode = bfsQueue[currentIndex].d_nodeId;
EqualityNodeId edgeNode = d_equalityEdges[currentEdge].getNodeId();
- unsigned reasonType = d_equalityEdges[currentEdge].getReasonType();
+ MergeReasonType reasonType = static_cast<MergeReasonType>(
+ d_equalityEdges[currentEdge].getReasonType());
Node reason = d_equalityEdges[currentEdge].getReason();
Debug("equality")
<< edge.getNodeId() << "} " << d_nodes[edge.getNodeId()] << ")"
<< std::endl;
Debug("equality")
- << d_name << " reason type = "
- << static_cast<MergeReasonType>(reasonType) << std::endl;
+ << d_name
+ << " reason type = " << reasonType
+ << "\n";
std::shared_ptr<EqProof> eqpc;;
// Make child proof if a proof is being constructed
{
eqpc->d_children.push_back(eqpc1);
eqpc->d_children.push_back(eqpc2);
- if (options::proofNew())
+ // build conclusion if ids correspond to non-internal nodes or
+ // if non-internal nodes can be retrieved from them (in the
+ // case of n-ary applications), otherwise leave conclusion as
+ // null. This is only done for congruence kinds, since
+ // congruence is not used otherwise.
+ Kind k = d_nodes[currentNode].getKind();
+ if (d_congruenceKinds[k])
{
- // build conclusion if ids correspond to non-internal nodes or
- // if non-internal nodes can be retrieved from them (in the
- // case of n-ary applications), otherwise leave conclusion as
- // null. This is only done for congruence kinds, since
- // congruence is not used otherwise.
- Kind k = d_nodes[currentNode].getKind();
- if (d_congruenceKinds[k])
- {
- buildEqConclusion(currentNode, edgeNode, eqpc.get());
- }
- else
- {
- Assert(k == kind::EQUAL)
- << "not an internal node " << d_nodes[currentNode]
- << " with non-congruence with " << k << "\n";
- }
- }
- else if (d_nodes[currentNode].getKind() == kind::EQUAL)
- {
- //leave node null for now
- eqpc->d_node = Node::null();
+ buildEqConclusion(currentNode, edgeNode, eqpc.get());
}
else
{
- if (d_nodes[f1.d_a].getKind() == kind::APPLY_UF
- || d_nodes[f1.d_a].getKind() == kind::SELECT
- || d_nodes[f1.d_a].getKind() == kind::STORE)
- {
- eqpc->d_node = d_nodes[f1.d_a];
- }
- else
- {
- if (d_nodes[f1.d_a].getKind() == kind::BUILTIN
- && d_nodes[f1.d_a].getConst<Kind>() == kind::SELECT)
- {
- eqpc->d_node = NodeManager::currentNM()->mkNode(
- kind::PARTIAL_SELECT_1, d_nodes[f1.d_b]);
- // The first child is a PARTIAL_SELECT_0.
- // Give it a child so that we know what kind of (read) it is, when we dump to LFSC.
- Assert(eqpc->d_children[0]->d_node.getKind()
- == kind::PARTIAL_SELECT_0);
- Assert(eqpc->d_children[0]->d_children.size() == 0);
-
- eqpc->d_children[0]->d_node =
- NodeManager::currentNM()->mkNode(
- kind::PARTIAL_SELECT_0, d_nodes[f1.d_b]);
- }
- else
- {
- eqpc->d_node = NodeManager::currentNM()->mkNode(
- kind::PARTIAL_APPLY_UF,
- ProofManager::currentPM()->mkOp(d_nodes[f1.d_a]),
- d_nodes[f1.d_b]);
- }
- }
+ Assert(k == kind::EQUAL)
+ << "not an internal node " << d_nodes[currentNode]
+ << " with non-congruence with " << k << "\n";
}
}
Debug("equality") << pop;
// Get the node we interpreted
TNode interpreted;
- if (eqpc && options::proofNew())
+ if (eqpc)
{
// build the conclusion f(c1, ..., cn) = c
if (d_nodes[currentNode].isConst())
Debug("equality") << d_name << "::eq::getExplanation(): adding: "
<< reason << std::endl;
Debug("equality")
- << d_name << "::eq::getExplanation(): reason type = "
- << static_cast<MergeReasonType>(reasonType) << std::endl;
+ << d_name
+ << "::eq::getExplanation(): reason type = " << reasonType
+ << "\n";
Node a = d_nodes[currentNode];
Node b = d_nodes[d_equalityEdges[currentEdge].getNodeId()];
if (eqpc) {
- //apply proof reconstruction processing (when eqpc is non-null)
- if (d_pathReconstructionTriggers.find(reasonType) != d_pathReconstructionTriggers.end()) {
- d_pathReconstructionTriggers.find(reasonType)
- ->second->notify(reasonType, reason, a, b, equalities,
- eqpc.get());
- }
if (reasonType == MERGED_THROUGH_EQUALITY) {
// in the new proof infrastructure we can assume that "theory
// assumptions", which are a consequence of theory reasoning
// on other assumptions, are externally justified. In this
// case we can use (= a b) directly as the conclusion here.
- eqpc->d_node = !options::proofNew() ? reason : b.eqNode(a);
+ eqpc->d_node = b.eqNode(a);
} else {
// The LFSC translator prefers (not (= a b)) over (= (= a b) false)
} else {
eqp->d_id = MERGED_THROUGH_TRANS;
eqp->d_children.insert( eqp->d_children.end(), eqp_trans.begin(), eqp_trans.end() );
- if (options::proofNew())
- {
- // build conclusion in case of equality between non-internal
- // nodes or of n-ary congruence kinds, otherwise leave as
- // null. The latter is necessary for the overall handling of
- // congruence proofs involving n-ary kinds, see
- // EqProof::reduceNestedCongruence for more details.
- buildEqConclusion(t1Id, t2Id, eqp);
- }
- else
- {
- eqp->d_node = NodeManager::currentNM()->mkNode(
- kind::EQUAL, d_nodes[t1Id], d_nodes[t2Id]);
- }
+ // build conclusion in case of equality between non-internal
+ // nodes or of n-ary congruence kinds, otherwise leave as
+ // null. The latter is necessary for the overall handling of
+ // congruence proofs involving n-ary kinds, see
+ // EqProof::reduceNestedCongruence for more details.
+ buildEqConclusion(t1Id, t2Id, eqp);
}
if (Debug.isOn("pf::ee"))
{
return getEqualityNode(getEqualityNode(t).getFind()).getSize();
}
-
-void EqualityEngine::addPathReconstructionTrigger(unsigned trigger, const PathReconstructionNotify* notify) {
- // Currently we can only inform one callback per trigger
- Assert(d_pathReconstructionTriggers.find(trigger)
- == d_pathReconstructionTriggers.end());
- d_pathReconstructionTriggers[trigger] = notify;
-}
-
-unsigned EqualityEngine::getFreshMergeReasonType() {
- return d_freshMergeReasonType++;
-}
-
std::string EqualityEngine::identify() const { return d_name; }
void EqualityEngine::addTriggerTerm(TNode t, TheoryId tag)
namespace theory {
namespace eq {
-
-class EqProof;
class EqClassesIterator;
class EqClassIterator;
-/**
- * An interface for equality engine notifications during equality path reconstruction.
- * Can be used to add theory-specific logic for, e.g., proof construction.
- */
-class PathReconstructionNotify {
-public:
-
- virtual ~PathReconstructionNotify() {}
-
- virtual void notify(unsigned reasonType, Node reason, Node a, Node b,
- std::vector<TNode>& equalities,
- EqProof* proof) const = 0;
-};
-
/**
* Class for keeping an incremental congruence closure over a set of terms. It provides
* notifications via an EqualityEngineNotify object.
/** The map of kinds with operators to be considered external (for higher-order) */
KindMap d_congruenceKindsExtOperators;
- /** Objects that need to be notified during equality path reconstruction */
- std::map<unsigned, const PathReconstructionNotify*> d_pathReconstructionTriggers;
-
/** Map from nodes to their ids */
std::unordered_map<TNode, EqualityNodeId, TNodeHashFunction> d_nodeIds;
/** Memory for the use-list nodes */
std::vector<UseListNode> d_useListNodes;
- /** A fresh merge reason type to return upon request */
- unsigned d_freshMergeReasonType;
-
/**
* We keep a list of asserted equalities. Not among original terms, but
* among the class representatives.
*/
bool consistent() const { return !d_done; }
- /**
- * Marks an object for merge type based notification during equality path reconstruction.
- */
- void addPathReconstructionTrigger(unsigned trigger, const PathReconstructionNotify* notify);
-
- /**
- * Returns a fresh merge reason type tag for the client to use.
- */
- unsigned getFreshMergeReasonType();
-
/** Identify this equality engine (for debugging, etc..) */
std::string identify() const;
};
* or a merge of an equality to false due to both sides being
* (different) constants.
*/
-enum MergeReasonType {
- /** Terms were merged due to application of congruence closure */
+enum MergeReasonType
+{
+ /** Terms were merged due to congruence */
MERGED_THROUGH_CONGRUENCE,
- /** Terms were merged due to application of pure equality */
+ /** Terms were merged due to an assumption */
MERGED_THROUGH_EQUALITY,
- /** Equality was merged to true, due to both sides of equality being in the same class */
+ /** Terms were merged due to reflexivity */
MERGED_THROUGH_REFLEXIVITY,
- /** Equality was merged to false, due to both sides of equality being a constant */
+ /** Terms were merged due to theory reasoning */
MERGED_THROUGH_CONSTANTS,
- /** (for proofs only) Equality was merged due to transitivity */
+ /** Terms were merged due to transitivity */
MERGED_THROUGH_TRANS,
-
- /** Reason types beyond this constant are theory specific reasons */
- NUMBER_OF_MERGE_REASONS
+ // TEMPORARY RULES WHILE WE DON'T MIGRATE TO PROOF_NEW
+
+ /** Terms were merged due to arrays read-over-write */
+ MERGED_THROUGH_ROW,
+ /** Terms were merged due to arrays read-over-write (1) */
+ MERGED_THROUGH_ROW1,
+ /** Terms were merged due to extensionality */
+ MERGED_THROUGH_EXT,
};
inline std::ostream& operator << (std::ostream& out, MergeReasonType reason) {
case MERGED_THROUGH_REFLEXIVITY:
out << "reflexivity";
break;
- case MERGED_THROUGH_CONSTANTS:
- out << "constants disequal";
- break;
+ case MERGED_THROUGH_CONSTANTS: out << "theory constants"; break;
case MERGED_THROUGH_TRANS:
out << "transitivity";
break;
-
+ case MERGED_THROUGH_ROW: out << "read-over-write"; break;
+ case MERGED_THROUGH_ROW1: out << "read-over-write (1)"; break;
+ case MERGED_THROUGH_EXT: out << "extensionality"; break;
default:
out << "[theory]";
break;
#include "options/smt_options.h"
#include "options/theory_options.h"
#include "options/uf_options.h"
-#include "proof/proof_manager.h"
-#include "proof/theory_proof.h"
-#include "proof/uf_proof.h"
#include "theory/theory_model.h"
#include "theory/type_enumerator.h"
#include "theory/uf/cardinality_extension.h"
return ok;
}/* TheoryUF::propagate(TNode) */
-void TheoryUF::explain(TNode literal, std::vector<TNode>& assumptions, eq::EqProof* pf) {
+void TheoryUF::explain(TNode literal, Node& exp)
+{
+ Debug("uf") << "TheoryUF::explain(" << literal << ")" << std::endl;
+ std::vector<TNode> assumptions;
// Do the work
bool polarity = literal.getKind() != kind::NOT;
TNode atom = polarity ? literal : literal[0];
- if (atom.getKind() == kind::EQUAL) {
+ if (atom.getKind() == kind::EQUAL)
+ {
d_equalityEngine->explainEquality(
- atom[0], atom[1], polarity, assumptions, pf);
- } else {
- d_equalityEngine->explainPredicate(atom, polarity, assumptions, pf);
- }
- if( pf ){
- Debug("pf::uf") << std::endl;
- pf->debug_print("pf::uf");
+ atom[0], atom[1], polarity, assumptions, nullptr);
}
-
- Debug("pf::uf") << "UF: explain( " << literal << " ):" << std::endl << "\t";
- for (unsigned i = 0; i < assumptions.size(); ++i) {
- Debug("pf::uf") << assumptions[i] << " ";
+ else
+ {
+ d_equalityEngine->explainPredicate(atom, polarity, assumptions, nullptr);
}
- Debug("pf::uf") << std::endl;
+ exp = mkAnd(assumptions);
}
TrustNode TheoryUF::explain(TNode literal)
{
- Node exp = explain(literal, NULL);
- return TrustNode::mkTrustPropExp(literal, exp, nullptr);
-}
-
-Node TheoryUF::explain(TNode literal, eq::EqProof* pf) {
- Debug("uf") << "TheoryUF::explain(" << literal << ")" << std::endl;
- std::vector<TNode> assumptions;
- explain(literal, assumptions, pf);
- return mkAnd(assumptions);
+ Node explanation;
+ explain(literal, explanation);
+ return TrustNode::mkTrustPropExp(literal, explanation, nullptr);
}
bool TheoryUF::collectModelValues(TheoryModel* m, const std::set<Node>& termSet)
<< std::endl;
}/* TheoryUF::computeCareGraph() */
-void TheoryUF::conflict(TNode a, TNode b) {
- std::shared_ptr<eq::EqProof> pf =
- d_proofsEnabled ? std::make_shared<eq::EqProof>() : nullptr;
- Node conf = explain(a.eqNode(b), pf.get());
- std::unique_ptr<ProofUF> puf(d_proofsEnabled ? new ProofUF(pf) : nullptr);
- d_out->conflict(conf, std::move(puf));
+void TheoryUF::conflict(TNode a, TNode b)
+{
+ Node conf;
+ explain(a.eqNode(b), conf);
+ d_out->conflict(conf);
d_state.notifyInConflict();
}
*/
bool propagateLit(TNode literal);
- /**
- * Explain why this literal is true by adding assumptions
- * with proof (if "pf" is non-NULL).
- */
- void explain(TNode literal, std::vector<TNode>& assumptions, eq::EqProof* pf);
-
- /**
- * Explain a literal, with proof (if "pf" is non-NULL).
- */
- Node explain(TNode literal, eq::EqProof* pf);
-
/** All the function terms that the theory has seen */
context::CDList<TNode> d_functionsTerms;
CardinalityExtension* getCardinalityExtension() const { return d_thss.get(); }
private:
+ /** Explain why this literal is true by building an explanation */
+ void explain(TNode literal, Node& exp);
+
bool areCareDisequal(TNode x, TNode y);
void addCarePairs(const TNodeTrie* t1,
const TNodeTrie* t2,
ostream_util.h
poly_util.cpp
poly_util.h
- proof.h
random.cpp
random.h
resource_manager.cpp
+++ /dev/null
-/********************* */
-/*! \file proof.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Tim King, Morgan Deters, 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 [[ Add one-line brief description here ]]
- **
- ** [[ Add lengthier description here ]]
- ** \todo document this file
- **/
-
-#include "cvc4_public.h"
-
-#ifndef CVC4__PROOF_H
-#define CVC4__PROOF_H
-
-#include <iosfwd>
-#include <unordered_map>
-
-namespace CVC4 {
-
-class Expr;
-class ProofLetCount;
-struct ExprHashFunction;
-
-typedef std::unordered_map<Expr, ProofLetCount, ExprHashFunction> ProofLetMap;
-
-class CVC4_PUBLIC Proof
-{
- public:
- virtual ~Proof() {}
- virtual void toStream(std::ostream& out) const = 0;
- virtual void toStream(std::ostream& out, const ProofLetMap& map) const = 0;
-};/* class Proof */
-
-}/* CVC4 namespace */
-
-#endif /* CVC4__PROOF_H */
regress0/nl/very-easy-sat.smt2
regress0/nl/very-simple-unsat.smt2
regress0/options/invalid_dump.smt2
- regress0/options/invalid_option_inc_proofs.smt2
regress0/opt-abd-no-use.smt2
regress0/parallel-let.smt2
regress0/parser/as.smt2
regress0/seq/seq-nth.smt2
regress0/seq/seq-nth-uf.smt2
regress0/seq/seq-nth-uf-z.smt2
- regress0/seq/seq-nth-undef.smt2
+ regress0/seq/seq-nth-undef.smt2
regress0/seq/seq-rewrites.smt2
regress0/sets/abt-min.smt2
regress0/sets/abt-te-exh.smt2
-; COMMAND-LINE: --fewer-preprocessing-holes
; EXPECT: unsat
(set-logic QF_UF)
(set-info :status unsat)
+++ /dev/null
-; REQUIRES: proof
-; COMMAND-LINE: --incremental --proof
-; EXPECT: (error "Error in option parsing: --incremental is not supported with proofs")
-; EXIT: 1
-(set-logic QF_BV)
-(check-sat)
-; COMMAND-LINE: --fewer-preprocessing-holes --check-proof --quiet
+; COMMAND-LINE: --quiet
; EXPECT: unsat
(set-logic QF_BV)
(declare-fun x () (_ BitVec 4))
; EXPECT: success
; EXPECT: success
; EXPECT: success
+; EXPECT: unsupported
; EXPECT: success
; EXPECT: success
; EXPECT: success
-; EXPECT: success
-; EXPECT: (error "")
; EXPECT: (error "")
; EXPECT: (error "")
; EXPECT: (error "")
(declare-fun p () Bool)
(get-unsat-core)
(get-value (p))
-(get-proof)
(get-model)
(get-assignment)
(assert true)
; REQUIRES: proof
-; COMMAND-LINE: --dump-instantiations --proof --print-inst-full
+; COMMAND-LINE: --dump-instantiations --produce-unsat-cores --print-inst-full
; EXPECT: unsat
; EXPECT: (instantiations (forall ((x Int)) (or (P x) (Q x)) )
; EXPECT: ( 2 )
(assert (forall ((x Int)) (or (not (S x)) (not (Q x)))))
(assert (and (not (R 0)) (not (R 10)) (not (S 1)) (not (P 2))))
(assert (S 2))
-; This tests that --proof minimizes the instantiations printed out.
-; This regression should require only the 2 instantiations above, but
-; may try more.
+; This tests that --produce-unsat-cores minimizes the instantiations
+; printed out. This regression should require only the 2
+; instantiations above, but may try more.
(check-sat)
add_subdirectory(main)
add_subdirectory(parser)
add_subdirectory(prop)
-add_subdirectory(proof)
add_subdirectory(theory)
add_subdirectory(preprocessing)
add_subdirectory(util)
+++ /dev/null
-#-----------------------------------------------------------------------------#
-# Add unit tests
-
-cvc4_add_unit_test_black(drat_proof_black proof)
-cvc4_add_unit_test_black(er_proof_black proof)
-cvc4_add_unit_test_black(lrat_proof_black proof)
-cvc4_add_unit_test_black(lfsc_proof_printer_black proof)
+++ /dev/null
-/********************* */
-/*! \file drat_proof_black.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir, 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 Black box testing of the DRAT proof class
- **
- ** In particular, tests DRAT binary parsing.
- **/
-
-#include <cxxtest/TestSuite.h>
-
-#include <cctype>
-
-#include "proof/drat/drat_proof.h"
-
-using namespace CVC4::proof::drat;
-
-class DratProofBlack : public CxxTest::TestSuite
-{
- public:
- void setUp() override {}
- void tearDown() override {}
-
- void testParseOneAdd();
- void testParseOneMediumAdd();
- void testParseOneBigAdd();
- void testParseLiteralIsTooBig();
- void testParseLiteralOverflow();
- void testParseClauseOverflow();
-
- void testParseTwo();
-
- void testOutputTwoAsText();
- void testOutputTwoAsLfsc();
-};
-
-void DratProofBlack::testParseOneAdd()
-{
- // a 1;
- std::string input("a\x02\x00", 3);
- DratProof proof = DratProof::fromBinary(input);
-
- TS_ASSERT_EQUALS(proof.getInstructions()[0].d_kind, ADDITION);
- TS_ASSERT_EQUALS(proof.getInstructions()[0].d_clause.size(), 1);
- TS_ASSERT_EQUALS(proof.getInstructions()[0].d_clause[0],
- SatLiteral(0, false));
-}
-
-void DratProofBlack::testParseOneMediumAdd()
-{
- // a -255;
- std::string input("a\xff\x01\x00", 4);
- DratProof proof = DratProof::fromBinary(input);
-
- TS_ASSERT_EQUALS(proof.getInstructions()[0].d_kind, ADDITION);
- TS_ASSERT_EQUALS(proof.getInstructions()[0].d_clause.size(), 1);
- TS_ASSERT_EQUALS(proof.getInstructions()[0].d_clause[0],
- SatLiteral(126, true));
-}
-
-void DratProofBlack::testParseOneBigAdd()
-{
- // a -2199023255551;
- std::string input("a\xff\xff\xff\xff\xff\x7f\x00", 8);
- DratProof proof = DratProof::fromBinary(input);
-
- TS_ASSERT_EQUALS(proof.getInstructions()[0].d_kind, ADDITION);
- TS_ASSERT_EQUALS(proof.getInstructions()[0].d_clause.size(), 1);
- TS_ASSERT_EQUALS(proof.getInstructions()[0].d_clause[0],
- SatLiteral(2199023255550, true));
-}
-
-void DratProofBlack::testParseLiteralIsTooBig()
-{
- std::string input("a\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x00",
- 14);
- TS_ASSERT_THROWS(DratProof::fromBinary(input), InvalidDratProofException&);
-}
-
-void DratProofBlack::testParseLiteralOverflow()
-{
- std::string input("a\x80", 2);
- TS_ASSERT_THROWS(DratProof::fromBinary(input), InvalidDratProofException&);
-}
-
-void DratProofBlack::testParseClauseOverflow()
-{
- std::string input("a\x80\x01", 3);
- TS_ASSERT_THROWS(DratProof::fromBinary(input), InvalidDratProofException&);
-}
-
-void DratProofBlack::testParseTwo()
-{
- // d -63 -8193
- // 129 -8191
- std::string input("\x64\x7f\x83\x80\x01\x00\x61\x82\x02\xff\x7f\x00", 12);
- DratProof proof = DratProof::fromBinary(input);
-
- TS_ASSERT_EQUALS(proof.getInstructions()[0].d_kind, DELETION);
- TS_ASSERT_EQUALS(proof.getInstructions()[0].d_clause.size(), 2);
- TS_ASSERT_EQUALS(proof.getInstructions()[0].d_clause[0],
- SatLiteral(62, true));
- TS_ASSERT_EQUALS(proof.getInstructions()[0].d_clause[1],
- SatLiteral(8192, true));
-
- TS_ASSERT_EQUALS(proof.getInstructions()[1].d_kind, ADDITION);
- TS_ASSERT_EQUALS(proof.getInstructions()[1].d_clause.size(), 2);
- TS_ASSERT_EQUALS(proof.getInstructions()[1].d_clause[0],
- SatLiteral(128, false));
- TS_ASSERT_EQUALS(proof.getInstructions()[1].d_clause[1],
- SatLiteral(8190, true));
-}
-
-void DratProofBlack::testOutputTwoAsText()
-{
- // d -63 -8193
- // 129 -8191
- std::string input("\x64\x7f\x83\x80\x01\x00\x61\x82\x02\xff\x7f\x00", 12);
- DratProof proof = DratProof::fromBinary(input);
-
- std::ostringstream output;
- proof.outputAsText(output);
-
- std::istringstream tokens(output.str());
- std::string token;
-
- tokens >> token;
- TS_ASSERT_EQUALS(token, "d");
-
- tokens >> token;
- TS_ASSERT_EQUALS(token, "-63");
-
- tokens >> token;
- TS_ASSERT_EQUALS(token, "-8193");
-
- tokens >> token;
- TS_ASSERT_EQUALS(token, "0");
-
- tokens >> token;
- TS_ASSERT_EQUALS(token, "129");
-
- tokens >> token;
- TS_ASSERT_EQUALS(token, "-8191");
-
- tokens >> token;
- TS_ASSERT_EQUALS(token, "0");
-}
-
-void DratProofBlack::testOutputTwoAsLfsc()
-{
- // d -63 -8193
- // 129 -8191
- std::string input("\x64\x7f\x83\x80\x01\x00\x61\x82\x02\xff\x7f\x00", 12);
- DratProof proof = DratProof::fromBinary(input);
- std::ostringstream lfsc;
- proof.outputAsLfsc(lfsc, 2);
- std::ostringstream lfscWithoutWhitespace;
- for (char c : lfsc.str())
- {
- if (!std::isspace(c))
- {
- lfscWithoutWhitespace << c;
- }
- }
- std::string expectedLfsc =
- "(DRATProofd (clc (neg bb.v62) (clc (neg bb.v8192) cln))"
- "(DRATProofa (clc (pos bb.v128) (clc (neg bb.v8190) cln))"
- "DRATProofn))";
- std::ostringstream expectedLfscWithoutWhitespace;
- for (char c : expectedLfsc)
- {
- if (!std::isspace(c))
- {
- expectedLfscWithoutWhitespace << c;
- }
- }
-
- TS_ASSERT_EQUALS(lfscWithoutWhitespace.str(),
- expectedLfscWithoutWhitespace.str());
-}
+++ /dev/null
-/********************* */
-/*! \file er_proof_black.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 Black box testing of the ER proof class
- **
- ** In particular, tests TRACECHECK parsing and ER LFSC output.
- **/
-
-#include <cxxtest/TestSuite.h>
-
-#include <algorithm>
-#include <cctype>
-#include <iostream>
-#include <iterator>
-#include <string>
-#include <unordered_map>
-#include <vector>
-
-#include "base/configuration_private.h"
-#include "proof/clause_id.h"
-#include "proof/er/er_proof.h"
-#include "prop/sat_solver_types.h"
-#include "utils.h"
-
-#if IS_LFSC_BUILD
-#include "lfscc.h"
-
-namespace CVC4 {
-namespace proof {
-extern const char* const plf_signatures;
-} // namespace proof
-} // namespace CVC4
-#endif
-
-
-using namespace CVC4;
-using namespace CVC4::proof::er;
-using namespace CVC4::prop;
-
-class ErProofBlack : public CxxTest::TestSuite
-{
- public:
- void setUp() override {}
- void tearDown() override {}
-
- void testTraceCheckParse1Line();
- void testTraceCheckParse5Lines();
- void testErTraceCheckParse();
- void testErTraceCheckOutput();
- void testErTraceCheckOutputMedium();
-};
-
-/**
- * @brief Add a new clause to the clause store and list of used clauses
- *
- * @param clauses the clause store
- * @param usedIds the used clauses
- * @param id the id of the new clause
- * @param clause the clause itself
- */
-void addClause(std::unordered_map<ClauseId, SatClause>& clauses,
- std::vector<ClauseId>& usedIds,
- ClauseId id,
- SatClause&& clause)
-{
- clauses.emplace(id, std::move(clause));
- usedIds.push_back(id);
-}
-
-void ErProofBlack::testTraceCheckParse1Line()
-{
- std::string tracecheckText = "1 -2 3 0 4 2 0\n";
- std::istringstream stream(tracecheckText);
- TraceCheckProof pf = TraceCheckProof::fromText(stream);
- TS_ASSERT_EQUALS(pf.d_lines.size(), 1);
-
- TS_ASSERT_EQUALS(pf.d_lines[0].d_idx, 1);
- TS_ASSERT_EQUALS(pf.d_lines[0].d_clause.size(), 2);
- TS_ASSERT_EQUALS(pf.d_lines[0].d_clause[0], SatLiteral(1, true));
- TS_ASSERT_EQUALS(pf.d_lines[0].d_clause[1], SatLiteral(2, false));
- TS_ASSERT_EQUALS(pf.d_lines[0].d_chain.size(), 2);
- TS_ASSERT_EQUALS(pf.d_lines[0].d_chain[0], 4);
- TS_ASSERT_EQUALS(pf.d_lines[0].d_chain[1], 2);
-}
-
-void ErProofBlack::testTraceCheckParse5Lines()
-{
- std::string tracecheckText =
- "1 1 -2 3 0 0\n"
- "2 -1 0 0\n"
- "3 2 0 0\n"
- "4 -3 0 0\n"
- "5 0 1 2 4 3 0\n";
- std::istringstream stream(tracecheckText);
- TraceCheckProof pf = TraceCheckProof::fromText(stream);
- TS_ASSERT_EQUALS(pf.d_lines.size(), 5);
-
- TS_ASSERT_EQUALS(pf.d_lines[0].d_idx, 1);
- TS_ASSERT_EQUALS(pf.d_lines[4].d_idx, 5);
-
- TS_ASSERT_EQUALS(pf.d_lines[0].d_clause.size(), 3);
- TS_ASSERT_EQUALS(pf.d_lines[0].d_clause[0], SatLiteral(0, false));
- TS_ASSERT_EQUALS(pf.d_lines[0].d_clause[1], SatLiteral(1, true));
- TS_ASSERT_EQUALS(pf.d_lines[0].d_clause[2], SatLiteral(2, false));
- TS_ASSERT_EQUALS(pf.d_lines[0].d_chain.size(), 0);
-
- TS_ASSERT_EQUALS(pf.d_lines[4].d_chain.size(), 4);
- TS_ASSERT_EQUALS(pf.d_lines[4].d_chain[0], 1);
- TS_ASSERT_EQUALS(pf.d_lines[4].d_chain[1], 2);
- TS_ASSERT_EQUALS(pf.d_lines[4].d_chain[2], 4);
- TS_ASSERT_EQUALS(pf.d_lines[4].d_chain[3], 3);
- TS_ASSERT_EQUALS(pf.d_lines[4].d_clause.size(), 0);
-}
-
-void ErProofBlack::testErTraceCheckParse()
-{
- std::string tracecheckText =
- "1 1 2 -3 0 0\n"
- "2 -1 -2 3 0 0\n"
- "3 2 3 -4 0 0\n"
- "4 -2 -3 4 0 0\n"
- "5 -1 -3 -4 0 0\n"
- "6 1 3 4 0 0\n"
- "7 -1 2 4 0 0\n"
- "8 1 -2 -4 0 0\n"
- "9 5 0 0\n"
- "10 5 1 0 0\n"
- "11 4 5 2 0 10 7 0\n"
- "12 -4 5 -3 0 10 5 0\n"
- "13 3 5 -2 0 10 2 0\n"
- "14 -2 -4 0 2 5 8 0\n"
- "15 4 3 0 7 2 6 0\n"
- "16 2 -3 0 7 5 1 0\n"
- "17 2 0 3 15 16 0\n"
- "18 0 4 15 14 17 0\n";
- std::istringstream stream(tracecheckText);
- TraceCheckProof tc = TraceCheckProof::fromText(stream);
-
- std::unordered_map<ClauseId, SatClause> clauses;
- std::vector<ClauseId> usedIds;
- addClause(
- clauses,
- usedIds,
- 1,
- std::vector<SatLiteral>{
- SatLiteral(0, false), SatLiteral(1, false), SatLiteral(2, true)});
- addClause(
- clauses,
- usedIds,
- 2,
- std::vector<SatLiteral>{
- SatLiteral(0, true), SatLiteral(1, true), SatLiteral(2, false)});
- addClause(
- clauses,
- usedIds,
- 3,
- std::vector<SatLiteral>{
- SatLiteral(1, false), SatLiteral(2, false), SatLiteral(3, true)});
- addClause(
- clauses,
- usedIds,
- 4,
- std::vector<SatLiteral>{
- SatLiteral(1, true), SatLiteral(2, true), SatLiteral(3, false)});
- addClause(clauses,
- usedIds,
- 5,
- std::vector<SatLiteral>{
- SatLiteral(0, true), SatLiteral(2, true), SatLiteral(3, true)});
- addClause(
- clauses,
- usedIds,
- 6,
- std::vector<SatLiteral>{
- SatLiteral(0, false), SatLiteral(2, false), SatLiteral(3, false)});
- addClause(
- clauses,
- usedIds,
- 7,
- std::vector<SatLiteral>{
- SatLiteral(0, true), SatLiteral(1, false), SatLiteral(3, false)});
- addClause(
- clauses,
- usedIds,
- 8,
- std::vector<SatLiteral>{
- SatLiteral(0, false), SatLiteral(1, true), SatLiteral(3, true)});
- ErProof pf(clauses, usedIds, std::move(tc));
-
- TS_ASSERT_EQUALS(pf.getInputClauseIds()[0], 1);
- TS_ASSERT_EQUALS(pf.getInputClauseIds()[7], 8);
-
- TS_ASSERT_EQUALS(pf.getDefinitions().size(), 1)
- TS_ASSERT_EQUALS(pf.getDefinitions()[0].d_newVariable, SatVariable(4));
- TS_ASSERT_EQUALS(pf.getDefinitions()[0].d_oldLiteral, SatLiteral(0, true));
- TS_ASSERT_EQUALS(pf.getDefinitions()[0].d_otherLiterals.size(), 0);
- TS_ASSERT_EQUALS(pf.getTraceCheckProof().d_lines.size(), 18);
-
- TS_ASSERT_EQUALS(pf.getTraceCheckProof().d_lines[0].d_idx, 1);
- TS_ASSERT_EQUALS(pf.getTraceCheckProof().d_lines[16].d_idx, 17);
-
- TS_ASSERT_EQUALS(pf.getTraceCheckProof().d_lines[0].d_clause.size(), 3);
- TS_ASSERT_EQUALS(pf.getTraceCheckProof().d_lines[0].d_clause[0],
- SatLiteral(0, false));
- TS_ASSERT_EQUALS(pf.getTraceCheckProof().d_lines[0].d_clause[1],
- SatLiteral(1, false));
- TS_ASSERT_EQUALS(pf.getTraceCheckProof().d_lines[0].d_clause[2],
- SatLiteral(2, true));
- TS_ASSERT_EQUALS(pf.getTraceCheckProof().d_lines[0].d_chain.size(), 0);
-
- TS_ASSERT_EQUALS(pf.getTraceCheckProof().d_lines[16].d_clause.size(), 1);
- TS_ASSERT_EQUALS(pf.getTraceCheckProof().d_lines[16].d_clause[0],
- SatLiteral(1, false));
- TS_ASSERT_EQUALS(pf.getTraceCheckProof().d_lines[16].d_chain.size(), 3);
- TS_ASSERT_EQUALS(pf.getTraceCheckProof().d_lines[16].d_chain[0], 3);
- TS_ASSERT_EQUALS(pf.getTraceCheckProof().d_lines[16].d_chain[1], 15);
- TS_ASSERT_EQUALS(pf.getTraceCheckProof().d_lines[16].d_chain[2], 16);
-}
-
-void ErProofBlack::testErTraceCheckOutput()
-{
- std::string tracecheckText =
- "1 1 2 -3 0 0\n"
- "2 -1 -2 3 0 0\n"
- "3 2 3 -4 0 0\n"
- "4 -2 -3 4 0 0\n"
- "5 -1 -3 -4 0 0\n"
- "6 1 3 4 0 0\n"
- "7 -1 2 4 0 0\n"
- "8 1 -2 -4 0 0\n"
- "9 5 0 0\n"
- "10 5 1 0 0\n"
- "11 4 5 2 0 10 7 0\n"
- "12 -4 5 -3 0 10 5 0\n"
- "13 3 5 -2 0 10 2 0\n"
- "14 -2 -4 0 2 5 8 0\n"
- "15 4 3 0 7 2 6 0\n"
- "16 2 -3 0 7 5 1 0\n"
- "17 2 0 3 15 16 0\n"
- "18 0 4 15 14 17 0\n";
- std::istringstream stream(tracecheckText);
- TraceCheckProof tc = TraceCheckProof::fromText(stream);
-
- std::unordered_map<ClauseId, SatClause> clauses;
- std::vector<ClauseId> usedIds;
- addClause(
- clauses,
- usedIds,
- 1,
- std::vector<SatLiteral>{
- SatLiteral(0, false), SatLiteral(1, false), SatLiteral(2, true)});
- addClause(
- clauses,
- usedIds,
- 2,
- std::vector<SatLiteral>{
- SatLiteral(0, true), SatLiteral(1, true), SatLiteral(2, false)});
- addClause(
- clauses,
- usedIds,
- 3,
- std::vector<SatLiteral>{
- SatLiteral(1, false), SatLiteral(2, false), SatLiteral(3, true)});
- addClause(
- clauses,
- usedIds,
- 4,
- std::vector<SatLiteral>{
- SatLiteral(1, true), SatLiteral(2, true), SatLiteral(3, false)});
- addClause(clauses,
- usedIds,
- 5,
- std::vector<SatLiteral>{
- SatLiteral(0, true), SatLiteral(2, true), SatLiteral(3, true)});
- addClause(
- clauses,
- usedIds,
- 6,
- std::vector<SatLiteral>{
- SatLiteral(0, false), SatLiteral(2, false), SatLiteral(3, false)});
- addClause(
- clauses,
- usedIds,
- 7,
- std::vector<SatLiteral>{
- SatLiteral(0, true), SatLiteral(1, false), SatLiteral(3, false)});
- addClause(
- clauses,
- usedIds,
- 8,
- std::vector<SatLiteral>{
- SatLiteral(0, false), SatLiteral(1, true), SatLiteral(3, true)});
- ErProof pf(clauses, usedIds, std::move(tc));
-
- std::ostringstream lfsc;
- pf.outputAsLfsc(lfsc);
-
- std::string out = R"EOF(
- (decl_definition
- (neg bb.v0)
- cln
- (\ er.v4
- (\ er.def4
- (clausify_definition _ _ _ er.def4 _
- (\ er.c9
- (\ er.c10
- (\ er.cnf4
- (satlem_simplify _ _ _
- (R _ _ er.c10 bb.pb7 bb.v0) (\ er.c11
- (satlem_simplify _ _ _
- (R _ _ er.c10 bb.pb5 bb.v0) (\ er.c12
- (satlem_simplify _ _ _
- (R _ _ er.c10 bb.pb2 bb.v0) (\ er.c13
- (satlem_simplify _ _ _
- (Q _ _ (R _ _ bb.pb2 bb.pb5 bb.v2) bb.pb8 bb.v0) (\ er.c14
- (satlem_simplify _ _ _
- (Q _ _ (R _ _ bb.pb7 bb.pb2 bb.v1) bb.pb6 bb.v0) (\ er.c15
- (satlem_simplify _ _ _
- (Q _ _ (R _ _ bb.pb7 bb.pb5 bb.v3) bb.pb1 bb.v0) (\ er.c16
- (satlem_simplify _ _ _
- (R _ _ (Q _ _ bb.pb3 er.c15 bb.v3) er.c16 bb.v2) (\ er.c17
- (satlem_simplify _ _ _
- (Q _ _ (R _ _ (Q _ _ bb.pb4 er.c15 bb.v2) er.c14 bb.v3)
- er.c17 bb.v1) (\ er.c18
- er.c18 ; (holds cln)
- ))))))))))))))))
- )))
- )
- ))
- )
- )EOF";
-
- TS_ASSERT_EQUALS(filterWhitespace(lfsc.str()), filterWhitespace(out));
-}
-
-/**
- * This proof has been specially constructed to stress-test the proof
- * machinery, while still being short. It's a bit meandering...
- */
-void ErProofBlack::testErTraceCheckOutputMedium()
-{
- std::string tracecheckText =
- "1 1 2 -3 0 0\n"
- "2 -1 -2 3 0 0\n"
- "3 2 3 -4 0 0\n"
- "4 -2 -3 4 0 0\n"
- "5 -1 -3 -4 0 0\n"
- "6 1 3 4 0 0\n"
- "7 -1 2 4 0 0\n"
- "8 1 -2 -4 0 0\n"
-
- "9 5 2 4 0 0\n" // Definition with 2 other variables
- "10 5 1 0 0\n"
- "11 2 -5 -1 0 0\n"
- "12 4 -5 -1 0 0\n"
-
- "13 6 0 0\n" // Definition with no other variables
- "14 6 -3 0 0\n"
-
- "15 -3 4 0 11 1 10 7 4 0\n" // Chain w/ both def. and input clauses
-
- "16 -2 -4 0 2 5 8 0\n" // The useful bit of the proof
- "17 4 3 0 7 2 6 0\n"
- "18 2 -3 0 7 5 1 0\n"
- "19 2 0 3 17 18 0\n"
- "20 0 4 17 16 19 0\n";
-
- std::istringstream stream(tracecheckText);
- TraceCheckProof tc = TraceCheckProof::fromText(stream);
-
- std::unordered_map<ClauseId, SatClause> clauses;
- std::vector<ClauseId> usedIds;
- addClause(
- clauses,
- usedIds,
- 1,
- std::vector<SatLiteral>{
- SatLiteral(0, false), SatLiteral(1, false), SatLiteral(2, true)});
- addClause(
- clauses,
- usedIds,
- 2,
- std::vector<SatLiteral>{
- SatLiteral(0, true), SatLiteral(1, true), SatLiteral(2, false)});
- addClause(
- clauses,
- usedIds,
- 3,
- std::vector<SatLiteral>{
- SatLiteral(1, false), SatLiteral(2, false), SatLiteral(3, true)});
- addClause(
- clauses,
- usedIds,
- 4,
- std::vector<SatLiteral>{
- SatLiteral(1, true), SatLiteral(2, true), SatLiteral(3, false)});
- addClause(clauses,
- usedIds,
- 5,
- std::vector<SatLiteral>{
- SatLiteral(0, true), SatLiteral(2, true), SatLiteral(3, true)});
- addClause(
- clauses,
- usedIds,
- 6,
- std::vector<SatLiteral>{
- SatLiteral(0, false), SatLiteral(2, false), SatLiteral(3, false)});
- addClause(
- clauses,
- usedIds,
- 7,
- std::vector<SatLiteral>{
- SatLiteral(0, true), SatLiteral(1, false), SatLiteral(3, false)});
- addClause(
- clauses,
- usedIds,
- 8,
- std::vector<SatLiteral>{
- SatLiteral(0, false), SatLiteral(1, true), SatLiteral(3, true)});
- ErProof pf(clauses, usedIds, std::move(tc));
-
- std::ostringstream actual_pf_body;
- pf.outputAsLfsc(actual_pf_body);
-
-#if IS_LFSC_BUILD
- std::string pf_header = R"EOF(
- (check
- (% bb.v0 var
- (% bb.v1 var
- (% bb.v2 var
- (% bb.v3 var
- (% bb.pb1 (holds (clc (pos bb.v0) (clc (pos bb.v1) (clc (neg bb.v2) cln))))
- (% bb.pb2 (holds (clc (neg bb.v0) (clc (neg bb.v1) (clc (pos bb.v2) cln))))
- (% bb.pb3 (holds (clc (pos bb.v1) (clc (pos bb.v2) (clc (neg bb.v3) cln))))
- (% bb.pb4 (holds (clc (neg bb.v1) (clc (neg bb.v2) (clc (pos bb.v3) cln))))
- (% bb.pb5 (holds (clc (neg bb.v0) (clc (neg bb.v2) (clc (neg bb.v3) cln))))
- (% bb.pb6 (holds (clc (pos bb.v0) (clc (pos bb.v2) (clc (pos bb.v3) cln))))
- (% bb.pb7 (holds (clc (neg bb.v0) (clc (pos bb.v1) (clc (pos bb.v3) cln))))
- (% bb.pb8 (holds (clc (pos bb.v0) (clc (neg bb.v1) (clc (neg bb.v3) cln))))
- (: (holds cln)
- )EOF";
-
- std::string pf_footer = R"EOF(
- )
- ))))))))
- ))))
- )
- )EOF";
-
- std::stringstream actual_pf;
- actual_pf << proof::plf_signatures << pf_header << actual_pf_body.str() << pf_footer;
-
- lfscc_init();
- lfscc_check_file(actual_pf, false, false, false, false, false, false, false);
-#endif
-}
+++ /dev/null
-/********************* */
-/*! \file lfsc_proof_printer_black.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 Black box testing of LFSC proof printing
- **/
-
-#include <cxxtest/TestSuite.h>
-
-#include "proof/lfsc_proof_printer.h"
-#include "prop/sat_solver_types.h"
-#include "proof/clause_id.h"
-
-using namespace CVC4::proof;
-using namespace CVC4::prop;
-
-class LfscProofPrinterBlack : public CxxTest::TestSuite
-{
- public:
- void setUp() override {}
- void tearDown() override {}
-
- void testPrintClause();
- void testPrintSatInputProof();
- void testPrintCMapProof();
-};
-
-void LfscProofPrinterBlack::testPrintClause()
-{
- SatClause clause{
- SatLiteral(0, false), SatLiteral(1, true), SatLiteral(3, false)};
- std::ostringstream lfsc;
-
- LFSCProofPrinter::printSatClause(clause, lfsc, "");
-
- std::string expectedLfsc =
- "(clc (pos .v0) "
- "(clc (neg .v1) "
- "(clc (pos .v3) "
- "cln)))";
-
- TS_ASSERT_EQUALS(lfsc.str(), expectedLfsc);
-}
-
-void LfscProofPrinterBlack::testPrintSatInputProof()
-{
- std::vector<CVC4::ClauseId> ids{2, 40, 3};
- std::ostringstream lfsc;
-
- LFSCProofPrinter::printSatInputProof(ids, lfsc, "");
-
- std::string expectedLfsc =
- "(cnfc_proof _ _ _ .pb2 "
- "(cnfc_proof _ _ _ .pb40 "
- "(cnfc_proof _ _ _ .pb3 "
- "cnfn_proof)))";
-
- std::ostringstream lfscWithoutWhitespace;
- for (char c : lfsc.str())
- {
- if (!std::isspace(c))
- {
- lfscWithoutWhitespace << c;
- }
- }
- std::ostringstream expectedLfscWithoutWhitespace;
- for (char c : expectedLfsc)
- {
- if (!std::isspace(c))
- {
- expectedLfscWithoutWhitespace << c;
- }
- }
-
- TS_ASSERT_EQUALS(lfscWithoutWhitespace.str(),
- expectedLfscWithoutWhitespace.str());
-}
-
-void LfscProofPrinterBlack::testPrintCMapProof()
-{
- std::vector<CVC4::ClauseId> ids{2, 40, 3};
- std::ostringstream lfsc;
-
- LFSCProofPrinter::printCMapProof(ids, lfsc, "");
-
- std::string expectedLfsc =
- "(CMapc_proof 1 _ _ _ .pb2 "
- "(CMapc_proof 2 _ _ _ .pb40 "
- "(CMapc_proof 3 _ _ _ .pb3 "
- "CMapn_proof)))";
-
- std::ostringstream lfscWithoutWhitespace;
- for (char c : lfsc.str())
- {
- if (!std::isspace(c))
- {
- lfscWithoutWhitespace << c;
- }
- }
- std::ostringstream expectedLfscWithoutWhitespace;
- for (char c : expectedLfsc)
- {
- if (!std::isspace(c))
- {
- expectedLfscWithoutWhitespace << c;
- }
- }
-
- TS_ASSERT_EQUALS(lfscWithoutWhitespace.str(),
- expectedLfscWithoutWhitespace.str());
-}
+++ /dev/null
-/********************* */
-/*! \file lrat_proof_black.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir, 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 Black box testing of the LRAT proof class
- **
- ** In particular, tests LRAT LFSC output.
- **/
-
-#include <cxxtest/TestSuite.h>
-
-#include <iostream>
-
-#include "proof/lrat/lrat_proof.h"
-#include "prop/sat_solver_types.h"
-#include "utils.h"
-
-using namespace CVC4;
-using namespace CVC4::proof::lrat;
-using namespace CVC4::prop;
-
-class LratProofBlack : public CxxTest::TestSuite
-{
- public:
- void setUp() override {}
- void tearDown() override {}
-
- void testOutputAsLfsc();
-};
-
-void LratProofBlack::testOutputAsLfsc()
-{
- std::vector<std::unique_ptr<LratInstruction>> instructions;
-
- // 6 d 1 2
- std::vector<ClauseIdx> clausesToDelete{1, 2};
- std::unique_ptr<LratDeletion> deletion = std::unique_ptr<LratDeletion>(
- new LratDeletion(6, std::move(clausesToDelete)));
- instructions.push_back(std::move(deletion));
-
- // 7 1 2 0 5 2 0
- std::vector<SatLiteral> firstAddedClause{SatLiteral(1, false),
- SatLiteral(2, false)};
- LratUPTrace firstTrace{5, 2};
- std::vector<std::pair<ClauseIdx, LratUPTrace>> firstHints;
- std::unique_ptr<LratAddition> add1 =
- std::unique_ptr<LratAddition>(new LratAddition(
- 7, std::move(firstAddedClause), std::move(firstTrace), firstHints));
- instructions.push_back(std::move(add1));
-
- // 8 2 0 -1 3 -5 2 0
- std::vector<SatLiteral> secondAddedClause{SatLiteral(2, false)};
- LratUPTrace secondTrace;
- std::vector<std::pair<ClauseIdx, LratUPTrace>> secondHints;
- LratUPTrace secondHints0Trace{3};
- secondHints.emplace_back(1, secondHints0Trace);
- LratUPTrace secondHints1Trace{2};
- secondHints.emplace_back(5, secondHints1Trace);
- std::unique_ptr<LratAddition> add2 = std::unique_ptr<LratAddition>(
- new LratAddition(8,
- std::move(secondAddedClause),
- std::move(secondTrace),
- secondHints));
- instructions.push_back(std::move(add2));
-
- LratProof proof(std::move(instructions));
-
- std::ostringstream lfsc;
- proof.outputAsLfsc(lfsc);
-
- // 6 d 1 2
- // 7 1 2 0 5 2 0
- // 8 2 0 -1 3 -5 2 0
- std::string expectedLfsc =
- "(LRATProofd (CIListc 1 (CIListc 2 CIListn)) "
- "(LRATProofa 7 "
- " (clc (pos bb.v1) (clc (pos bb.v2) cln))"
- " (Tracec 5 (Tracec 2 Tracen))"
- " RATHintsn "
- "(LRATProofa 8 "
- " (clc (pos bb.v2) cln)"
- " Tracen "
- " (RATHintsc 1 (Tracec 3 Tracen)"
- " (RATHintsc 5 (Tracec 2 Tracen)"
- " RATHintsn)) "
- "LRATProofn)))";
-
- TS_ASSERT_EQUALS(filterWhitespace(lfsc.str()),
- filterWhitespace(expectedLfsc));
-}
+++ /dev/null
-/********************* */
-/*! \file utils.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 Utilities for proof testing
- **/
-
-#include <algorithm>
-#include <string>
-#include <cctype>
-#include <iterator>
-
-/**
- * Creates a new stream with whitespace removed.
- *
- * @param s the source string
- *
- * @return a string without whitespace
- */
-std::string filterWhitespace(const std::string& s)
-{
- std::string out;
- std::copy_if(s.cbegin(), s.cend(), std::inserter(out, out.end()), [](char c) {
- return !std::isspace(c);
- });
- return out;
-}
Node a = d_nodeManager->mkVar(d_nodeManager->booleanType());
Node b = d_nodeManager->mkVar(d_nodeManager->booleanType());
Node c = d_nodeManager->mkVar(d_nodeManager->booleanType());
- d_cnfStream->convertAndAssert(d_nodeManager->mkNode(kind::AND, a, b, c),
- false, false, RULE_INVALID, Node::null());
+ d_cnfStream->convertAndAssert(
+ d_nodeManager->mkNode(kind::AND, a, b, c), false, false);
TS_ASSERT(d_satSolver->addClauseCalled());
}
Node f = d_nodeManager->mkVar(d_nodeManager->booleanType());
d_cnfStream->convertAndAssert(
d_nodeManager->mkNode(
- kind::IMPLIES, d_nodeManager->mkNode(kind::AND, a, b),
+ kind::IMPLIES,
+ d_nodeManager->mkNode(kind::AND, a, b),
d_nodeManager->mkNode(
- kind::EQUAL, d_nodeManager->mkNode(kind::OR, c, d),
+ kind::EQUAL,
+ d_nodeManager->mkNode(kind::OR, c, d),
d_nodeManager->mkNode(kind::NOT,
d_nodeManager->mkNode(kind::XOR, e, f)))),
- false, false, RULE_INVALID, Node::null());
+ false,
+ false);
TS_ASSERT(d_satSolver->addClauseCalled());
}
void testTrue() {
NodeManagerScope nms(d_nodeManager);
- d_cnfStream->convertAndAssert(d_nodeManager->mkConst(true), false, false,
- RULE_INVALID, Node::null());
+ d_cnfStream->convertAndAssert(d_nodeManager->mkConst(true), false, false);
TS_ASSERT(d_satSolver->addClauseCalled());
}
void testFalse() {
NodeManagerScope nms(d_nodeManager);
- d_cnfStream->convertAndAssert(d_nodeManager->mkConst(false), false, false,
- RULE_INVALID, Node::null());
+ d_cnfStream->convertAndAssert(d_nodeManager->mkConst(false), false, false);
TS_ASSERT(d_satSolver->addClauseCalled());
}
NodeManagerScope nms(d_nodeManager);
Node a = d_nodeManager->mkVar(d_nodeManager->booleanType());
Node b = d_nodeManager->mkVar(d_nodeManager->booleanType());
- d_cnfStream->convertAndAssert(d_nodeManager->mkNode(kind::EQUAL, a, b), false,
- false, RULE_INVALID, Node::null());
+ d_cnfStream->convertAndAssert(
+ d_nodeManager->mkNode(kind::EQUAL, a, b), false, false);
TS_ASSERT(d_satSolver->addClauseCalled());
}
NodeManagerScope nms(d_nodeManager);
Node a = d_nodeManager->mkVar(d_nodeManager->booleanType());
Node b = d_nodeManager->mkVar(d_nodeManager->booleanType());
- d_cnfStream->convertAndAssert(d_nodeManager->mkNode(kind::IMPLIES, a, b),
- false, false, RULE_INVALID, Node::null());
+ d_cnfStream->convertAndAssert(
+ d_nodeManager->mkNode(kind::IMPLIES, a, b), false, false);
TS_ASSERT(d_satSolver->addClauseCalled());
}
- // ITEs should be removed before going to CNF
- // void testIte() {
- // NodeManagerScope nms(d_nodeManager);
- // d_cnfStream->convertAndAssert(
- // d_nodeManager->mkNode(
- // kind::EQUAL,
- // d_nodeManager->mkNode(
- // kind::ITE,
- // d_nodeManager->mkVar(d_nodeManager->booleanType()),
- // d_nodeManager->mkVar(d_nodeManager->integerType()),
- // d_nodeManager->mkVar(d_nodeManager->integerType())
- // ),
- // d_nodeManager->mkVar(d_nodeManager->integerType())
- // ), false, false, RULE_INVALID, Node::null());
- //
- //}
-
void testNot() {
NodeManagerScope nms(d_nodeManager);
Node a = d_nodeManager->mkVar(d_nodeManager->booleanType());
- d_cnfStream->convertAndAssert(d_nodeManager->mkNode(kind::NOT, a), false,
- false, RULE_INVALID, Node::null());
+ d_cnfStream->convertAndAssert(
+ d_nodeManager->mkNode(kind::NOT, a), false, false);
TS_ASSERT(d_satSolver->addClauseCalled());
}
Node a = d_nodeManager->mkVar(d_nodeManager->booleanType());
Node b = d_nodeManager->mkVar(d_nodeManager->booleanType());
Node c = d_nodeManager->mkVar(d_nodeManager->booleanType());
- d_cnfStream->convertAndAssert(d_nodeManager->mkNode(kind::OR, a, b, c),
- false, false, RULE_INVALID, Node::null());
+ d_cnfStream->convertAndAssert(
+ d_nodeManager->mkNode(kind::OR, a, b, c), false, false);
TS_ASSERT(d_satSolver->addClauseCalled());
}
NodeManagerScope nms(d_nodeManager);
Node a = d_nodeManager->mkVar(d_nodeManager->booleanType());
Node b = d_nodeManager->mkVar(d_nodeManager->booleanType());
- d_cnfStream->convertAndAssert(a, false, false, RULE_INVALID, Node::null());
+ d_cnfStream->convertAndAssert(a, false, false);
TS_ASSERT(d_satSolver->addClauseCalled());
d_satSolver->reset();
- d_cnfStream->convertAndAssert(b, false, false, RULE_INVALID, Node::null());
+ d_cnfStream->convertAndAssert(b, false, false);
TS_ASSERT(d_satSolver->addClauseCalled());
}
NodeManagerScope nms(d_nodeManager);
Node a = d_nodeManager->mkVar(d_nodeManager->booleanType());
Node b = d_nodeManager->mkVar(d_nodeManager->booleanType());
- d_cnfStream->convertAndAssert(d_nodeManager->mkNode(kind::XOR, a, b), false,
- false, RULE_INVALID, Node::null());
+ d_cnfStream->convertAndAssert(
+ d_nodeManager->mkNode(kind::XOR, a, b), false, false);
TS_ASSERT(d_satSolver->addClauseCalled());
}
#include "theory/theory_rewriter.h"
#include "theory/valuation.h"
#include "util/integer.h"
-#include "util/proof.h"
#include "util/rational.h"
using namespace CVC4;
using namespace std;
class FakeOutputChannel : public OutputChannel {
- void conflict(TNode n, std::unique_ptr<Proof> pf) override
- {
- Unimplemented();
- }
+ void conflict(TNode n) override { Unimplemented(); }
bool propagate(TNode n) override { Unimplemented(); }
LemmaStatus lemma(TNode n,
- ProofRule rule,
LemmaProperty p = LemmaProperty::NONE) override
{
Unimplemented();
#include "smt/smt_engine_scope.h"
#include "theory/theory.h"
#include "theory/theory_engine.h"
-#include "util/proof.h"
#include "util/resource_manager.h"
using namespace CVC4;
~TestOutputChannel() override {}
void safePoint(ResourceManager::Resource r) override {}
- void conflict(TNode n, std::unique_ptr<Proof> pf) override
- {
- push(CONFLICT, n);
- }
+ void conflict(TNode n) override { push(CONFLICT, n); }
bool propagate(TNode n) override {
push(PROPAGATE, n);
}
LemmaStatus lemma(TNode n,
- ProofRule rule,
LemmaProperty p = LemmaProperty::NONE) override
{
push(LEMMA, n);
void testOutputChannel() {
Node n = atom0.orNode(atom1);
- d_outputChannel.lemma(n, RULE_INVALID);
+ d_outputChannel.lemma(n);
d_outputChannel.split(atom0);
Node s = atom0.orNode(atom0.notNode());
TS_ASSERT_EQUALS(d_outputChannel.d_callHistory.size(), 2u);