#include "picosat.h" #include #include #include #include #include #include #include #define GUNZIP "gunzip -c %s" #define BUNZIP2 "bzcat %s" #define GZIP "gzip -c -f > %s" #ifndef NZIP FILE * popen (const char *, const char*); int pclose (FILE *); #endif static PicoSAT * picosat; static int lineno; static FILE *input; static int inputid; static FILE *output; static int verbose; static int sargc; static char ** sargv; static char buffer[100]; static char *bhead = buffer; static const char *eob = buffer + 80; static FILE * incremental_rup_file; static signed char * sol; extern void picosat_enter (PicoSAT *); extern void picosat_leave (PicoSAT *); static int next (void) { int res = getc (input); if (res == '\n') lineno++; return res; } static const char * parse (PicoSAT * picosat, int force) { int ch, sign, lit, vars, clauses; lineno = 1; /* DM inputid = fileno (input); */ SKIP_COMMENTS: ch = next (); if (ch == 'c') { while ((ch = next ()) != EOF && ch != '\n') ; goto SKIP_COMMENTS; } if (isspace (ch)) goto SKIP_COMMENTS; if (ch != 'p') INVALID_HEADER: return "missing or invalid 'p cnf ' header"; if (!isspace (next ())) goto INVALID_HEADER; while (isspace (ch = next ())) ; if (ch != 'c' || next () != 'n' || next () != 'f' || !isspace (next ())) goto INVALID_HEADER; while (isspace (ch = next ())) ; if (!isdigit (ch)) goto INVALID_HEADER; vars = ch - '0'; while (isdigit (ch = next ())) vars = 10 * vars + (ch - '0'); if (!isspace (ch)) goto INVALID_HEADER; while (isspace (ch = next ())) ; if (!isdigit (ch)) goto INVALID_HEADER; clauses = ch - '0'; while (isdigit (ch = next ())) clauses = 10 * clauses + (ch - '0'); if (!isspace (ch) && ch != '\n' ) goto INVALID_HEADER; if (verbose) { fprintf (output, "c parsed header 'p cnf %d %d'\n", vars, clauses); fflush (output); } picosat_adjust (picosat, vars); if (incremental_rup_file) picosat_set_incremental_rup_file (picosat, incremental_rup_file, vars, clauses); lit = 0; READ_LITERAL: ch = next (); if (ch == 'c') { while ((ch = next ()) != EOF && ch != '\n') ; goto READ_LITERAL; } if (ch == EOF) { if (lit) return "trailing 0 missing"; if (clauses && !force) return "clause missing"; return 0; } if (isspace (ch)) goto READ_LITERAL; sign = 1; if (ch == '-') { sign = -1; ch = next (); } if (!isdigit (ch)) return "expected number"; lit = ch - '0'; while (isdigit (ch = next ())) lit = 10 * lit + (ch - '0'); if (!clauses && !force) return "too many clauses"; if (lit) { if (lit > vars && !force) return "maximal variable index exceeded"; lit *= sign; } else clauses--; picosat_add (picosat, lit); goto READ_LITERAL; } static void bflush (void) { *bhead = 0; fputs (buffer, output); fputc ('\n', output); bhead = buffer; } static void printi (int i) { char *next; int l; REENTER: if (bhead == buffer) *bhead++ = 'v'; l = sprintf (bhead, " %d", i); next = bhead + l; if (next >= eob) { bflush (); goto REENTER; } else bhead = next; } static void printa (PicoSAT * picosat, int partial) { int max_idx = picosat_variables (picosat), i, lit, val; assert (bhead == buffer); for (i = 1; i <= max_idx; i++) { if (partial) { val = picosat_deref_partial (picosat, i); if (!val) continue; } else val = picosat_deref (picosat, i); lit = (val > 0) ? i : -i; printi (lit); } printi (0); if (bhead > buffer) bflush (); } static void blocksol (PicoSAT * picosat) { int max_idx = picosat_variables (picosat), i; if (!sol) { sol = malloc (max_idx + 1); memset (sol, 0, max_idx + 1); } for (i = 1; i <= max_idx; i++) sol[i] = (picosat_deref (picosat, i) > 0) ? 1 : -1; for (i = 1; i <= max_idx; i++) picosat_add (picosat, (sol[i] < 0) ? i : -i); picosat_add (picosat, 0); } static int has_suffix (const char *str, const char *suffix) { const char *tmp = strstr (str, suffix); if (!tmp) return 0; return str + strlen (str) - strlen (suffix) == tmp; } static void write_core_variables (PicoSAT * picosat, FILE * file) { int i, max_idx = picosat_variables (picosat), count = 0; for (i = 1; i <= max_idx; i++) if (picosat_corelit (picosat, i)) { fprintf (file, "%d\n", i); count++; } if (verbose) fprintf (output, "c found and wrote %d core variables\n", count); } static int next_assumption (int start) { char * arg, c; int res; res = start + 1; while (res < sargc) { arg = sargv[res++]; if (!strcmp (arg, "-a")) { assert (res < sargc); break; } if (arg[0] == '-') { c = arg[1]; if (c == 'l' || c == 'i' || c == 's' || c == 'o' || c == 't' || c == 'T' || c == 'r' || c == 'R' || c == 'c' || c == 'V' || c == 'U' || c == 'A') res++; } } if (res >= sargc) res = 0; return res; } static void write_failed_assumptions (PicoSAT * picosat, FILE * file) { int i, lit, count = 0; #ifndef NDEBUG int max_idx = picosat_variables (picosat); #endif i = 0; while ((i = next_assumption (i))) { lit = atoi (sargv[i]); if (!picosat_failed_assumption (picosat, lit)) continue; fprintf (file, "%d\n", lit); count++; } if (verbose) fprintf (output, "c found and wrote %d failed assumptions\n", count); #ifndef NDEBUG for (i = 1; i <= max_idx; i++) if (picosat_failed_assumption (picosat, i)) count--; #endif assert (!count); } static void write_to_file (PicoSAT * picosat, const char *name, const char *type, void (*writer) (PicoSAT *, FILE *)) { int pclose_file, zipped = has_suffix (name, ".gz"); FILE *file; char *cmd; if (zipped) { #ifdef NZIP file = NULL; #else cmd = malloc (strlen (GZIP) + strlen (name)); sprintf (cmd, GZIP, name); file = popen (cmd, "w"); free (cmd); pclose_file = 1; #endif } else { file = fopen (name, "w"); pclose_file = 0; } if (file) { if (verbose) fprintf (output, "c\nc writing %s%s to '%s'\n", zipped ? "gzipped " : "", type, name); writer (picosat, file); #ifndef NZIP if (pclose_file) pclose (file); else #endif fclose (file); } else fprintf (output, "*** picosat: can not write to '%s'\n", name); } static int catched; static void (*sig_int_handler); static void (*sig_segv_handler); static void (*sig_abrt_handler); static void (*sig_term_handler); #ifndef NALLSIGNALS static void (*sig_kill_handler); static void (*sig_xcpu_handler); static void (*sig_xfsz_handler); #endif static void resetsighandlers (void) { (void) signal (SIGINT, sig_int_handler); (void) signal (SIGSEGV, sig_segv_handler); (void) signal (SIGABRT, sig_abrt_handler); (void) signal (SIGTERM, sig_term_handler); #ifndef NALLSIGNALS (void) signal (SIGKILL, sig_kill_handler); (void) signal (SIGXCPU, sig_xcpu_handler); (void) signal (SIGXFSZ, sig_xfsz_handler); #endif } static int time_limit_in_seconds; static void (*sig_alarm_handler); static int ought_to_be_interrupted, interrupt_notified; static void alarm_triggered (int sig) { (void) sig; assert (sig == SIGALRM); assert (time_limit_in_seconds); assert (!ought_to_be_interrupted); ought_to_be_interrupted = 1; assert (!interrupt_notified); } static int interrupt_call_back (void * dummy) { (void) dummy; if (!ought_to_be_interrupted) return 0; if (!interrupt_notified) { if (verbose) { picosat_message (picosat, 1, ""); picosat_message (picosat, 1, "*** TIME LIMIT OF %d SECONDS REACHED ***", time_limit_in_seconds); picosat_message (picosat, 1, ""); } interrupt_notified = 1; } return 1; } static void setalarm () { #ifndef NALARM assert (time_limit_in_seconds > 0); sig_alarm_handler = signal (SIGALRM, alarm_triggered); alarm (time_limit_in_seconds); assert (picosat); picosat_set_interrupt (picosat, 0, interrupt_call_back); #endif } static void resetalarm () { assert (time_limit_in_seconds > 0); (void) signal (SIGALRM, sig_term_handler); } static void message (int sig) { picosat_message (picosat, 1, ""); picosat_message (picosat, 1, "*** CAUGHT SIGNAL %d ***", sig); picosat_message (picosat, 1, ""); } static void catch (int sig) { if (!catched) { message (sig); catched = 1; picosat_stats (picosat); message (sig); } resetsighandlers (); raise (sig); } static void setsighandlers (void) { sig_int_handler = signal (SIGINT, catch); sig_segv_handler = signal (SIGSEGV, catch); sig_abrt_handler = signal (SIGABRT, catch); sig_term_handler = signal (SIGTERM, catch); #ifndef NALLSIGNALS sig_kill_handler = signal (SIGKILL, catch); sig_xcpu_handler = signal (SIGXCPU, catch); sig_xfsz_handler = signal (SIGXFSZ, catch); #endif } #define USAGE \ "usage: picosat [