summaryrefslogtreecommitdiff
path: root/cryptominisat5/cryptominisat-5.6.3/src/sccfinder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cryptominisat5/cryptominisat-5.6.3/src/sccfinder.cpp')
-rw-r--r--cryptominisat5/cryptominisat-5.6.3/src/sccfinder.cpp230
1 files changed, 230 insertions, 0 deletions
diff --git a/cryptominisat5/cryptominisat-5.6.3/src/sccfinder.cpp b/cryptominisat5/cryptominisat-5.6.3/src/sccfinder.cpp
new file mode 100644
index 000000000..5d000bd89
--- /dev/null
+++ b/cryptominisat5/cryptominisat-5.6.3/src/sccfinder.cpp
@@ -0,0 +1,230 @@
+/******************************************
+Copyright (c) 2016, Mate Soos
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+***********************************************/
+
+#include <iostream>
+#include <vector>
+#include <iomanip>
+
+#include "solvertypes.h"
+#include "sccfinder.h"
+#include "varreplacer.h"
+#include "time_mem.h"
+#include "solver.h"
+#include "sqlstats.h"
+
+using namespace CMSat;
+using std::cout;
+using std::endl;
+
+SCCFinder::SCCFinder(Solver* _solver) :
+ globalIndex(0)
+ , solver(_solver)
+{}
+
+bool SCCFinder::performSCC(uint64_t* bogoprops_given)
+{
+ assert(binxors.empty());
+ runStats.clear();
+ runStats.numCalls = 1;
+ depth_warning_issued = false;
+ const double myTime = cpuTime();
+
+ globalIndex = 0;
+ index.clear();
+ index.resize(solver->nVars()*2, std::numeric_limits<uint32_t>::max());
+ lowlink.clear();
+ lowlink.resize(solver->nVars()*2, std::numeric_limits<uint32_t>::max());
+ stackIndicator.clear();
+ stackIndicator.resize(solver->nVars()*2, false);
+ assert(stack.empty());
+
+ depth = 0;
+ for (uint32_t vertex = 0; vertex < solver->nVars()*2; vertex++) {
+ //Start a DFS at each node we haven't visited yet
+ const uint32_t v = vertex>>1;
+ if (solver->value(v) != l_Undef) {
+ continue;
+ }
+ assert(depth == 0);
+ if (index[vertex] == std::numeric_limits<uint32_t>::max()) {
+ tarjan(vertex);
+ depth--;
+ assert(stack.empty());
+ }
+ }
+
+ //Update & print stats
+ runStats.cpu_time = cpuTime() - myTime;
+ runStats.foundXorsNew = binxors.size();
+ if (solver->conf.verbosity) {
+ if (solver->conf.verbosity >= 3)
+ runStats.print();
+ else
+ runStats.print_short(solver);
+ }
+ globalStats += runStats;
+
+ if (bogoprops_given) {
+ *bogoprops_given += runStats.bogoprops;
+ }
+
+ return solver->okay();
+}
+
+void SCCFinder::tarjan(const uint32_t vertex)
+{
+ depth++;
+ if (depth >= (uint32_t)solver->conf.max_scc_depth) {
+ if (solver->conf.verbosity && !depth_warning_issued) {
+ depth_warning_issued = true;
+ cout << "c [scc] WARNING: reached maximum depth of " << solver->conf.max_scc_depth << endl;
+ }
+ return;
+ }
+
+ const Lit vertLit = Lit::toLit(vertex);
+ if (solver->varData[vertLit.var()].removed != Removed::none) {
+ return;
+ }
+
+ runStats.bogoprops += 1;
+ index[vertex] = globalIndex; // Set the depth index for v
+ lowlink[vertex] = globalIndex;
+ globalIndex++;
+ stack.push(vertex); // Push v on the stack
+ stackIndicator[vertex] = true;
+
+ vector<LitExtra>* transCache = NULL;
+ if (solver->conf.doCache
+ && solver->conf.doExtendedSCC
+ && (!(solver->drat->enabled() || solver->conf.simulate_drat) ||
+ solver->conf.otfHyperbin)
+ ) {
+ transCache = &(solver->implCache[~vertLit].lits);
+ __builtin_prefetch(transCache->data());
+ }
+
+ //Go through the watch
+ watch_subarray_const ws = solver->watches[~vertLit];
+ runStats.bogoprops += ws.size()/4;
+ for (const Watched& w: ws) {
+ //Only binary clauses matter
+ if (!w.isBin())
+ continue;
+
+ const Lit lit = w.lit2();
+ if (solver->value(lit) != l_Undef) {
+ continue;
+ }
+ doit(lit, vertex);
+ }
+
+ if (transCache) {
+ runStats.bogoprops += transCache->size()/4;
+ for (const LitExtra& le: *transCache) {
+ Lit lit = le.getLit();
+ if (solver->value(lit) != l_Undef) {
+ continue;
+ }
+ if (lit != ~vertLit) {
+ doit(lit, vertex);
+ }
+ }
+ }
+
+ // Is v the root of an SCC?
+ if (lowlink[vertex] == index[vertex]) {
+ uint32_t vprime;
+ tmp.clear();
+ do {
+ assert(!stack.empty());
+ vprime = stack.top();
+ stack.pop();
+ stackIndicator[vprime] = false;
+ tmp.push_back(vprime);
+ } while (vprime != vertex);
+ if (tmp.size() >= 2) {
+ runStats.bogoprops += 3;
+ add_bin_xor_in_tmp();
+ }
+ }
+}
+
+void SCCFinder::add_bin_xor_in_tmp()
+{
+ for (uint32_t i = 1; i < tmp.size(); i++) {
+ bool rhs = Lit::toLit(tmp[0]).sign()
+ ^ Lit::toLit(tmp[i]).sign();
+
+ BinaryXor binxor(Lit::toLit(tmp[0]).var(), Lit::toLit(tmp[i]).var(), rhs);
+ binxors.insert(binxor);
+
+ //Both are UNDEF, so this is a proper binary XOR
+ if (solver->value(binxor.vars[0]) == l_Undef
+ && solver->value(binxor.vars[1]) == l_Undef
+ ) {
+ runStats.foundXors++;
+ #ifdef VERBOSE_DEBUG
+ cout << "SCC says: "
+ << binxor.vars[0] +1
+ << " XOR "
+ << binxor.vars[1] +1
+ << " = " << binxor.rhs
+ << endl;
+ #endif
+ }
+ }
+}
+
+void SCCFinder::Stats::print_short(Solver* solver) const
+{
+ cout
+ << "c [scc]"
+ << " new: " << foundXorsNew
+ << " BP " << bogoprops/(1000*1000) << "M";
+ if (solver) {
+ cout << solver->conf.print_times(cpu_time);
+ } else {
+ cout << " T: " << std::setprecision(2) << std::fixed << cpu_time;
+ }
+ cout << endl;
+
+ if (solver && solver->sqlStats) {
+ solver->sqlStats->time_passed_min(
+ solver
+ , "scc"
+ , cpu_time
+ );
+ }
+}
+
+size_t SCCFinder::mem_used() const
+{
+ size_t mem = 0;
+ mem += index.capacity()*sizeof(uint32_t);
+ mem += lowlink.capacity()*sizeof(uint32_t);
+ mem += stack.size()*sizeof(uint32_t); //TODO under-estimates
+ mem += stackIndicator.capacity()*sizeof(char);
+ mem += tmp.capacity()*sizeof(uint32_t);
+
+ return mem;
+}
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback