summaryrefslogtreecommitdiff
path: root/cryptominisat5/cryptominisat-5.6.3/src/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cryptominisat5/cryptominisat-5.6.3/src/main.cpp')
-rw-r--r--cryptominisat5/cryptominisat-5.6.3/src/main.cpp1339
1 files changed, 1339 insertions, 0 deletions
diff --git a/cryptominisat5/cryptominisat-5.6.3/src/main.cpp b/cryptominisat5/cryptominisat-5.6.3/src/main.cpp
new file mode 100644
index 000000000..5c1715880
--- /dev/null
+++ b/cryptominisat5/cryptominisat-5.6.3/src/main.cpp
@@ -0,0 +1,1339 @@
+/*
+Copyright (c) 2010-2015 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.
+*/
+
+#if defined(__GNUC__) && defined(__linux__)
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <fenv.h>
+#endif
+
+#include <ctime>
+#include <cstring>
+#include <errno.h>
+#include <string.h>
+#include <sstream>
+#include <iostream>
+#include <iomanip>
+#include <map>
+#include <set>
+#include <fstream>
+#include <sys/stat.h>
+#include <string.h>
+#include <list>
+#include <array>
+#include <thread>
+
+#include "main.h"
+#include "main_common.h"
+#include "time_mem.h"
+#include "dimacsparser.h"
+#include "cryptominisat5/cryptominisat.h"
+#include "signalcode.h"
+
+#include <boost/lexical_cast.hpp>
+using namespace CMSat;
+using boost::lexical_cast;
+
+using std::cout;
+using std::cerr;
+using std::endl;
+using boost::lexical_cast;
+using std::list;
+using std::map;
+
+struct WrongParam
+{
+ WrongParam(string _param, string _msg) :
+ param(_param)
+ , msg(_msg)
+ {}
+
+ const string& getMsg() const
+ {
+ return msg;
+ }
+
+ const string& getParam() const
+ {
+ return param;
+ }
+
+ string param;
+ string msg;
+};
+
+bool fileExists(const string& filename)
+{
+ struct stat buf;
+ if (stat(filename.c_str(), &buf) != -1)
+ {
+ return true;
+ }
+ return false;
+}
+
+
+Main::Main(int _argc, char** _argv) :
+ argc(_argc)
+ , argv(_argv)
+ , fileNamePresent (false)
+{
+}
+
+void Main::readInAFile(SATSolver* solver2, const string& filename)
+{
+ solver2->add_sql_tag("filename", filename);
+ if (conf.verbosity) {
+ cout << "c Reading file '" << filename << "'" << endl;
+ }
+ #ifndef USE_ZLIB
+ FILE * in = fopen(filename.c_str(), "rb");
+ DimacsParser<StreamBuffer<FILE*, FN> > parser(solver2, &debugLib, conf.verbosity);
+ #else
+ gzFile in = gzopen(filename.c_str(), "rb");
+ DimacsParser<StreamBuffer<gzFile, GZ> > parser(solver2, &debugLib, conf.verbosity);
+ #endif
+
+ if (in == NULL) {
+ std::cerr
+ << "ERROR! Could not open file '"
+ << filename
+ << "' for reading: " << strerror(errno) << endl;
+
+ std::exit(1);
+ }
+
+ bool strict_header = conf.preprocess;
+ if (!parser.parse_DIMACS(in, strict_header)) {
+ exit(-1);
+ }
+
+ if (!independent_vars_str.empty() && !parser.independent_vars.empty()) {
+ cerr << "ERROR! Independent vars set in console but also in CNF." << endl;
+ exit(-1);
+ }
+
+ if (!independent_vars_str.empty()) {
+ assert(independent_vars.empty());
+
+ std::stringstream ss(independent_vars_str);
+ uint32_t i;
+ while (ss >> i)
+ {
+ const uint32_t var = i-1;
+ independent_vars.push_back(var);
+
+ if (ss.peek() == ',' || ss.peek() == ' ')
+ ss.ignore();
+ }
+ } else {
+ independent_vars.swap(parser.independent_vars);
+ }
+
+ if (independent_vars.empty()) {
+ if (only_indep_solution) {
+ cout << "ERROR: only independent vars are requested in the solution, but no independent vars have been set!" << endl;
+ exit(-1);
+ }
+ } else {
+ solver2->set_independent_vars(&independent_vars);
+ cout << "c Independent vars set: ";
+ for(size_t i = 0; i < independent_vars.size(); i++) {
+ const uint32_t v = independent_vars[i];
+ cout << v+1;
+ if (i+1 != independent_vars.size())
+ cout << ",";
+ }
+ cout << endl;
+ }
+ call_after_parse();
+
+ #ifndef USE_ZLIB
+ fclose(in);
+ #else
+ gzclose(in);
+ #endif
+}
+
+void Main::readInStandardInput(SATSolver* solver2)
+{
+ if (conf.verbosity) {
+ cout
+ << "c Reading from standard input... Use '-h' or '--help' for help."
+ << endl;
+ }
+
+ #ifndef USE_ZLIB
+ FILE * in = stdin;
+ #else
+ gzFile in = gzdopen(0, "rb"); //opens stdin, which is 0
+ #endif
+
+ if (in == NULL) {
+ std::cerr << "ERROR! Could not open standard input for reading" << endl;
+ std::exit(1);
+ }
+
+ #ifndef USE_ZLIB
+ DimacsParser<StreamBuffer<FILE*, FN> > parser(solver2, &debugLib, conf.verbosity);
+ #else
+ DimacsParser<StreamBuffer<gzFile, GZ> > parser(solver2, &debugLib, conf.verbosity);
+ #endif
+
+ if (!parser.parse_DIMACS(in, false)) {
+ exit(-1);
+ }
+
+ #ifdef USE_ZLIB
+ gzclose(in);
+ #endif
+}
+
+void Main::parseInAllFiles(SATSolver* solver2)
+{
+ const double myTime = cpuTime();
+
+ //First read normal extra files
+ if (!debugLib.empty() && filesToRead.size() > 1) {
+ cout
+ << "debugLib must be OFF"
+ << "to parse in more than one file"
+ << endl;
+
+ std::exit(-1);
+ }
+
+ for (const string& fname: filesToRead) {
+ readInAFile(solver2, fname.c_str());
+ }
+
+ solver->add_sql_tag("stdin", fileNamePresent ? "False" : "True");
+ if (!fileNamePresent) {
+ readInStandardInput(solver2);
+ }
+
+ if (conf.verbosity) {
+ cout
+ << "c Parsing time: "
+ << std::fixed << std::setprecision(2)
+ << (cpuTime() - myTime)
+ << " s" << endl;
+ }
+}
+
+void Main::printResultFunc(
+ std::ostream* os
+ , const bool toFile
+ , const lbool ret
+) {
+ if (ret == l_True) {
+ if(toFile) {
+ *os << "SAT" << endl;
+ }
+ else if (!printResult) *os << "s SATISFIABLE" << endl;
+ else *os << "s SATISFIABLE" << endl;
+ } else if (ret == l_False) {
+ if(toFile) {
+ *os << "UNSAT" << endl;
+ }
+ else if (!printResult) *os << "s UNSATISFIABLE" << endl;
+ else *os << "s UNSATISFIABLE" << endl;
+ } else {
+ *os << "s INDETERMINATE" << endl;
+ }
+
+ if (ret == l_True && (printResult || toFile)) {
+ if (toFile) {
+ for (uint32_t var = 0; var < solver->nVars(); var++) {
+ if (solver->get_model()[var] != l_Undef) {
+ *os << ((solver->get_model()[var] == l_True)? "" : "-") << var+1 << " ";
+ }
+ }
+ *os << "0" << endl;
+ } else {
+ const uint32_t num_undef = print_model(os, solver);
+ if (num_undef && !toFile && conf.verbosity) {
+ if (only_indep_solution) {
+ cout << "c NOTE: some variables' value are NOT set -- you ONLY asked for the independent set's values: '--onlyindep'" << endl;
+ } else {
+ cout << "c NOTE: " << num_undef << " varables are NOT set" << endl;
+ }
+ }
+ }
+ }
+}
+
+void Main::add_supported_options()
+{
+ // Declare the supported options.
+ generalOptions.add_options()
+ ("help,h", "Print simple help")
+ ("hhelp", "Print extensive help")
+ ("version,v", "Print version info")
+ ("verb", po::value(&conf.verbosity)->default_value(conf.verbosity)
+ , "[0-10] Verbosity of solver. 0 = only solution")
+ ("random,r", po::value(&conf.origSeed)->default_value(conf.origSeed)
+ , "[0..] Random seed")
+ ("threads,t", po::value(&num_threads)->default_value(1)
+ ,"Number of threads")
+ ("maxtime", po::value(&conf.maxTime)->default_value(conf.maxTime, "MAX")
+ , "Stop solving after this much time (s)")
+ ("maxconfl", po::value(&conf.max_confl)->default_value(conf.max_confl, "MAX")
+ , "Stop solving after this many conflicts")
+// ("undef", po::value(&conf.greedy_undef)->default_value(conf.greedy_undef)
+// , "Set as many variables in solution to UNDEF as possible if solution is SAT")
+ ("mult,m", po::value(&conf.orig_global_timeout_multiplier)->default_value(conf.orig_global_timeout_multiplier)
+ , "Time multiplier for all simplification cutoffs")
+ ("memoutmult", po::value(&conf.var_and_mem_out_mult)->default_value(conf.var_and_mem_out_mult)
+ , "Multiplier for memory-out checks on variables and clause-link-in, etc. Useful when you have limited memory.")
+ ("preproc,p", po::value(&conf.preprocess)->default_value(conf.preprocess)
+ , "0 = normal run, 1 = preprocess and dump, 2 = read back dump and solution to produce final solution")
+ ("polar", po::value<string>()->default_value("auto")
+ , "{true,false,rnd,auto} Selects polarity mode. 'true' -> selects only positive polarity when branching. 'false' -> selects only negative polarity when branching. 'auto' -> selects last polarity used (also called 'caching')")
+ #ifdef STATS_NEEDED
+ ("clid", po::bool_switch(&clause_ID_needed)
+ , "Add clause IDs to DRAT output")
+ #endif
+ //("greedyunbound", po::bool_switch(&conf.greedyUnbound)
+ // , "Greedily unbound variables that are not needed for SAT")
+ ;
+
+ std::ostringstream s_blocking_multip;
+ s_blocking_multip << std::setprecision(4) << conf.blocking_restart_multip;
+
+ po::options_description restartOptions("Restart options");
+ restartOptions.add_options()
+ ("restart", po::value<string>()
+ , "{geom, glue, luby} Restart strategy to follow.")
+ ("gluehist", po::value(&conf.shortTermHistorySize)->default_value(conf.shortTermHistorySize)
+ , "The size of the moving window for short-term glue history of redundant clauses. If higher, the minimal number of conflicts between restarts is longer")
+ ("blkrest", po::value(&conf.do_blocking_restart)->default_value(conf.do_blocking_restart)
+ , "Perform blocking restarts as per Glucose 3.0")
+ ("blkrestlen", po::value(&conf.blocking_restart_trail_hist_length)->default_value(conf.blocking_restart_trail_hist_length)
+ , "Length of the long term trail size for blocking restart")
+ ("blkrestmultip", po::value(&conf.blocking_restart_multip)->default_value(conf.blocking_restart_multip, s_blocking_multip.str())
+ , "Multiplier used for blocking restart cut-off (called 'R' in Glucose 3.0)")
+ ("lwrbndblkrest", po::value(&conf.lower_bound_for_blocking_restart)->default_value(conf.lower_bound_for_blocking_restart)
+ , "Lower bound on blocking restart -- don't block before this many conflicts")
+ ("locgmult" , po::value(&conf.local_glue_multiplier)->default_value(conf.local_glue_multiplier)
+ , "The multiplier used to determine if we should restart during glue-based restart")
+ ("brokengluerest", po::value(&conf.broken_glue_restart)->default_value(conf.broken_glue_restart)
+ , "Should glue restart be broken as before 8e74cb5010bb4")
+ ("ratiogluegeom", po::value(&conf.ratio_glue_geom)->default_value(conf.ratio_glue_geom)
+ , "Ratio of glue vs geometric restarts -- more is more glue")
+ ;
+
+ std::ostringstream s_incclean;
+
+ std::ostringstream s_adjust_low;
+ s_adjust_low << std::setprecision(2) << conf.adjust_glue_if_too_many_low;
+
+ po::options_description reduceDBOptions("Redundant clause options");
+ reduceDBOptions.add_options()
+ ("gluecut0", po::value(&conf.glue_put_lev0_if_below_or_eq)->default_value(conf.glue_put_lev0_if_below_or_eq)
+ , "Glue value for lev 0 ('keep') cut")
+ ("gluecut1", po::value(&conf.glue_put_lev1_if_below_or_eq)->default_value(conf.glue_put_lev1_if_below_or_eq)
+ , "Glue value for lev 1 cut ('give another shot'")
+ ("adjustglue", po::value(&conf.adjust_glue_if_too_many_low)->default_value(conf.adjust_glue_if_too_many_low, s_adjust_low.str())
+ , "If more than this % of clauses is LOW glue (level 0) then lower the glue cutoff by 1 -- once and never again")
+ ("ml", po::value(&conf.guess_cl_effectiveness)->default_value(conf.guess_cl_effectiveness)
+ , "Use ML model to guess clause effectiveness")
+ ("everylev1", po::value(&conf.every_lev1_reduce)->default_value(conf.every_lev1_reduce)
+ , "Reduce lev1 clauses every N")
+ ("everylev2", po::value(&conf.every_lev2_reduce)->default_value(conf.every_lev2_reduce)
+ , "Reduce lev2 clauses every N")
+ ("lev1usewithin", po::value(&conf.must_touch_lev1_within)->default_value(conf.must_touch_lev1_within)
+ , "Learnt clause must be used in lev1 within this timeframe or be dropped to lev2")
+ ("dumpred", po::value(&dump_red_fname)->default_value(dump_red_fname)
+ , "Dump redundant clauses of gluecut0&1 to this filename")
+ ("dumpredmaxlen", po::value(&dump_red_max_len)->default_value(dump_red_max_len)
+ , "When dumping redundant clauses, only dump clauses at most this long")
+ ("dumpredmaxglue", po::value(&dump_red_max_len)->default_value(dump_red_max_glue)
+ , "When dumping redundant clauses, only dump clauses with at most this large glue")
+ ;
+
+ std::ostringstream s_random_var_freq;
+ s_random_var_freq << std::setprecision(5) << conf.random_var_freq;
+
+ std::ostringstream s_var_decay_vsids_start;
+ s_var_decay_vsids_start << std::setprecision(5) << conf.var_decay_vsids_start;
+
+ std::ostringstream s_var_decay_vsids_max;
+ s_var_decay_vsids_max << std::setprecision(5) << conf.var_decay_vsids_max;
+
+ po::options_description varPickOptions("Variable branching options");
+ varPickOptions.add_options()
+ ("vardecaystart", po::value(&conf.var_decay_vsids_start)->default_value(conf.var_decay_vsids_start, s_var_decay_vsids_start.str())
+ , "variable activity increase divider (MUST be smaller than multiplier)")
+ ("vardecaymax", po::value(&conf.var_decay_vsids_max)->default_value(conf.var_decay_vsids_max, s_var_decay_vsids_max.str())
+ , "variable activity increase divider (MUST be smaller than multiplier)")
+ ("vincstart", po::value(&conf.var_inc_vsids_start)->default_value(conf.var_inc_vsids_start)
+ , "variable activity increase stars with this value. Make sure that this multiplied by multiplier and divided by divider is larger than itself")
+ ("freq", po::value(&conf.random_var_freq)->default_value(conf.random_var_freq, s_random_var_freq.str())
+ , "[0 - 1] freq. of picking var at random")
+ ("maple", po::value(&conf.maple)->default_value(conf.maple)
+ , "Use maple-type variable picking sometimes")
+ ("maplemod", po::value(&conf.modulo_maple_iter)->default_value(conf.modulo_maple_iter)
+ , "Use maple N-1 of N rounds. Normally, N is 2, so used every other round. Set to 3 so it will use maple 2/3rds of the time.")
+ ("maplemorebump", po::value(&conf.more_maple_bump_high_glue)->default_value(conf.more_maple_bump_high_glue)
+ , "Bump variable usefulness more when glue is HIGH")
+ ;
+
+
+ po::options_description iterativeOptions("Iterative solve options");
+ iterativeOptions.add_options()
+ ("maxsol", po::value(&max_nr_of_solutions)->default_value(max_nr_of_solutions)
+ , "Search for given amount of solutions")
+ ("debuglib", po::value<string>(&debugLib)
+ , "MainSolver at specific 'solve()' points in CNF file")
+ ("dumpresult", po::value(&resultFilename)
+ , "Write solution(s) to this file")
+ ;
+
+ po::options_description probeOptions("Probing options");
+ probeOptions.add_options()
+ ("bothprop", po::value(&conf.doBothProp)->default_value(conf.doBothProp)
+ , "Do propagations solely to propagate the same value twice")
+ ("probe", po::value(&conf.doProbe)->default_value(conf.doProbe)
+ , "Carry out probing")
+ ("probemaxm", po::value(&conf.probe_bogoprops_time_limitM)->default_value(conf.probe_bogoprops_time_limitM)
+ , "Time in mega-bogoprops to perform probing")
+ ("transred", po::value(&conf.doTransRed)->default_value(conf.doTransRed)
+ , "Remove useless binary clauses (transitive reduction)")
+ ("intree", po::value(&conf.doIntreeProbe)->default_value(conf.doIntreeProbe)
+ , "Carry out intree-based probing")
+ ("intreemaxm", po::value(&conf.intree_time_limitM)->default_value(conf.intree_time_limitM)
+ , "Time in mega-bogoprops to perform intree probing")
+ ;
+
+ std::ostringstream ssERatio;
+ ssERatio << std::setprecision(4) << "norm: " << conf.varElimRatioPerIter << " preproc: " << 1.0;
+
+ po::options_description simplificationOptions("Simplification options");
+ simplificationOptions.add_options()
+ ("schedsimp", po::value(&conf.do_simplify_problem)->default_value(conf.do_simplify_problem)
+ , "Perform simplification rounds. If 0, we never perform any.")
+ ("presimp", po::value(&conf.simplify_at_startup)->default_value(conf.simplify_at_startup)
+ , "Perform simplification at the very start")
+ ("allpresimp", po::value(&conf.simplify_at_every_startup)->default_value(conf.simplify_at_every_startup)
+ , "Perform simplification at EVERY start -- only matters in library mode")
+ ("nonstop,n", po::value(&conf.never_stop_search)->default_value(conf.never_stop_search)
+ , "Never stop the search() process in class SATSolver")
+
+ ("schedule", po::value(&conf.simplify_schedule_nonstartup)
+ , "Schedule for simplification during run")
+ ("preschedule", po::value(&conf.simplify_schedule_startup)
+ , "Schedule for simplification at startup")
+
+ ("occsimp", po::value(&conf.perform_occur_based_simp)->default_value(conf.perform_occur_based_simp)
+ , "Perform occurrence-list-based optimisations (variable elimination, subsumption, bounded variable addition...)")
+
+
+ ("confbtwsimp", po::value(&conf.num_conflicts_of_search)->default_value(conf.num_conflicts_of_search)
+ , "Start first simplification after this many conflicts")
+ ("confbtwsimpinc", po::value(&conf.num_conflicts_of_search_inc)->default_value(conf.num_conflicts_of_search_inc)
+ , "Simp rounds increment by this power of N")
+ ("varelim", po::value(&conf.doVarElim)->default_value(conf.doVarElim)
+ , "Perform variable elimination as per Een and Biere")
+ ("varelimto", po::value(&conf.varelim_time_limitM)->default_value(conf.varelim_time_limitM)
+ , "Var elimination bogoprops M time limit")
+ ("varelimover", po::value(&conf.min_bva_gain)->default_value(conf.min_bva_gain)
+ , "Do BVE until the resulting no. of clause increase is less than X. Only power of 2 makes sense, i.e. 2,4,8...")
+ ("emptyelim", po::value(&conf.do_empty_varelim)->default_value(conf.do_empty_varelim)
+ , "Perform empty resolvent elimination using bit-map trick")
+ ("strengthen", po::value(&conf.do_strengthen_with_occur)->default_value(conf.do_strengthen_with_occur)
+ , "Perform clause contraction through self-subsuming resolution as part of the occurrence-subsumption system")
+ ("bva", po::value(&conf.do_bva)->default_value(conf.do_bva)
+ , "Perform bounded variable addition")
+ ("bvalim", po::value(&conf.bva_limit_per_call)->default_value(conf.bva_limit_per_call)
+ , "Maximum number of variables to add by BVA per call")
+ ("bva2lit", po::value(&conf.bva_also_twolit_diff)->default_value(conf.bva_also_twolit_diff)
+ , "BVA with 2-lit difference hack, too. Beware, this reduces the effectiveness of 1-lit diff")
+ ("bvato", po::value(&conf.bva_time_limitM)->default_value(conf.bva_time_limitM)
+ , "BVA time limit in bogoprops M")
+ ("eratio", po::value(&conf.varElimRatioPerIter)->default_value(conf.varElimRatioPerIter, ssERatio.str())
+ , "Eliminate this ratio of free variables at most per variable elimination iteration")
+ ("skipresol", po::value(&conf.skip_some_bve_resolvents)->default_value(conf.skip_some_bve_resolvents)
+ , "Skip BVE resolvents in case they belong to a gate")
+ ("occredmax", po::value(&conf.maxRedLinkInSize)->default_value(conf.maxRedLinkInSize)
+ , "Don't add to occur list any redundant clause larger than this")
+ ("occirredmaxmb", po::value(&conf.maxOccurIrredMB)->default_value(conf.maxOccurIrredMB)
+ , "Don't allow irredundant occur size to be beyond this many MB")
+ ("occredmaxmb", po::value(&conf.maxOccurRedMB)->default_value(conf.maxOccurRedMB)
+ , "Don't allow redundant occur size to be beyond this many MB")
+ ("substimelim", po::value(&conf.subsumption_time_limitM)->default_value(conf.subsumption_time_limitM)
+ , "Time-out in bogoprops M of subsumption of long clauses with long clauses, after computing occur")
+ ("strstimelim", po::value(&conf.strengthening_time_limitM)->default_value(conf.strengthening_time_limitM)
+ , "Time-out in bogoprops M of strengthening of long clauses with long clauses, after computing occur")
+ ("agrelimtimelim", po::value(&conf.aggressive_elim_time_limitM)->default_value(conf.aggressive_elim_time_limitM)
+ , "Time-out in bogoprops M of aggressive(=uses reverse distillation) var-elimination")
+ ;
+
+ po::options_description xorOptions("XOR-related options");
+ xorOptions.add_options()
+ ("xor", po::value(&conf.doFindXors)->default_value(conf.doFindXors)
+ , "Discover long XORs")
+ ("xorcache", po::value(&conf.useCacheWhenFindingXors)->default_value(conf.useCacheWhenFindingXors)
+ , "Use cache when finding XORs. Finds a LOT more XORs, but takes a lot more time")
+ ("varsperxorcut", po::value(&conf.xor_var_per_cut)->default_value(conf.xor_var_per_cut)
+ , "Number of _real_ variables per XOR when cutting them. So 2 will have XORs of size 4 because 1 = connecting to previous, 1 = connecting to next, 2 in the midde. If the XOR is 4 long, it will be just one 4-long XOR, no connectors")
+ ("echelonxor", po::value(&conf.doEchelonizeXOR)->default_value(conf.doEchelonizeXOR)
+ , "Extract data from XORs through echelonization (TOP LEVEL ONLY)")
+ ("maxxormat", po::value(&conf.maxXORMatrix)->default_value(conf.maxXORMatrix)
+ , "Maximum matrix size (=num elements) that we should try to echelonize")
+ //Not implemented yet
+ //("mix", po::value(&conf.doMixXorAndGates)->default_value(conf.doMixXorAndGates)
+ // , "Mix XORs and OrGates for new truths")
+ ;
+
+ po::options_description eqLitOpts("Equivalent literal options");
+ eqLitOpts.add_options()
+ ("scc", po::value(&conf.doFindAndReplaceEqLits)->default_value(conf.doFindAndReplaceEqLits)
+ , "Find equivalent literals through SCC and replace them")
+ ("extscc", po::value(&conf.doExtendedSCC)->default_value(conf.doExtendedSCC)
+ , "Perform SCC using cache")
+ ;
+
+ po::options_description gateOptions("Gate-related options");
+ gateOptions.add_options()
+ ("gates", po::value(&conf.doGateFind)->default_value(conf.doGateFind)
+ , "Find gates. Disables all sub-options below")
+ ("gorshort", po::value(&conf.doShortenWithOrGates)->default_value(conf.doShortenWithOrGates)
+ , "Shorten clauses with OR gates")
+ ("gandrem", po::value(&conf.doRemClWithAndGates)->default_value(conf.doRemClWithAndGates)
+ , "Remove clauses with AND gates")
+ ("gateeqlit", po::value(&conf.doFindEqLitsWithGates)->default_value(conf.doFindEqLitsWithGates)
+ , "Find equivalent literals using gates")
+ /*("maxgatesz", po::value(&conf.maxGateSize)->default_value(conf.maxGateSize)
+ , "Maximum gate size to discover")*/
+ ("printgatedot", po::value(&conf.doPrintGateDot)->default_value(conf.doPrintGateDot)
+ , "Print gate structure regularly to file 'gatesX.dot'")
+ ("gatefindto", po::value(&conf.gatefinder_time_limitM)->default_value(conf.gatefinder_time_limitM)
+ , "Max time in bogoprops M to find gates")
+ ("shortwithgatesto", po::value(&conf.shorten_with_gates_time_limitM)->default_value(conf.shorten_with_gates_time_limitM)
+ , "Max time to shorten with gates, bogoprops M")
+ ("remwithgatesto", po::value(&conf.remove_cl_with_gates_time_limitM)->default_value(conf.remove_cl_with_gates_time_limitM)
+ , "Max time to remove with gates, bogoprops M")
+ ;
+
+ po::options_description conflOptions("Conflict options");
+ conflOptions.add_options()
+ ("recur", po::value(&conf.doRecursiveMinim)->default_value(conf.doRecursiveMinim)
+ , "Perform recursive minimisation")
+ ("moreminim", po::value(&conf.doMinimRedMore)->default_value(conf.doMinimRedMore)
+ , "Perform strong minimisation at conflict gen.")
+ ("moremoreminim", po::value(&conf.doMinimRedMoreMore)->default_value(conf.doMinimRedMoreMore)
+ , "Perform even stronger minimisation at conflict gen.")
+ ("moremorecachelimit", po::value(&conf.more_red_minim_limit_cache)->default_value(conf.more_red_minim_limit_cache)
+ , "Time-out in microsteps for each more minimisation with cache. Only active if 'moreminim' is on")
+ ("moremorestamp", po::value(&conf.more_more_with_stamp)->default_value(conf.more_more_with_stamp)
+ , "Use cache for otf more minim of learnt clauses")
+ ("moremorealways", po::value(&conf.doAlwaysFMinim)->default_value(conf.doAlwaysFMinim)
+ , "Always strong-minimise clause")
+ ("otfsubsume", po::value(&conf.doOTFSubsume)->default_value(conf.doOTFSubsume)
+ , "Perform on-the-fly subsumption")
+ ;
+
+ po::options_description propOptions("Propagation options");
+ propOptions.add_options()
+ ("updateglueonanalysis", po::value(&conf.update_glues_on_analyze)->default_value(conf.update_glues_on_analyze)
+ , "Update glues while analyzing")
+ ("otfhyper", po::value(&conf.otfHyperbin)->default_value(conf.otfHyperbin)
+ , "Perform hyper-binary resolution at dec. level 1 after every restart and during probing")
+ ;
+
+
+ po::options_description stampOptions("Stamping options");
+ stampOptions.add_options()
+ ("stamp", po::value(&conf.doStamp)->default_value(conf.doStamp)
+ , "Use time stamping as per Heule&Jarvisalo&Biere paper")
+ ("cache", po::value(&conf.doCache)->default_value(conf.doCache)
+ , "Use implication cache -- may use a lot of memory")
+ ("cachesize", po::value(&conf.maxCacheSizeMB)->default_value(conf.maxCacheSizeMB)
+ , "Maximum size of the implication cache in MB. It may temporarily reach higher usage, but will be deleted&disabled if this limit is reached.")
+ ("cachecutoff", po::value(&conf.cacheUpdateCutoff)->default_value(conf.cacheUpdateCutoff)
+ , "If the number of literals propagated by a literal is more than this, it's not included into the implication cache")
+ ;
+
+ po::options_description sqlOptions("SQL options");
+ sqlOptions.add_options()
+ ("sql", po::value(&sql)->default_value(0)
+ , "Write to SQL. 0 = no SQL, 1 or 2 = sqlite")
+ ("sqlitedb", po::value(&sqlite_filename)
+ , "Where to put the SQLite database")
+ ("cldatadumpratio", po::value(&conf.dump_individual_cldata_ratio)->default_value(conf.dump_individual_cldata_ratio)
+ , "Only dump this ratio of clauses' data, randomly selected. Since machine learning doesn't need that much data, this can reduce the data you have to deal with.")
+ ;
+
+ po::options_description printOptions("Printing options");
+ printOptions.add_options()
+ ("verbstat", po::value(&conf.verbStats)->default_value(conf.verbStats)
+ , "Change verbosity of statistics at the end of the solving [0..2]")
+ ("verbrestart", po::value(&conf.print_full_restart_stat)->default_value(conf.print_full_restart_stat)
+ , "Print more thorough, but different stats")
+ ("verballrestarts", po::value(&conf.print_all_restarts)->default_value(conf.print_all_restarts)
+ , "Print a line for every restart")
+ ("printsol,s", po::value(&printResult)->default_value(printResult)
+ , "Print assignment if solution is SAT")
+ ("restartprint", po::value(&conf.print_restart_line_every_n_confl)->default_value(conf.print_restart_line_every_n_confl)
+ , "Print restart status lines at least every N conflicts")
+ ;
+
+ po::options_description componentOptions("Component options");
+ componentOptions.add_options()
+ ("comps", po::value(&conf.doCompHandler)->default_value(conf.doCompHandler)
+ , "Perform component-finding and separate handling")
+ ("compsfrom", po::value(&conf.handlerFromSimpNum)->default_value(conf.handlerFromSimpNum)
+ , "Component finding only after this many simplification rounds")
+ ("compsvar", po::value(&conf.compVarLimit)->default_value(conf.compVarLimit)
+ , "Only use components in case the number of variables is below this limit")
+ ("compslimit", po::value(&conf.comp_find_time_limitM)->default_value(conf.comp_find_time_limitM)
+ , "Limit how much time is spent in component-finding");
+
+ po::options_description distillOptions("Misc options");
+ distillOptions.add_options()
+ //("noparts", "Don't find&solve subproblems with subsolvers")
+ ("distill", po::value(&conf.do_distill_clauses)->default_value(conf.do_distill_clauses)
+ , "Regularly execute clause distillation")
+ ("distillmaxm", po::value(&conf.distill_long_cls_time_limitM)->default_value(conf.distill_long_cls_time_limitM)
+ , "Maximum number of Mega-bogoprops(~time) to spend on vivifying/distilling long cls by enqueueing and propagating")
+ ("distillto", po::value(&conf.distill_time_limitM)->default_value(conf.distill_time_limitM)
+ , "Maximum time in bogoprops M for distillation")
+ ;
+
+ po::options_description miscOptions("Misc options");
+ miscOptions.add_options()
+ //("noparts", "Don't find&solve subproblems with subsolvers")
+ ("strcachemaxm", po::value(&conf.watch_cache_stamp_based_str_time_limitM)->default_value(conf.watch_cache_stamp_based_str_time_limitM)
+ , "Maximum number of Mega-bogoprops(~time) to spend on vivifying long irred cls through watches, cache and stamps")
+ ("renumber", po::value(&conf.doRenumberVars)->default_value(conf.doRenumberVars)
+ , "Renumber variables to increase CPU cache efficiency")
+ ("savemem", po::value(&conf.doSaveMem)->default_value(conf.doSaveMem)
+ , "Save memory by deallocating variable space after renumbering. Only works if renumbering is active.")
+ ("implicitmanip", po::value(&conf.doStrSubImplicit)->default_value(conf.doStrSubImplicit)
+ , "Subsume and strengthen implicit clauses with each other")
+ ("implsubsto", po::value(&conf.subsume_implicit_time_limitM)->default_value(conf.subsume_implicit_time_limitM)
+ , "Timeout (in bogoprop Millions) of implicit subsumption")
+ ("implstrto", po::value(&conf.distill_implicit_with_implicit_time_limitM)->default_value(conf.distill_implicit_with_implicit_time_limitM)
+ , "Timeout (in bogoprop Millions) of implicit strengthening")
+ ;
+
+ po::options_description reconfOptions("Reconf options");
+ reconfOptions.add_options()
+ ("reconfat", po::value(&conf.reconfigure_at)->default_value(conf.reconfigure_at)
+ , "Reconfigure after this many simplifications")
+ ("reconf", po::value(&conf.reconfigure_val)->default_value(conf.reconfigure_val)
+ , "Reconfigure after some time to this solver configuration [0..15]")
+ ;
+
+ hiddenOptions.add_options()
+ ("sync", po::value(&conf.sync_every_confl)->default_value(conf.sync_every_confl)
+ , "Sync threads every N conflicts")
+ ("dratdebug", po::bool_switch(&dratDebug)
+ , "Output DRAT verification into the console. Helpful to see where DRAT fails -- use in conjunction with --verb 20")
+ ("clearinter", po::value(&need_clean_exit)->default_value(0)
+ , "Interrupt threads cleanly, all the time")
+ ("zero-exit-status", po::bool_switch(&zero_exit_status)
+ , "Exit with status zero in case the solving has finished without an issue")
+ ("input", po::value< vector<string> >(), "file(s) to read")
+ ("printtimes", po::value(&conf.do_print_times)->default_value(conf.do_print_times)
+ , "Print time it took for each simplification run. If set to 0, logs are easier to compare")
+ ("drat,d", po::value(&dratfilname)
+ , "Put DRAT verification information into this file")
+ ("savedstate", po::value(&conf.saved_state_file)->default_value(conf.saved_state_file)
+ , "The file to save the saved state of the solver")
+ ("maxsccdepth", po::value(&conf.max_scc_depth)->default_value(conf.max_scc_depth)
+ , "The maximum for scc search depth")
+ ("simdrat", po::value(&conf.simulate_drat)->default_value(conf.simulate_drat)
+ , "The maximum for scc search depth")
+ ("indep", po::value(&independent_vars_str)->default_value(independent_vars_str)
+ , "Independent vars, separated by comma")
+ ("onlyindep", po::bool_switch(&only_indep_solution)
+ , "Independent vars, separated by comma")
+ ;
+
+#ifdef USE_GAUSS
+ po::options_description gaussOptions("Gauss options");
+ gaussOptions.add_options()
+ ("maxgaussdepth", po::value(&conf.gaussconf.decision_until)->default_value(conf.gaussconf.decision_until)
+ , "Only run Gaussian Elimination until this depth. You may want this depth to be relatively small, such as 120-30, though it depends on the complexity of the problem. It is best to experiment.")
+ ("maxmatrixrows", po::value(&conf.gaussconf.max_matrix_rows)->default_value(conf.gaussconf.max_matrix_rows)
+ , "Set maximum no. of rows for gaussian matrix. Too large matrixes"
+ "should bee discarded for reasons of efficiency")
+ ("autodisablegauss", po::value(&conf.gaussconf.autodisable)->default_value(conf.gaussconf.autodisable)
+ , "Automatically disable gauss when performing badly")
+ ("minmatrixrows", po::value(&conf.gaussconf.min_matrix_rows)->default_value(conf.gaussconf.min_matrix_rows)
+ , "Set minimum no. of rows for gaussian matrix. Normally, too small"
+ "matrixes are discarded for reasons of efficiency")
+ ("maxnummatrixes", po::value(&conf.gaussconf.max_num_matrixes)->default_value(conf.gaussconf.max_num_matrixes)
+ , "Maximum number of matrixes to treat.")
+ ;
+#endif //USE_GAUSS
+
+ help_options_complicated
+ .add(generalOptions)
+ #if defined(USE_SQLITE3)
+ .add(sqlOptions)
+ #endif
+ .add(restartOptions)
+ .add(printOptions)
+ .add(propOptions)
+ .add(reduceDBOptions)
+ .add(varPickOptions)
+ .add(conflOptions)
+ .add(iterativeOptions)
+ .add(probeOptions)
+ .add(stampOptions)
+ .add(simplificationOptions)
+ .add(eqLitOpts)
+ .add(componentOptions)
+ #if defined(USE_M4RI) or defined(USE_GAUSS)
+ .add(xorOptions)
+ #endif
+ .add(gateOptions)
+ #ifdef USE_GAUSS
+ .add(gaussOptions)
+ #endif
+ .add(distillOptions)
+ .add(reconfOptions)
+ .add(miscOptions)
+ ;
+}
+
+string remove_last_comma_if_exists(std::string s)
+{
+ std::string s2 = s;
+ if (s[s.length()-1] == ',')
+ s2.resize(s2.length()-1);
+ return s2;
+}
+
+void Main::check_options_correctness()
+{
+ try {
+ po::store(po::command_line_parser(argc, argv).options(all_options).positional(p).run(), vm);
+ if (vm.count("hhelp"))
+ {
+ cout
+ << "A universal, fast SAT solver with XOR and Gaussian Elimination support. " << endl
+ << "Input "
+ #ifndef USE_ZLIB
+ << "must be plain"
+ #else
+ << "can be either plain or gzipped"
+ #endif
+ << " DIMACS with XOR extension" << endl << endl;
+
+ cout
+ << "cryptominisat5 [options] inputfile [drat-trim-file]" << endl << endl;
+
+ cout << "Preprocessor usage:" << endl
+ << " cryptominisat5 --preproc 1 [options] inputfile simplified-cnf-file" << endl << endl
+ << " cryptominisat5 --preproc 2 [options] solution-file" << endl;
+
+ cout << help_options_complicated << endl;
+ cout << "Normal run schedules:" << endl;
+ cout << " Default schedule: "
+ << remove_last_comma_if_exists(conf.simplify_schedule_nonstartup) << endl<< endl;
+ cout << " Schedule at startup: "
+ << remove_last_comma_if_exists(conf.simplify_schedule_startup) << endl << endl;
+
+ cout << "Preproc run schedule:" << endl;
+ cout << " "
+ << remove_last_comma_if_exists(conf.simplify_schedule_preproc) << endl;
+ std::exit(0);
+ }
+
+ if (vm.count("help"))
+ {
+ cout
+ << "USAGE 1: " << argv[0] << " [options] inputfile [drat-trim-file]" << endl
+ << "USAGE 2: " << argv[0] << " --preproc 1 [options] inputfile simplified-cnf-file" << endl
+ << "USAGE 2: " << argv[0] << " --preproc 2 [options] solution-file" << endl
+
+ << " where input is "
+ #ifndef USE_ZLIB
+ << "plain"
+ #else
+ << "plain or gzipped"
+ #endif
+ << " DIMACS." << endl;
+
+ cout << help_options_simple << endl;
+ std::exit(0);
+ }
+
+ po::notify(vm);
+ } catch (boost::exception_detail::clone_impl<
+ boost::exception_detail::error_info_injector<po::unknown_option> >& c
+ ) {
+ cerr
+ << "ERROR: Some option you gave was wrong. Please give '--help' to get help" << endl
+ << " Unkown option: " << c.what() << endl;
+ std::exit(-1);
+ } catch (boost::bad_any_cast &e) {
+ std::cerr
+ << "ERROR! You probably gave a wrong argument type" << endl
+ << " Bad cast: " << e.what()
+ << endl;
+
+ std::exit(-1);
+ } catch (boost::exception_detail::clone_impl<
+ boost::exception_detail::error_info_injector<po::invalid_option_value> >& what
+ ) {
+ cerr
+ << "ERROR: Invalid value '" << what.what() << "'" << endl
+ << " given to option '" << what.get_option_name() << "'"
+ << endl;
+
+ std::exit(-1);
+ } catch (boost::exception_detail::clone_impl<
+ boost::exception_detail::error_info_injector<po::multiple_occurrences> >& what
+ ) {
+ cerr
+ << "ERROR: " << what.what() << " of option '"
+ << what.get_option_name() << "'"
+ << endl;
+
+ std::exit(-1);
+ } catch (boost::exception_detail::clone_impl<
+ boost::exception_detail::error_info_injector<po::required_option> >& what
+ ) {
+ cerr
+ << "ERROR: You forgot to give a required option '"
+ << what.get_option_name() << "'"
+ << endl;
+
+ std::exit(-1);
+ } catch (boost::exception_detail::clone_impl<
+ boost::exception_detail::error_info_injector<po::too_many_positional_options_error> >& what
+ ) {
+ cerr
+ << "ERROR: You gave too many positional arguments. Only at most two can be given:" << endl
+ << " the 1st the CNF file input, and optinally, the 2nd the DRAT file output" << endl
+ << " OR (pre-processing) 1st for the input CNF, 2nd for the simplified CNF" << endl
+ << " OR (post-processing) 1st for the solution file" << endl
+ ;
+
+ std::exit(-1);
+ } catch (boost::exception_detail::clone_impl<
+ boost::exception_detail::error_info_injector<po::ambiguous_option> >& what
+ ) {
+ cerr
+ << "ERROR: The option you gave was not fully written and matches" << endl
+ << " more than one option. Please give the full option name." << endl
+ << " The option you gave: '" << what.get_option_name() << "'" <<endl
+ << " The alternatives are: ";
+ for(size_t i = 0; i < what.alternatives().size(); i++) {
+ cout << what.alternatives()[i];
+ if (i+1 < what.alternatives().size()) {
+ cout << ", ";
+ }
+ }
+ cout << endl;
+
+ std::exit(-1);
+ } catch (boost::exception_detail::clone_impl<
+ boost::exception_detail::error_info_injector<po::invalid_command_line_syntax> >& what
+ ) {
+ cerr
+ << "ERROR: The option you gave is missing the argument or the" << endl
+ << " argument is given with space between the equal sign." << endl
+ << " detailed error message: " << what.what() << endl
+ ;
+ std::exit(-1);
+ }
+}
+
+void Main::handle_drat_option()
+{
+ if (!conf.simulate_drat) {
+ if (dratDebug) {
+ dratf = &cout;
+ } else {
+ std::ofstream* dratfTmp = new std::ofstream;
+ dratfTmp->open(dratfilname.c_str(), std::ofstream::out | std::ofstream::binary);
+ if (!*dratfTmp) {
+ std::cerr
+ << "ERROR: Could not open DRAT file "
+ << dratfilname
+ << " for writing"
+ << endl;
+
+ std::exit(-1);
+ }
+ dratf = dratfTmp;
+ }
+ }
+
+ if (!conf.otfHyperbin) {
+ if (conf.verbosity) {
+ cout
+ << "c OTF hyper-bin is needed for BProp in DRAT, turning it back"
+ << endl;
+ }
+ conf.otfHyperbin = true;
+ }
+
+ if (conf.doFindXors) {
+ if (conf.verbosity) {
+ cout
+ << "c XOR manipulation is not supported in DRAT, turning it off"
+ << endl;
+ }
+ conf.doFindXors = false;
+ }
+
+ if (conf.doRenumberVars) {
+ if (conf.verbosity) {
+ cout
+ << "c Variable renumbering is not supported during DRAT, turning it off"
+ << endl;
+ }
+ conf.doRenumberVars = false;
+ }
+
+ if (conf.doCompHandler) {
+ if (conf.verbosity) {
+ cout
+ << "c Component finding & solving is not supported during DRAT, turning it off"
+ << endl;
+ }
+ conf.doCompHandler = false;
+ }
+}
+
+void Main::parse_restart_type()
+{
+ if (vm.count("restart")) {
+ string type = vm["restart"].as<string>();
+ if (type == "geom")
+ conf.restartType = Restart::geom;
+ else if (type == "luby")
+ conf.restartType = Restart::luby;
+ else if (type == "glue")
+ conf.restartType = Restart::glue;
+ else throw WrongParam("restart", "unknown restart type");
+ }
+}
+
+void Main::parse_polarity_type()
+{
+ if (vm.count("polar")) {
+ string mode = vm["polar"].as<string>();
+
+ if (mode == "true") conf.polarity_mode = PolarityMode::polarmode_pos;
+ else if (mode == "false") conf.polarity_mode = PolarityMode::polarmode_neg;
+ else if (mode == "rnd") conf.polarity_mode = PolarityMode::polarmode_rnd;
+ else if (mode == "auto") conf.polarity_mode = PolarityMode::polarmode_automatic;
+ else throw WrongParam(mode, "unknown polarity-mode");
+ }
+}
+
+void Main::manually_parse_some_options()
+{
+ if (conf.shortTermHistorySize <= 0) {
+ cout
+ << "You MUST give a short term history size (\"--gluehist\")" << endl
+ << " greater than 0!"
+ << endl;
+
+ std::exit(-1);
+ }
+
+ if (!vm["savedstate"].defaulted() && conf.preprocess == 0) {
+ cout << "ERROR: It does not make sense to have --savedstate passed and not use preprocessing" << endl;
+ exit(-1);
+ }
+
+ if (conf.preprocess != 0) {
+ conf.simplify_at_startup = 1;
+ conf.varelim_time_limitM *= 5;
+ conf.orig_global_timeout_multiplier *= 1.5;
+ if (conf.doCompHandler) {
+ conf.doCompHandler = false;
+ if (conf.verbosity) {
+ cout << "c Cannot handle components when preprocessing. Turning it off." << endl;
+ }
+ }
+
+ if (num_threads > 1) {
+ num_threads = 1;
+ cout << "c Cannot handle multiple threads for preprocessing. Setting to 1." << endl;
+ }
+
+
+ if (!redDumpFname.empty()
+ || !irredDumpFname.empty()
+ ) {
+ std::cerr << "ERROR: dumping clauses with preprocessing makes no sense. Exiting" << endl;
+ std::exit(-1);
+ }
+
+ if (max_nr_of_solutions > 1) {
+ std::cerr << "ERROR: multi-solutions make no sense with preprocessing. Exiting." << endl;
+ std::exit(-1);
+ }
+
+ if (!filesToRead.empty()) {
+ assert(false && "we should never reach this place, filesToRead has not been populated yet");
+ exit(-1);
+ }
+
+ if (!debugLib.empty()) {
+ std::cerr << "ERROR: debugLib makes no sense with preprocessing. Exiting." << endl;
+ std::exit(-1);
+ }
+
+ if (vm.count("schedule")) {
+ std::cerr << "ERROR: Pleaase adjust the --preschedule not the --schedule when preprocessing. Exiting." << endl;
+ std::exit(-1);
+ }
+
+ if (vm.count("occschedule")) {
+ std::cerr << "ERROR: Pleaase adjust the --preoccschedule not the --occschedule when preprocessing. Exiting." << endl;
+ std::exit(-1);
+ }
+
+ if (!vm.count("preschedule")) {
+ conf.simplify_schedule_startup = conf.simplify_schedule_preproc;
+ }
+
+ if (!vm.count("eratio")) {
+ conf.varElimRatioPerIter = 2.0;
+ }
+ }
+
+ if (vm.count("dumpresult")) {
+ resultfile = new std::ofstream;
+ resultfile->open(resultFilename.c_str());
+ if (!(*resultfile)) {
+ cout
+ << "ERROR: Couldn't open file '"
+ << resultFilename
+ << "' for writing!"
+ << endl;
+ std::exit(-1);
+ }
+ }
+
+ parse_polarity_type();
+
+ if (conf.random_var_freq < 0 || conf.random_var_freq > 1) {
+ throw WrongParam(lexical_cast<string>(conf.random_var_freq), "Illegal random var frequency ");
+ }
+
+ //Conflict
+ if (vm.count("maxdump") && redDumpFname.empty()) {
+ throw WrongParam("maxdump", "--dumpred <filename> must be activated if issuing --maxdump <size>");
+ }
+
+ parse_restart_type();
+
+ if (conf.preprocess == 2) {
+ if (vm.count("input") == 0) {
+ cout << "ERROR: When post-processing you must give the solution as the positional argument"
+ << endl;
+ std::exit(-1);
+ }
+
+ vector<string> solution = vm["input"].as<vector<string> >();
+ if (solution.size() > 1) {
+ cout << "ERROR: When post-processing you must give only the solution as the positional argument."
+ << endl
+ << "The saved state must be given as the argument '--savedsate X'"
+ << endl;
+ std::exit(-1);
+ }
+ conf.solution_file = solution[0];
+ } else if (vm.count("input")) {
+ filesToRead = vm["input"].as<vector<string> >();
+ if (!vm.count("sqlitedb")) {
+ sqlite_filename = filesToRead[0] + ".sqlite";
+ } else {
+ sqlite_filename = vm["sqlitedb"].as<string>();
+ }
+ fileNamePresent = true;
+ } else {
+ fileNamePresent = false;
+ }
+
+ if (conf.preprocess == 1) {
+ if (!vm.count("drat")) {
+ cout << "ERROR: When preprocessing, you must give the simplified file name as 2nd argument" << endl;
+ std::exit(-1);
+ }
+ conf.simplified_cnf = vm["drat"].as<string>();
+ }
+
+ if (conf.preprocess == 2) {
+ if (vm.count("drat")) {
+ cout << "ERROR: When postprocessing, you must NOT give a 2nd argument" << endl;
+ std::exit(-1);
+ }
+ }
+
+ if (conf.preprocess == 0 &&
+ (vm.count("drat") || conf.simulate_drat)
+ ) {
+ handle_drat_option();
+ }
+
+ if (conf.verbosity) {
+ cout << "c Outputting solution to console" << endl;
+ }
+}
+
+void Main::parseCommandLine()
+{
+ need_clean_exit = 0;
+
+ //Reconstruct the command line so we can emit it later if needed
+ for(int i = 0; i < argc; i++) {
+ commandLine += string(argv[i]);
+ if (i+1 < argc) {
+ commandLine += " ";
+ }
+ }
+
+ add_supported_options();
+ p.add("input", 1);
+ p.add("drat", 1);
+ all_options.add(help_options_complicated);
+ all_options.add(hiddenOptions);
+
+ help_options_simple
+ .add(generalOptions)
+ ;
+
+ check_options_correctness();
+ if (vm.count("version")) {
+ printVersionInfo();
+ std::exit(0);
+ }
+
+ try {
+ manually_parse_some_options();
+ } catch(WrongParam& wp) {
+ cerr << "ERROR: " << wp.getMsg() << endl;
+ exit(-1);
+ }
+}
+
+void Main::check_num_threads_sanity(const unsigned thread_num) const
+{
+ const unsigned num_cores = std::thread::hardware_concurrency();
+ if (num_cores == 0) {
+ //Library doesn't know much, we can't do any checks.
+ return;
+ }
+
+ if (thread_num > num_cores && conf.verbosity) {
+ std::cout
+ << "c WARNING: Number of threads requested is more than the number of"
+ << " cores reported by the system.\n"
+ << "c WARNING: This is not a good idea in general. It's best to set the"
+ << " number of threads to the number of real cores" << endl;
+ }
+}
+
+void Main::dump_red_file()
+{
+ if (dump_red_fname.length() == 0)
+ return;
+
+ std::ofstream* dumpfile = new std::ofstream;
+ dumpfile->open(dump_red_fname.c_str());
+ if (!(*dumpfile)) {
+ cout
+ << "ERROR: Couldn't open file '"
+ << resultFilename
+ << "' for writing!"
+ << endl;
+ std::exit(-1);
+ }
+
+ bool ret = true;
+ vector<Lit> lits;
+ solver->start_getting_small_clauses(dump_red_max_len, dump_red_max_glue);
+ while(ret) {
+ ret = solver->get_next_small_clause(lits);
+ if (ret) {
+ *dumpfile << lits << " " << 0 << endl;
+ }
+ }
+ solver->end_getting_small_clauses();
+
+ delete dumpfile;
+}
+
+int Main::solve()
+{
+ solver = new SATSolver((void*)&conf);
+ solverToInterrupt = solver;
+ if (dratf) {
+ solver->set_drat(dratf, clause_ID_needed);
+ }
+ check_num_threads_sanity(num_threads);
+ solver->set_num_threads(num_threads);
+ if (sql != 0) {
+ solver->set_sqlite(sqlite_filename);
+ }
+
+ //Print command line used to execute the solver: for options and inputs
+ if (conf.verbosity) {
+ printVersionInfo();
+ cout
+ << "c Executed with command line: "
+ << commandLine
+ << endl;
+ }
+
+ solver->add_sql_tag("commandline", commandLine);
+ solver->add_sql_tag("verbosity", lexical_cast<string>(conf.verbosity));
+ solver->add_sql_tag("threads", lexical_cast<string>(num_threads));
+ solver->add_sql_tag("version", solver->get_version());
+ solver->add_sql_tag("SHA-revision", solver->get_version_sha1());
+ solver->add_sql_tag("env", solver->get_compilation_env());
+ #ifdef __GNUC__
+ solver->add_sql_tag("compiler", "gcc-" __VERSION__);
+ #else
+ solver->add_sql_tag("compiler", "non-gcc");
+ #endif
+
+ //Parse in DIMACS (maybe gzipped) files
+ //solver->log_to_file("mydump.cnf");
+ if (conf.preprocess != 2) {
+ parseInAllFiles(solver);
+ }
+
+ lbool ret = multi_solutions();
+
+ if (conf.preprocess != 1) {
+ if (ret == l_Undef && conf.verbosity) {
+ cout
+ << "c Not finished running -- signal caught or some maximum reached"
+ << endl;
+ }
+ if (conf.verbosity) {
+ solver->print_stats();
+ }
+ if (ret == l_True) {
+ dump_red_file();
+ }
+ }
+ printResultFunc(&cout, false, ret);
+ if (resultfile) {
+ printResultFunc(resultfile, true, ret);
+ }
+
+ return correctReturnValue(ret);
+}
+
+lbool Main::multi_solutions()
+{
+ unsigned long current_nr_of_solutions = 0;
+ lbool ret = l_True;
+ while(current_nr_of_solutions < max_nr_of_solutions && ret == l_True) {
+ ret = solver->solve(NULL, only_indep_solution);
+ current_nr_of_solutions++;
+
+ if (ret == l_True && current_nr_of_solutions < max_nr_of_solutions) {
+ printResultFunc(&cout, false, ret);
+ if (resultfile) {
+ printResultFunc(resultfile, true, ret);
+ }
+
+ if (conf.verbosity) {
+ cout
+ << "c Number of solutions found until now: "
+ << std::setw(6) << current_nr_of_solutions
+ << endl;
+ }
+ #ifdef VERBOSE_DEBUG_RECONSTRUCT
+ solver->print_removed_vars();
+ #endif
+
+ //Banning found solution
+ vector<Lit> lits;
+ if (independent_vars.empty()) {
+ for (uint32_t var = 0; var < solver->nVars(); var++) {
+ if (solver->get_model()[var] != l_Undef) {
+ lits.push_back( Lit(var, (solver->get_model()[var] == l_True)? true : false) );
+ }
+ }
+ } else {
+ for (const uint32_t var: independent_vars) {
+ if (solver->get_model()[var] != l_Undef) {
+ lits.push_back( Lit(var, (solver->get_model()[var] == l_True)? true : false) );
+ }
+ }
+ }
+ solver->add_clause(lits);
+ }
+ }
+ return ret;
+}
+
+///////////
+// Useful helper functions
+///////////
+
+void Main::printVersionInfo()
+{
+ cout << "c CryptoMiniSat version " << solver->get_version() << endl;
+ cout << "c CryptoMiniSat SHA revision " << solver->get_version_sha1() << endl;
+ #ifdef USE_GAUSS
+ cout << "c Using code from 'When Boolean Satisfiability Meets Gauss-E. in a Simplex Way'" << endl;
+ cout << "c by C.-S. Han and J.-H. Roland Jiang in CAV 2012. Fixes by M. Soos" << endl;
+ #endif
+ cout << "c CryptoMiniSat compilation env " << solver->get_compilation_env() << endl;
+ #ifdef __GNUC__
+ cout << "c CryptoMiniSat compiled with gcc version " << __VERSION__ << endl;
+ #else
+ cout << "c CryptoMiniSat compiled with non-gcc compiler" << endl;
+ #endif
+}
+
+int Main::correctReturnValue(const lbool ret) const
+{
+ int retval = -1;
+ if (ret == l_True) {
+ retval = 10;
+ } else if (ret == l_False) {
+ retval = 20;
+ } else if (ret == l_Undef) {
+ retval = 15;
+ } else {
+ std::cerr << "Something is very wrong, output is neither l_Undef, nor l_False, nor l_True" << endl;
+ exit(-1);
+ }
+
+ if (zero_exit_status) {
+ return 0;
+ } else {
+ return retval;
+ }
+}
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback