diff options
author | Alex Ozdemir <aozdemir@hmc.edu> | 2019-06-05 12:16:46 -0700 |
---|---|---|
committer | Andres Noetzli <noetzli@stanford.edu> | 2019-06-05 12:16:46 -0700 |
commit | 9af5e9653582a18b1871dfc3774ab50dd24463ce (patch) | |
tree | 9bbe5cd5708dbd3475626cabd4d2c9711f0ac133 /src/proof/dimacs.cpp | |
parent | c587235d29d2e3e1cd52a9f76dde8f58c89ae37e (diff) |
DRAT-Optimization (#2971)
This commit enables DRAT-optimization, which consists of two sub-processes:
1. removing unnecessary instructions from DRAT-proofs and
2. not proving clauses which are not needed by DRAT proofs.
These changes have the effect of dramatically shortening some some bit-vector proofs. Specifically, proofs using lemmas in the ER, DRAT, and LRAT formats, since proofs in any of these formats are derived from a (now optimized!) DRAT proof produced by CryptoMiniSat. What follows is a description of the main parts of this PR:
## DRAT Optimization
The DRAT-optimization is done by `drat-trim`, which is bundled with `drat2er`. The (new) function `ClausalBitVectorProof::optimizeDratProof` is our interface to the optimization machinery, and most of the new logic in this PR is in that function.
## CNF Representation
The ability to not prove unused clauses requires a slight architectural change as well. In particular, we need to be able to describe **which** subset of the original clause set actually needs to be proved. To facilitate this, when the clause set for CryptoMiniSat is first formed it is represented as a (a) map from clause indices to clauses and (b) a list of indices. Then, when the CNF is optimized, we temporarily store a new list of the clauses in the optimized formula. This change in representation requires a number of small tweaks throughout the code.
## Small Fixes to Signatures
When we decided to check and accept two different kinds of DRAT, some of our DRAT-checking broke. In particular, when supporting one kind of DRAT, it is okay to `fail` (crash) when a proof fails to check. If you're supporting two kinds of DRAT, crashing in response to the first checker rejecting the proof denies the second checker an opportunity to check the proof. This PR tweaks the signatures slightly (and soundly!) to do something else instead of `fail`ing.
Diffstat (limited to 'src/proof/dimacs.cpp')
-rw-r--r-- | src/proof/dimacs.cpp | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/src/proof/dimacs.cpp b/src/proof/dimacs.cpp new file mode 100644 index 000000000..cced98660 --- /dev/null +++ b/src/proof/dimacs.cpp @@ -0,0 +1,120 @@ +/********************* */ +/*! \file dimacs.cpp + ** \verbatim + ** Top contributors (to current version): + ** Alex Ozdemir + ** This file is part of the CVC4 project. + ** Copyright (c) 2009-2019 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/cvc4_assert.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 |