/***************************************************************************
CryptoMiniSat -- Copyright (c) 2009 Mate Soos
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
****************************************************************************/
#include "Solver.h"
#include "VarReplacer.h"
#include "Subsumer.h"
#include "XorSubsumer.h"
#include "time_mem.h"
#include "DimacsParser.h"
#include "FailedLitSearcher.h"
#include "DataSync.h"
#include "SCCFinder.h"
#include
#include
#ifdef USE_GAUSS
#include "Gaussian.h"
#endif
#ifndef _MSC_VER
#include
#include
#endif
using namespace CMSat;
static const int space = 10;
bool Solver::dumpSortedLearnts(const std::string& fileName, const uint32_t maxSize)
{
FILE* outfile = fopen(fileName.c_str(), "w");
if (!outfile)
return false;
fprintf(outfile, "c \nc ---------\n");
fprintf(outfile, "c unitaries\n");
fprintf(outfile, "c ---------\n");
for (uint32_t i = 0, end = (trail_lim.size() > 0) ? trail_lim[0] : trail.size() ; i < end; i++) {
trail[i].printFull(outfile);
}
fprintf(outfile, "c conflicts %lu\n", (unsigned long)conflicts);
if (maxSize == 1) goto end;
fprintf(outfile, "c \nc ---------------------------------\n");
fprintf(outfile, "c learnt binary clauses (extracted from watchlists)\n");
fprintf(outfile, "c ---------------------------------\n");
dumpBinClauses(true, false, outfile);
fprintf(outfile, "c \nc ---------------------------------------\n");
fprintf(outfile, "c clauses representing 2-long XOR clauses\n");
fprintf(outfile, "c ---------------------------------------\n");
{
const vector& table = varReplacer->getReplaceTable();
for (Var var = 0; var != table.size(); var++) {
Lit lit = table[var];
if (lit.var() == var)
continue;
fprintf(outfile, "%s%d %d 0\n", (!lit.sign() ? "-" : ""), lit.var()+1, var+1);
fprintf(outfile, "%s%d -%d 0\n", (lit.sign() ? "-" : ""), lit.var()+1, var+1);
}
}
fprintf(outfile, "c \nc --------------------\n");
fprintf(outfile, "c clauses from learnts\n");
fprintf(outfile, "c --------------------\n");
if (lastSelectedRestartType == dynamic_restart)
std::sort(learnts.getData(), learnts.getData()+learnts.size(), reduceDB_ltGlucose());
else
std::sort(learnts.getData(), learnts.getData()+learnts.size(), reduceDB_ltMiniSat());
for (int i = learnts.size()-1; i >= 0 ; i--) {
if (learnts[i]->size() <= maxSize) {
learnts[i]->print(outfile);
}
}
end:
fclose(outfile);
return true;
}
void Solver::printStrangeBinLit(const Lit lit) const
{
const vec& ws = watches[(~lit).toInt()];
for (vec::const_iterator it2 = ws.getData(), end2 = ws.getDataEnd(); it2 != end2; it2++) {
if (it2->isBinary()) {
std::cout << "bin: " << lit << " , " << it2->getOtherLit() << " learnt : " << (it2->getLearnt()) << std::endl;
} else if (it2->isTriClause()) {
std::cout << "tri: " << lit << " , " << it2->getOtherLit() << " , " << (it2->getOtherLit2()) << std::endl;
} else if (it2->isClause()) {
std::cout << "cla:" << it2->getNormOffset() << std::endl;
} else {
assert(it2->isXorClause());
std::cout << "xor:" << it2->getXorOffset() << std::endl;
}
}
}
uint32_t Solver::countNumBinClauses(const bool alsoLearnt, const bool alsoNonLearnt) const
{
uint32_t num = 0;
uint32_t wsLit = 0;
for (const vec *it = watches.getData(), *end = watches.getDataEnd(); it != end; it++, wsLit++) {
const vec& ws = *it;
for (vec::const_iterator it2 = ws.getData(), end2 = ws.getDataEnd(); it2 != end2; it2++) {
if (it2->isBinary()) {
if (it2->getLearnt()) num += alsoLearnt;
else num+= alsoNonLearnt;
}
}
}
assert(num % 2 == 0);
return num/2;
}
void Solver::dumpBinClauses(const bool alsoLearnt, const bool alsoNonLearnt, FILE* outfile) const
{
uint32_t wsLit = 0;
for (const vec *it = watches.getData(), *end = watches.getDataEnd(); it != end; it++, wsLit++) {
Lit lit = ~Lit::toLit(wsLit);
const vec& ws = *it;
for (vec::const_iterator it2 = ws.getData(), end2 = ws.getDataEnd(); it2 != end2; it2++) {
if (it2->isBinary() && lit.toInt() < it2->getOtherLit().toInt()) {
bool toDump = false;
if (it2->getLearnt() && alsoLearnt) toDump = true;
if (!it2->getLearnt() && alsoNonLearnt) toDump = true;
if (toDump) it2->dump(outfile, lit);
}
}
}
}
uint32_t Solver::getBinWatchSize(const bool alsoLearnt, const Lit lit)
{
uint32_t num = 0;
const vec& ws = watches[lit.toInt()];
for (vec::const_iterator it2 = ws.getData(), end2 = ws.getDataEnd(); it2 != end2; it2++) {
if (it2->isBinary() && (alsoLearnt || !it2->getLearnt())) {
num++;
}
}
return num;
}
void Solver::printBinClause(const Lit litP1, const Lit litP2, FILE* outfile) const
{
if (value(litP1) == l_True) {
litP1.printFull(outfile);
} else if (value(litP1) == l_False) {
litP2.printFull(outfile);
} else if (value(litP2) == l_True) {
litP2.printFull(outfile);
} else if (value(litP2) == l_False) {
litP1.printFull(outfile);
} else {
litP1.print(outfile);
litP2.printFull(outfile);
}
}
bool Solver::dumpOrigClauses(const std::string& fileName) const
{
FILE* outfile;
if (fileName != std::string("stdout")) {
outfile = fopen(fileName.c_str(), "w");
if (!outfile)
return false;
} else {
outfile = stdout;
}
uint32_t numClauses = 0;
//unitary clauses
for (uint32_t i = 0, end = (trail_lim.size() > 0) ? trail_lim[0] : trail.size() ; i < end; i++)
numClauses++;
//binary XOR clauses
const vector& table = varReplacer->getReplaceTable();
for (Var var = 0; var != table.size(); var++) {
Lit lit = table[var];
if (lit.var() == var)
continue;
numClauses += 2;
}
//binary normal clauses
numClauses += countNumBinClauses(false, true);
//normal clauses
numClauses += clauses.size();
//xor clauses
numClauses += xorclauses.size();
//previously eliminated clauses
const map > >& elimedOutVar = subsumer->getElimedOutVar();
for (map > >::const_iterator it = elimedOutVar.begin(); it != elimedOutVar.end(); it++) {
const vector >& cs = it->second;
numClauses += cs.size();
}
const map > >& elimedOutVarBin = subsumer->getElimedOutVarBin();
for (map > >::const_iterator it = elimedOutVarBin.begin(); it != elimedOutVarBin.end(); it++) {
numClauses += it->second.size();
}
const map >& xorElimedOutVar = xorSubsumer->getElimedOutVar();
for (map >::const_iterator it = xorElimedOutVar.begin(); it != xorElimedOutVar.end(); it++) {
const vector& cs = it->second;
numClauses += cs.size();
}
fprintf(outfile, "p cnf %d %d\n", nVars(), numClauses);
////////////////////////////////////////////////////////////////////
fprintf(outfile, "c \nc ---------\n");
fprintf(outfile, "c unitaries\n");
fprintf(outfile, "c ---------\n");
for (uint32_t i = 0, end = (trail_lim.size() > 0) ? trail_lim[0] : trail.size() ; i < end; i++) {
trail[i].printFull(outfile);
}
fprintf(outfile, "c \nc ---------------------------------------\n");
fprintf(outfile, "c clauses representing 2-long XOR clauses\n");
fprintf(outfile, "c ---------------------------------------\n");
for (Var var = 0; var != table.size(); var++) {
Lit lit = table[var];
if (lit.var() == var)
continue;
Lit litP1 = ~lit;
Lit litP2 = Lit(var, false);
printBinClause(litP1, litP2, outfile);
printBinClause(~litP1, ~litP2, outfile);
}
fprintf(outfile, "c \nc ------------\n");
fprintf(outfile, "c binary clauses\n");
fprintf(outfile, "c ---------------\n");
dumpBinClauses(false, true, outfile);
fprintf(outfile, "c \nc ------------\n");
fprintf(outfile, "c normal clauses\n");
fprintf(outfile, "c ---------------\n");
for (Clause *const *i = clauses.getData(); i != clauses.getDataEnd(); i++) {
assert(!(*i)->learnt());
(*i)->print(outfile);
}
fprintf(outfile, "c \nc ------------\n");
fprintf(outfile, "c xor clauses\n");
fprintf(outfile, "c ---------------\n");
for (XorClause *const *i = xorclauses.getData(); i != xorclauses.getDataEnd(); i++) {
assert(!(*i)->learnt());
(*i)->print(outfile);
}
fprintf(outfile, "c -------------------------------\n");
fprintf(outfile, "c previously eliminated variables\n");
fprintf(outfile, "c -------------------------------\n");
for (map > >::const_iterator it = elimedOutVar.begin(); it != elimedOutVar.end(); it++) {
fprintf(outfile, "c ########### cls for eliminated var %d ### start\n", it->first + 1);
const vector >& cs = it->second;
for (vector >::const_iterator it2 = cs.begin(); it2 != cs.end(); it2++) {
printClause(outfile, *it2);
}
fprintf(outfile, "c ########### cls for eliminated var %d ### finish\n", it->first + 1);
}
for (map > >::const_iterator it = elimedOutVarBin.begin(); it != elimedOutVarBin.end(); it++) {
for (uint32_t i = 0; i < it->second.size(); i++) {
it->second[i].first.print(outfile);
it->second[i].second.printFull(outfile);
}
}
fprintf(outfile, "c -------------------------------\n");
fprintf(outfile, "c previously xor-eliminated variables\n");
fprintf(outfile, "c -------------------------------\n");
for (map >::const_iterator it = xorElimedOutVar.begin(); it != xorElimedOutVar.end(); it++) {
for (vector::const_iterator it2 = it->second.begin(), end2 = it->second.end(); it2 != end2; it2++) {
it2->plainPrint(outfile);
}
}
if (fileName != "stdout") fclose(outfile);
return true;
}
vector Solver::get_unitary_learnts() const
{
vector unitaries;
if (decisionLevel() > 0) {
for (uint32_t i = 0; i != trail_lim[0]; i++) {
unitaries.push_back(trail[i]);
}
}
return unitaries;
}
const vec& Solver::get_learnts() const
{
return learnts;
}
const vec& Solver::get_sorted_learnts()
{
if (lastSelectedRestartType == dynamic_restart)
std::sort(learnts.getData(), learnts.getData()+learnts.size(), reduceDB_ltGlucose());
else
std::sort(learnts.getData(), learnts.getData()+learnts.size(), reduceDB_ltMiniSat());
return learnts;
}
uint32_t Solver::getNumElimSubsume() const
{
return subsumer->getNumElimed();
}
uint32_t Solver::getNumElimXorSubsume() const
{
return xorSubsumer->getNumElimed();
}
uint32_t Solver::getNumXorTrees() const
{
return varReplacer->getNumTrees();
}
uint32_t Solver::getNumXorTreesCrownSize() const
{
return varReplacer->getNumReplacedVars();
}
double Solver::getTotalTimeSubsumer() const
{
return subsumer->getTotalTime();
}
double Solver::getTotalTimeFailedLitSearcher() const
{
return failedLitSearcher->getTotalTime();
}
double Solver::getTotalTimeXorSubsumer() const
{
return xorSubsumer->getTotalTime();
}
double Solver::getTotalTimeSCC() const
{
return sCCFinder->getTotalTime();
}
void Solver::printStatHeader() const
{
if (conf.verbosity >= 2) {
std::cout << "c "
<< "========================================================================================="
<< std::endl;
std::cout << "c"
<< " types(t): F = full restart, N = normal restart" << std::endl;
std::cout << "c"
<< " types(t): S = simplification begin/end, E = solution found" << std::endl;
std::cout << "c"
<< " restart types(rt): st = static, dy = dynamic" << std::endl;
std::cout << "c "
<< std::setw(2) << "t"
<< std::setw(3) << "rt"
<< std::setw(6) << "Rest"
<< std::setw(space) << "Confl"
<< std::setw(space) << "Vars"
<< std::setw(space) << "NormCls"
<< std::setw(space) << "XorCls"
<< std::setw(space) << "BinCls"
<< std::setw(space) << "Learnts"
<< std::setw(space) << "ClLits"
<< std::setw(space) << "LtLits"
<< std::setw(space) << "LGlueHist"
<< std::setw(space) << "SGlueHist"
<< std::endl;
}
}
void Solver::printRestartStat(const char* type)
{
if (conf.verbosity >= 2) {
//printf("c | %9d | %7d %8d %8d | %8d %8d %6.0f |", (int)conflicts, (int)order_heap.size(), (int)(nClauses()-nbBin), (int)clauses_literals, (int)(nbclausesbeforereduce*curRestart+nbCompensateSubsumer), (int)(nLearnts()+nbBin), (double)learnts_literals/(double)(nLearnts()+nbBin));
std::cout << "c "
<< std::setw(2) << type
<< std::setw(3) << ((restartType == static_restart) ? "st" : "dy")
<< std::setw(6) << starts
<< std::setw(space) << conflicts
<< std::setw(space) << order_heap.size()
<< std::setw(space) << clauses.size()
<< std::setw(space) << xorclauses.size()
<< std::setw(space) << numBins
<< std::setw(space) << learnts.size()
<< std::setw(space) << clauses_literals
<< std::setw(space) << learnts_literals;
if (glueHistory.getTotalNumeElems() > 0) {
std::cout << std::setw(space) << std::fixed << std::setprecision(2) << glueHistory.getAvgAllDouble();
} else {
std::cout << std::setw(space) << "no data";
}
if (glueHistory.isvalid()) {
std::cout << std::setw(space) << std::fixed << std::setprecision(2) << glueHistory.getAvgDouble();
} else {
std::cout << std::setw(space) << "no data";
}
#ifdef RANDOM_LOOKAROUND_SEARCHSPACE
if (conf.doPrintAvgBranch) {
if (avgBranchDepth.isvalid())
std::cout << std::setw(space) << avgBranchDepth.getAvgUInt();
else
std::cout << std::setw(space) << "no data";
}
#endif //RANDOM_LOOKAROUND_SEARCHSPACE
#ifdef USE_GAUSS
print_gauss_sum_stats();
#endif //USE_GAUSS
std::cout << std::endl;
}
}
void Solver::printEndSearchStat()
{
if (conf.verbosity >= 1) {
printRestartStat("E");
}
}
#ifdef USE_GAUSS
void Solver::print_gauss_sum_stats()
{
if (gauss_matrixes.size() == 0 && conf.verbosity >= 2) {
std::cout << " --";
return;
}
uint32_t called = 0;
uint32_t useful_prop = 0;
uint32_t useful_confl = 0;
uint32_t disabled = 0;
for (vector::const_iterator gauss = gauss_matrixes.begin(), end= gauss_matrixes.end(); gauss != end; gauss++) {
disabled += (*gauss)->get_disabled();
called += (*gauss)->get_called();
useful_prop += (*gauss)->get_useful_prop();
useful_confl += (*gauss)->get_useful_confl();
sum_gauss_unit_truths += (*gauss)->get_unit_truths();
//gauss->print_stats();
//gauss->print_matrix_stats();
}
sum_gauss_called += called;
sum_gauss_confl += useful_confl;
sum_gauss_prop += useful_prop;
if (conf.verbosity >= 2) {
if (called == 0) {
std::cout << " --";
} else {
std::cout << " "
<< std::fixed << std::setprecision(1) << std::setw(5)
<< ((double)useful_prop/(double)called*100.0) << "% "
<< std::fixed << std::setprecision(1) << std::setw(5)
<< ((double)useful_confl/(double)called*100.0) << "% "
<< std::fixed << std::setprecision(1) << std::setw(5)
<< (100.0-(double)disabled/(double)gauss_matrixes.size()*100.0) << "%";
}
}
}
#endif //USE_GAUSS
/**
@brief Sorts the watchlists' clauses as: binary, tertiary, normal, xor
*/
void Solver::sortWatched()
{
#ifdef VERBOSE_DEBUG
std::cout << "Sorting watchlists:" << std::endl;
#endif
double myTime = cpuTime();
for (vec *i = watches.getData(), *end = watches.getDataEnd(); i != end; i++) {
if (i->size() == 0) continue;
#ifdef VERBOSE_DEBUG
vec& ws = *i;
std::cout << "Before sorting:" << std::endl;
for (uint32_t i2 = 0; i2 < ws.size(); i2++) {
if (ws[i2].isBinary()) std::cout << "Binary,";
if (ws[i2].isTriClause()) std::cout << "Tri,";
if (ws[i2].isClause()) std::cout << "Normal,";
if (ws[i2].isXorClause()) std::cout << "Xor,";
}
std::cout << std::endl;
#endif //VERBOSE_DEBUG
std::sort(i->getData(), i->getDataEnd(), WatchedSorter());
#ifdef VERBOSE_DEBUG
std::cout << "After sorting:" << std::endl;
for (uint32_t i2 = 0; i2 < ws.size(); i2++) {
if (ws[i2].isBinary()) std::cout << "Binary,";
if (ws[i2].isTriClause()) std::cout << "Tri,";
if (ws[i2].isClause()) std::cout << "Normal,";
if (ws[i2].isXorClause()) std::cout << "Xor,";
}
std::cout << std::endl;
#endif //VERBOSE_DEBUG
}
if (conf.verbosity >= 3) {
std::cout << "c watched "
<< "sorting time: " << cpuTime() - myTime
<< std::endl;
}
}
void Solver::addSymmBreakClauses()
{
if (xorclauses.size() > 0) {
std::cout << "c xor clauses present -> no saucy" << std::endl;
return;
}
double myTime = cpuTime();
std::cout << "c Doing saucy" << std::endl;
dumpOrigClauses("origProblem.cnf");
int rvalue;
rvalue= system("grep -v \"^c\" origProblem.cnf > origProblem2.cnf");
if (rvalue >= 2) { // unsuccessful grep in POSIX standard
std::cout << "c impossible to complete saucy" << std::endl;
return;
}
rvalue= system("python saucyReader.py origProblem2.cnf > output");
if (rvalue != 0) { // unsuccessful saucyReader.py
std::cout << "c impossible to complete saucy" << std::endl;
return;
}
DimacsParser parser(this, false, false, false, true);
#ifdef DISABLE_ZLIB
FILE * in = fopen("output", "rb");
#else
gzFile in = gzopen("output", "rb");
#endif // DISABLE_ZLIB
parser.parse_DIMACS(in);
#ifdef DISABLE_ZLIB
fclose(in);
#else
gzclose(in);
#endif // DISABLE_ZLIB
std::cout << "c Finished saucy, time: " << (cpuTime() - myTime) << std::endl;
}
/**
@brief Pretty-prints a literal
*/
void Solver::printLit(const Lit l) const
{
printf("%s%d:%c", l.sign() ? "-" : "", l.var()+1, value(l) == l_True ? '1' : (value(l) == l_False ? '0' : 'X'));
}
/**
@brief Sets that we need a CNF file that documents all commands
newVar() and addClause(), addXorClause() commands are logged to this CNF
file and then can be re-read with special arguments to the main program. This
can help simulate a segfaulting library-call
*/
bool Solver::needLibraryCNFFile(const std::string& fileName)
{
libraryCNFFile = fopen(fileName.c_str(), "w");
return libraryCNFFile != NULL;
}
template
void Solver::printStatsLine(std::string left, T value, T2 value2, std::string extra)
{
std::cout << std::fixed << std::left << std::setw(27) << left << ": " << std::setw(11) << std::setprecision(2) << value << " (" << std::left << std::setw(9) << std::setprecision(2) << value2 << " " << extra << ")" << std::endl;
}
template
void Solver::printStatsLine(std::string left, T value, std::string extra)
{
std::cout << std::fixed << std::left << std::setw(27) << left << ": " << std::setw(11) << std::setprecision(2) << value << extra << std::endl;
}
/**
@brief prints the statistics line at the end of solving
Prints all sorts of statistics, like number of restarts, time spent in
SatELite-type simplification, number of unit claues found, etc.
*/
void Solver::printStats()
{
double cpu_time = cpuTime();
uint64_t mem_used = memUsed();
int numThreads = omp_get_num_threads();
if (numThreads > 1) {
std::cout << "c Following stats are for *FIRST FINISHED THREAD ONLY*" << std::endl;
#if !defined(_MSC_VER) && !defined(RUSAGE_THREAD)
std::cout << "c There is no platform-independent way to measure time per thread" << std::endl;
std::cout << "c All times indicated are sum of ALL threads" << std::endl;
std::cout << "c Use a utilty provided by your platform to get total thread time, etc." << std::endl;
#endif
}
printStatsLine("c num threads" , numThreads);
//Restarts stats
printStatsLine("c restarts", starts);
printStatsLine("c dynamic restarts", dynStarts);
printStatsLine("c static restarts", staticStarts);
printStatsLine("c full restarts", fullStarts);
printStatsLine("c total simplify time", totalSimplifyTime);
//Learnts stats
printStatsLine("c learnts DL2", nbGlue2);
printStatsLine("c learnts size 2", numNewBin);
printStatsLine("c learnts size 1", get_unitary_learnts_num(), (double)get_unitary_learnts_num()/(double)nVars()*100.0, "% of vars");
printStatsLine("c filedLit time", getTotalTimeFailedLitSearcher(), getTotalTimeFailedLitSearcher()/cpu_time*100.0, "% time");
//Subsumer stats
printStatsLine("c v-elim SatELite", getNumElimSubsume(), (double)getNumElimSubsume()/(double)nVars()*100.0, "% vars");
printStatsLine("c SatELite time", getTotalTimeSubsumer(), getTotalTimeSubsumer()/cpu_time*100.0, "% time");
//XorSubsumer stats
printStatsLine("c v-elim xor", getNumElimXorSubsume(), (double)getNumElimXorSubsume()/(double)nVars()*100.0, "% vars");
printStatsLine("c xor elim time", getTotalTimeXorSubsumer(), getTotalTimeXorSubsumer()/cpu_time*100.0, "% time");
//VarReplacer stats
printStatsLine("c num binary xor trees", getNumXorTrees());
printStatsLine("c binxor trees' crown", getNumXorTreesCrownSize(), (double)getNumXorTreesCrownSize()/(double)getNumXorTrees(), "leafs/tree");
printStatsLine("c bin xor find time", getTotalTimeSCC());
//OTF clause improvement stats
printStatsLine("c OTF clause improved", improvedClauseNo, (double)improvedClauseNo/(double)conflicts, "clauses/conflict");
printStatsLine("c OTF impr. size diff", improvedClauseSize, (double)improvedClauseSize/(double)improvedClauseNo, " lits/clause");
//Clause-shrinking through watchlists
printStatsLine("c OTF cl watch-shrink", numShrinkedClause, (double)numShrinkedClause/(double)conflicts, "clauses/conflict");
printStatsLine("c OTF cl watch-sh-lit", numShrinkedClauseLits, (double)numShrinkedClauseLits/(double)numShrinkedClause, " lits/clause");
printStatsLine("c tried to recurMin cls", moreRecurMinLDo, (double)moreRecurMinLDo/(double)conflicts*100.0, " % of conflicts");
printStatsLine("c updated cache", updateTransCache, updateTransCache/(double)moreRecurMinLDo, " lits/tried recurMin");
//Multi-threading
if (numThreads > 1) {
printStatsLine("c unit cls received", dataSync->getRecvUnitData(), (double)dataSync->getRecvUnitData()/(double)get_unitary_learnts_num()*100.0, "% of units");
printStatsLine("c unit cls sent", dataSync->getSentUnitData(), (double)dataSync->getSentUnitData()/(double)get_unitary_learnts_num()*100.0, "% of units");
printStatsLine("c bin cls received", dataSync->getRecvBinData());
printStatsLine("c bin cls sent", dataSync->getSentBinData());
}
#ifdef USE_GAUSS
if (gaussconfig.decision_until > 0) {
std::cout << "c " << std::endl;
printStatsLine("c gauss unit truths ", get_sum_gauss_unit_truths());
printStatsLine("c gauss called", get_sum_gauss_called());
printStatsLine("c gauss conflicts ", get_sum_gauss_confl(), (double)get_sum_gauss_confl() / (double)get_sum_gauss_called() * 100.0, " %");
printStatsLine("c gauss propagations ", get_sum_gauss_prop(), (double)get_sum_gauss_prop() / (double)get_sum_gauss_called() * 100.0, " %");
printStatsLine("c gauss useful", ((double)get_sum_gauss_prop() + (double)get_sum_gauss_confl())/ (double)get_sum_gauss_called() * 100.0, " %");
std::cout << "c " << std::endl;
}
#endif
printStatsLine("c clauses over max glue", nbClOverMaxGlue, (double)nbClOverMaxGlue/(double)conflicts*100.0, "% of all clauses");
//Search stats
printStatsLine("c conflicts", conflicts, (double)conflicts/cpu_time, "/ sec");
printStatsLine("c decisions", decisions, (double)rnd_decisions*100.0/(double)decisions, "% random");
printStatsLine("c bogo-props", propagations, (double)propagations/cpu_time, "/ sec");
printStatsLine("c conflict literals", tot_literals, (double)(max_literals - tot_literals)*100.0/ (double)max_literals, "% deleted");
//General stats
printStatsLine("c Memory used", (double)mem_used / 1048576.0, " MB");
if (numThreads > 1) {
#if !defined(_MSC_VER) && defined(RUSAGE_THREAD)
printStatsLine("c single-thread CPU time", cpu_time, " s");
printStatsLine("c all-threads sum CPU time", cpuTimeTotal(), " s");
#else
printStatsLine("c all-threads sum CPU time", cpu_time, " s");
#endif
} else {
printStatsLine("c CPU time", cpu_time, " s");
}
}