1 /******************************************************************************************[Main.C]
2 MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
4 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
5 associated documentation files (the "Software"), to deal in the Software without restriction,
6 including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 furnished to do so, subject to the following conditions:
10 The above copyright notice and this permission notice shall be included in all copies or
11 substantial portions of the Software.
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
14 NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
17 OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 **************************************************************************************************/
30 /*************************************************************************************/
34 static inline double cpuTime(void) {
35 return (double)clock() / CLOCKS_PER_SEC; }
39 #include <sys/resource.h>
42 static inline double cpuTime(void) {
44 getrusage(RUSAGE_SELF, &ru);
45 return (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec / 1000000; }
49 #if defined(__linux__)
50 static inline int memReadStat(int field)
54 sprintf(name, "/proc/%d/statm", pid);
55 FILE* in = fopen(name, "rb");
56 if (in == NULL) return 0;
58 for (; field >= 0; field--)
59 fscanf(in, "%d", &value);
63 static inline uint64_t memUsed() { return (uint64_t)memReadStat(0) * (uint64_t)getpagesize(); }
66 #elif defined(__FreeBSD__)
67 static inline uint64_t memUsed(void) {
69 getrusage(RUSAGE_SELF, &ru);
70 return ru.ru_maxrss*1024; }
74 static inline uint64_t memUsed() { return 0; }
77 #if defined(__linux__)
78 #include <fpu_control.h>
81 //=================================================================================================
84 #define CHUNK_LIMIT 1048576
88 char buf[CHUNK_LIMIT];
92 void assureLookahead() {
95 size = gzread(in, buf, sizeof(buf)); } }
98 StreamBuffer(gzFile i) : in(i), pos(0), size(0) {
101 int operator * () { return (pos >= size) ? EOF : buf[pos]; }
102 void operator ++ () { pos++; assureLookahead(); }
105 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
108 static void skipWhitespace(B& in) {
109 while ((*in >= 9 && *in <= 13) || *in == 32)
113 static void skipLine(B& in) {
115 if (*in == EOF || *in == '\0') return;
116 if (*in == '\n') { ++in; return; }
120 static int parseInt(B& in) {
124 if (*in == '-') neg = true, ++in;
125 else if (*in == '+') ++in;
126 if (*in < '0' || *in > '9') reportf("PARSE ERROR! Unexpected char: %c\n", *in), exit(3);
127 while (*in >= '0' && *in <= '9')
128 val = val*10 + (*in - '0'),
130 return neg ? -val : val; }
133 static void readClause(B& in, Solver& S, vec<Lit>& lits) {
137 parsed_lit = parseInt(in);
138 if (parsed_lit == 0) break;
139 var = abs(parsed_lit)-1;
140 while (var >= S.nVars()) S.newVar();
141 lits.push( (parsed_lit > 0) ? Lit(var) : ~Lit(var) );
146 static bool match(B& in, char* str) {
147 for (; *str != 0; ++str, ++in)
155 static void parse_DIMACS_main(B& in, Solver& S) {
161 else if (*in == 'p'){
162 if (match(in, "p cnf")){
163 int vars = parseInt(in);
164 int clauses = parseInt(in);
165 reportf("| Number of variables: %-12d |\n", vars);
166 reportf("| Number of clauses: %-12d |\n", clauses);
168 reportf("PARSE ERROR! Unexpected char: %c\n", *in), exit(3);
170 } else if (*in == 'c' || *in == 'p')
173 readClause(in, S, lits),
178 // Inserts problem into solver.
180 static void parse_DIMACS(gzFile input_stream, Solver& S) {
181 StreamBuffer in(input_stream);
182 parse_DIMACS_main(in, S); }
185 //=================================================================================================
188 void printStats(Solver& solver)
190 double cpu_time = cpuTime();
191 uint64_t mem_used = memUsed();
192 reportf("restarts : %lld\n", solver.starts);
193 reportf("conflicts : %-12lld (%.0f /sec)\n", solver.conflicts , solver.conflicts /cpu_time);
194 reportf("decisions : %-12lld (%4.2f %% random) (%.0f /sec)\n", solver.decisions, (float)solver.rnd_decisions*100 / (float)solver.decisions, solver.decisions /cpu_time);
195 reportf("propagations : %-12lld (%.0f /sec)\n", solver.propagations, solver.propagations/cpu_time);
196 reportf("conflict literals : %-12lld (%4.2f %% deleted)\n", solver.tot_literals, (solver.max_literals - solver.tot_literals)*100 / (double)solver.max_literals);
197 if (mem_used != 0) reportf("Memory used : %.2f MB\n", mem_used / 1048576.0);
198 reportf("CPU time : %g s\n", cpu_time);
202 static void SIGINT_handler(int signum) {
203 reportf("\n"); reportf("*** INTERRUPTED ***\n");
205 reportf("\n"); reportf("*** INTERRUPTED ***\n");
209 //=================================================================================================
212 void printUsage(char** argv)
214 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]);
215 reportf("OPTIONS:\n\n");
216 reportf(" -polarity-mode = {true,false,rnd}\n");
217 reportf(" -decay = <num> [ 0 - 1 ]\n");
218 reportf(" -rnd-freq = <num> [ 0 - 1 ]\n");
219 reportf(" -verbosity = {0,1,2}\n");
224 const char* hasPrefix(const char* str, const char* prefix)
226 int len = strlen(prefix);
227 if (strncmp(str, prefix, len) == 0)
234 int main(int argc, char** argv)
242 for (i = j = 0; i < argc; i++){
243 if ((value = hasPrefix(argv[i], "-polarity-mode="))){
244 if (strcmp(value, "true") == 0)
245 S.polarity_mode = Solver::polarity_true;
246 else if (strcmp(value, "false") == 0)
247 S.polarity_mode = Solver::polarity_false;
248 else if (strcmp(value, "rnd") == 0)
249 S.polarity_mode = Solver::polarity_rnd;
251 reportf("ERROR! unknown polarity-mode %s\n", value);
254 }else if ((value = hasPrefix(argv[i], "-rnd-freq="))){
256 if (sscanf(value, "%lf", &rnd) <= 0 || rnd < 0 || rnd > 1){
257 reportf("ERROR! illegal rnd-freq constant %s\n", value);
259 S.random_var_freq = rnd;
261 }else if ((value = hasPrefix(argv[i], "-decay="))){
263 if (sscanf(value, "%lf", &decay) <= 0 || decay <= 0 || decay > 1){
264 reportf("ERROR! illegal decay constant %s\n", value);
266 S.var_decay = 1 / decay;
268 }else if ((value = hasPrefix(argv[i], "-verbosity="))){
269 int verbosity = (int)strtol(value, NULL, 10);
270 if (verbosity == 0 && errno == EINVAL){
271 reportf("ERROR! illegal verbosity level %s\n", value);
273 S.verbosity = verbosity;
275 }else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-help") == 0 || strcmp(argv[i], "--help") == 0){
279 }else if (strncmp(argv[i], "-", 1) == 0){
280 reportf("ERROR! unknown flag %s\n", argv[i]);
289 reportf("This is MiniSat 2.0 beta\n");
290 #if defined(__linux__)
291 fpu_control_t oldcw, newcw;
292 _FPU_GETCW(oldcw); newcw = (oldcw & ~_FPU_EXTENDED) | _FPU_DOUBLE; _FPU_SETCW(newcw);
293 reportf("WARNING: for repeatability, setting FPU to use double precision\n");
295 double cpu_time = cpuTime();
298 signal(SIGINT,SIGINT_handler);
299 signal(SIGHUP,SIGINT_handler);
302 reportf("Reading from standard input... Use '-h' or '--help' for help.\n");
304 gzFile in = (argc == 1) ? gzdopen(0, "rb") : gzopen(argv[1], "rb");
306 reportf("ERROR! Could not open file: %s\n", argc == 1 ? "<stdin>" : argv[1]), exit(1);
308 reportf("============================[ Problem Statistics ]=============================\n");
313 FILE* res = (argc >= 3) ? fopen(argv[2], "wb") : NULL;
315 double parse_time = cpuTime() - cpu_time;
316 reportf("| Parsing time: %-12.2f s |\n", parse_time);
319 reportf("Solved by unit propagation\n");
320 if (res != NULL) fprintf(res, "UNSAT\n"), fclose(res);
321 printf("UNSATISFIABLE\n");
325 bool ret = S.solve();
328 printf(ret ? "SATISFIABLE\n" : "UNSATISFIABLE\n");
331 fprintf(res, "SAT\n");
332 for (int i = 0; i < S.nVars(); i++)
333 if (S.model[i] != l_Undef)
334 fprintf(res, "%s%s%d", (i==0)?"":" ", (S.model[i]==l_True)?"":"-", i+1);
335 fprintf(res, " 0\n");
337 fprintf(res, "UNSAT\n");
342 exit(ret ? 10 : 20); // (faster than "return", which will invoke the destructor for 'Solver')