diff options
author | Morgan Deters <mdeters@gmail.com> | 2009-11-17 17:06:57 +0000 |
---|---|---|
committer | Morgan Deters <mdeters@gmail.com> | 2009-11-17 17:06:57 +0000 |
commit | 61330b862f7b5565f70e3c1f4d26a8c51a0f534a (patch) | |
tree | 60d102ef1e49ee8b1f0b905a5620d2d823c3ba34 /src/prop/minisat/simp/Main.C | |
parent | 0201aa29bea8467e5cc07f2d0af68a4da3e86ec1 (diff) |
from meeting
Diffstat (limited to 'src/prop/minisat/simp/Main.C')
-rw-r--r-- | src/prop/minisat/simp/Main.C | 415 |
1 files changed, 415 insertions, 0 deletions
diff --git a/src/prop/minisat/simp/Main.C b/src/prop/minisat/simp/Main.C new file mode 100644 index 000000000..b6d194631 --- /dev/null +++ b/src/prop/minisat/simp/Main.C @@ -0,0 +1,415 @@ +/******************************************************************************************[Main.C] +MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson + +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 <ctime> +#include <cstring> +#include <stdint.h> +#include <errno.h> + +#include <signal.h> +#include <zlib.h> + +#include "SimpSolver.h" + +/*************************************************************************************/ +#ifdef _MSC_VER +#include <ctime> + +static inline double cpuTime(void) { + return (double)clock() / CLOCKS_PER_SEC; } +#else + +#include <sys/time.h> +#include <sys/resource.h> +#include <unistd.h> + +static inline double cpuTime(void) { + struct rusage ru; + getrusage(RUSAGE_SELF, &ru); + return (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec / 1000000; } +#endif + + +#if defined(__linux__) +static inline int memReadStat(int field) +{ + char name[256]; + pid_t pid = getpid(); + sprintf(name, "/proc/%d/statm", pid); + FILE* in = fopen(name, "rb"); + if (in == NULL) return 0; + int value; + for (; field >= 0; field--) + fscanf(in, "%d", &value); + fclose(in); + return value; +} +static inline uint64_t memUsed() { return (uint64_t)memReadStat(0) * (uint64_t)getpagesize(); } + + +#elif defined(__FreeBSD__) +static inline uint64_t memUsed(void) { + struct rusage ru; + getrusage(RUSAGE_SELF, &ru); + return ru.ru_maxrss*1024; } + + +#else +static inline uint64_t memUsed() { return 0; } +#endif + +#if defined(__linux__) +#include <fpu_control.h> +#endif + + +//================================================================================================= +// DIMACS Parser: + +#define CHUNK_LIMIT 1048576 + +class StreamBuffer { + gzFile in; + char buf[CHUNK_LIMIT]; + int pos; + int size; + + void assureLookahead() { + if (pos >= size) { + pos = 0; + size = gzread(in, buf, sizeof(buf)); } } + +public: + StreamBuffer(gzFile i) : in(i), pos(0), size(0) { + assureLookahead(); } + + int operator * () { return (pos >= size) ? EOF : buf[pos]; } + void operator ++ () { pos++; assureLookahead(); } +}; + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template<class B> +static void skipWhitespace(B& in) { + while ((*in >= 9 && *in <= 13) || *in == 32) + ++in; } + +template<class B> +static void skipLine(B& in) { + for (;;){ + if (*in == EOF || *in == '\0') return; + if (*in == '\n') { ++in; return; } + ++in; } } + +template<class B> +static int parseInt(B& in) { + int val = 0; + bool neg = false; + skipWhitespace(in); + if (*in == '-') neg = true, ++in; + else if (*in == '+') ++in; + if (*in < '0' || *in > '9') reportf("PARSE ERROR! Unexpected char: %c\n", *in), exit(3); + while (*in >= '0' && *in <= '9') + val = val*10 + (*in - '0'), + ++in; + return neg ? -val : val; } + +template<class B> +static void readClause(B& in, SimpSolver& S, vec<Lit>& lits) { + int parsed_lit, var; + lits.clear(); + for (;;){ + parsed_lit = parseInt(in); + if (parsed_lit == 0) break; + var = abs(parsed_lit)-1; + while (var >= S.nVars()) S.newVar(); + lits.push( (parsed_lit > 0) ? Lit(var) : ~Lit(var) ); + } +} + +template<class B> +static bool match(B& in, char* str) { + for (; *str != 0; ++str, ++in) + if (*str != *in) + return false; + return true; +} + + +template<class B> +static void parse_DIMACS_main(B& in, SimpSolver& S) { + vec<Lit> lits; + for (;;){ + skipWhitespace(in); + if (*in == EOF) break; + else if (*in == 'p'){ + if (match(in, "p cnf")){ + int vars = parseInt(in); + int clauses = parseInt(in); + reportf("| Number of variables: %-12d |\n", vars); + reportf("| Number of clauses: %-12d |\n", clauses); + + // SATRACE'06 hack + if (clauses > 4000000) + S.eliminate(true); + }else{ + reportf("PARSE ERROR! Unexpected char: %c\n", *in), exit(3); + } + } else if (*in == 'c' || *in == 'p') + skipLine(in); + else{ + readClause(in, S, lits); + S.addClause(lits); } + } +} + +// Inserts problem into solver. +// +static void parse_DIMACS(gzFile input_stream, SimpSolver& S) { + StreamBuffer in(input_stream); + parse_DIMACS_main(in, S); } + + +//================================================================================================= + + +void printStats(Solver& S) +{ + double cpu_time = cpuTime(); + uint64_t mem_used = memUsed(); + reportf("restarts : %lld\n", S.starts); + reportf("conflicts : %-12lld (%.0f /sec)\n", S.conflicts , S.conflicts /cpu_time); + reportf("decisions : %-12lld (%4.2f %% random) (%.0f /sec)\n", S.decisions, (float)S.rnd_decisions*100 / (float)S.decisions, S.decisions /cpu_time); + reportf("propagations : %-12lld (%.0f /sec)\n", S.propagations, S.propagations/cpu_time); + reportf("conflict literals : %-12lld (%4.2f %% deleted)\n", S.tot_literals, (S.max_literals - S.tot_literals)*100 / (double)S.max_literals); + if (mem_used != 0) reportf("Memory used : %.2f MB\n", mem_used / 1048576.0); + reportf("CPU time : %g s\n", cpu_time); +} + +SimpSolver* solver; +static void SIGINT_handler(int signum) { + reportf("\n"); reportf("*** INTERRUPTED ***\n"); + printStats(*solver); + reportf("\n"); reportf("*** INTERRUPTED ***\n"); + exit(1); } + + +//================================================================================================= +// Main: + +void printUsage(char** argv) +{ + reportf("USAGE: %s [options] <input-file> <result-output-file>\n\n where input may be either in plain or gzipped DIMACS.\n\n", argv[0]); + reportf("OPTIONS:\n\n"); + reportf(" -pre = {none,once}\n"); + reportf(" -asymm\n"); + reportf(" -rcheck\n"); + reportf(" -grow = <num> [ >0 ]\n"); + reportf(" -polarity-mode = {true,false,rnd}\n"); + reportf(" -decay = <num> [ 0 - 1 ]\n"); + reportf(" -rnd-freq = <num> [ 0 - 1 ]\n"); + reportf(" -dimacs = <output-file>\n"); + reportf(" -verbosity = {0,1,2}\n"); + reportf("\n"); +} + +typedef enum { pre_none, pre_once, pre_repeat } preprocessMode; + +const char* hasPrefix(const char* str, const char* prefix) +{ + int len = strlen(prefix); + if (strncmp(str, prefix, len) == 0) + return str + len; + else + return NULL; +} + + +int main(int argc, char** argv) +{ + reportf("This is MiniSat 2.0 beta\n"); +#if defined(__linux__) + fpu_control_t oldcw, newcw; + _FPU_GETCW(oldcw); newcw = (oldcw & ~_FPU_EXTENDED) | _FPU_DOUBLE; _FPU_SETCW(newcw); + reportf("WARNING: for repeatability, setting FPU to use double precision\n"); +#endif + preprocessMode pre = pre_once; + const char* dimacs = NULL; + const char* freeze = NULL; + SimpSolver S; + S.verbosity = 1; + + // This just grew and grew, and I didn't have time to do sensible argument parsing yet :) + // + int i, j; + const char* value; + for (i = j = 0; i < argc; i++){ + if ((value = hasPrefix(argv[i], "-polarity-mode="))){ + if (strcmp(value, "true") == 0) + S.polarity_mode = Solver::polarity_true; + else if (strcmp(value, "false") == 0) + S.polarity_mode = Solver::polarity_false; + else if (strcmp(value, "rnd") == 0) + S.polarity_mode = Solver::polarity_rnd; + else{ + reportf("ERROR! unknown polarity-mode %s\n", value); + exit(0); } + + }else if ((value = hasPrefix(argv[i], "-rnd-freq="))){ + double rnd; + if (sscanf(value, "%lf", &rnd) <= 0 || rnd < 0 || rnd > 1){ + reportf("ERROR! illegal rnd-freq constant %s\n", value); + exit(0); } + S.random_var_freq = rnd; + + }else if ((value = hasPrefix(argv[i], "-decay="))){ + double decay; + if (sscanf(value, "%lf", &decay) <= 0 || decay <= 0 || decay > 1){ + reportf("ERROR! illegal decay constant %s\n", value); + exit(0); } + S.var_decay = 1 / decay; + + }else if ((value = hasPrefix(argv[i], "-verbosity="))){ + int verbosity = (int)strtol(value, NULL, 10); + if (verbosity == 0 && errno == EINVAL){ + reportf("ERROR! illegal verbosity level %s\n", value); + exit(0); } + S.verbosity = verbosity; + + }else if ((value = hasPrefix(argv[i], "-pre="))){ + if (strcmp(value, "none") == 0) + pre = pre_none; + else if (strcmp(value, "once") == 0) + pre = pre_once; + else if (strcmp(value, "repeat") == 0){ + pre = pre_repeat; + reportf("ERROR! preprocessing mode \"repeat\" is not supported at the moment.\n"); + exit(0); + }else{ + reportf("ERROR! unknown preprocessing mode %s\n", value); + exit(0); } + }else if (strcmp(argv[i], "-asymm") == 0){ + S.asymm_mode = true; + }else if (strcmp(argv[i], "-rcheck") == 0){ + S.redundancy_check = true; + }else if ((value = hasPrefix(argv[i], "-grow="))){ + int grow = (int)strtol(value, NULL, 10); + if (grow == 0 && errno == EINVAL){ + reportf("ERROR! illegal grow constant %s\n", &argv[i][6]); + exit(0); } + S.grow = grow; + }else if ((value = hasPrefix(argv[i], "-dimacs="))){ + dimacs = value; + }else if ((value = hasPrefix(argv[i], "-freeze="))){ + freeze = value; + }else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-help") == 0){ + printUsage(argv); + exit(0); + }else if (strncmp(argv[i], "-", 1) == 0){ + reportf("ERROR! unknown flag %s\n", argv[i]); + exit(0); + }else + argv[j++] = argv[i]; + } + argc = j; + + double cpu_time = cpuTime(); + + if (pre == pre_none) + S.eliminate(true); + + solver = &S; + signal(SIGINT,SIGINT_handler); + signal(SIGHUP,SIGINT_handler); + + if (argc == 1) + reportf("Reading from standard input... Use '-h' or '--help' for help.\n"); + + gzFile in = (argc == 1) ? gzdopen(0, "rb") : gzopen(argv[1], "rb"); + if (in == NULL) + reportf("ERROR! Could not open file: %s\n", argc == 1 ? "<stdin>" : argv[1]), exit(1); + + reportf("============================[ Problem Statistics ]=============================\n"); + reportf("| |\n"); + + parse_DIMACS(in, S); + gzclose(in); + FILE* res = (argc >= 3) ? fopen(argv[2], "wb") : NULL; + + + double parse_time = cpuTime() - cpu_time; + reportf("| Parsing time: %-12.2f s |\n", parse_time); + + /*HACK: Freeze variables*/ + if (freeze != NULL && pre != pre_none){ + int count = 0; + FILE* in = fopen(freeze, "rb"); + for(;;){ + Var x; + fscanf(in, "%d", &x); + if (x == 0) break; + x--; + + /**/assert(S.n_occ[toInt(Lit(x))] + S.n_occ[toInt(~Lit(x))] != 0); + /**/assert(S.value(x) == l_Undef); + S.setFrozen(x, true); + count++; + } + fclose(in); + reportf("| Frozen vars : %-12.0f |\n", (double)count); + } + /*END*/ + + if (!S.simplify()){ + reportf("Solved by unit propagation\n"); + if (res != NULL) fprintf(res, "UNSAT\n"), fclose(res); + printf("UNSATISFIABLE\n"); + exit(20); + } + + if (dimacs){ + if (pre != pre_none) + S.eliminate(true); + reportf("==============================[ Writing DIMACS ]===============================\n"); + S.toDimacs(dimacs); + printStats(S); + exit(0); + }else{ + bool ret = S.solve(true, true); + printStats(S); + reportf("\n"); + + printf(ret ? "SATISFIABLE\n" : "UNSATISFIABLE\n"); + if (res != NULL){ + if (ret){ + fprintf(res, "SAT\n"); + for (int i = 0; i < S.nVars(); i++) + if (S.model[i] != l_Undef) + fprintf(res, "%s%s%d", (i==0)?"":" ", (S.model[i]==l_True)?"":"-", i+1); + fprintf(res, " 0\n"); + }else + fprintf(res, "UNSAT\n"); + fclose(res); + } +#ifdef NDEBUG + exit(ret ? 10 : 20); // (faster than "return", which will invoke the destructor for 'Solver') +#endif + } + +} |