168 lines
5.4 KiB
C
168 lines
5.4 KiB
C
/**************************************************************************************************
|
|
MiniSat -- Copyright (c) 2003-2005, 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 "Solver.h"
|
|
#include <ctime>
|
|
#include <unistd.h>
|
|
#include <signal.h>
|
|
#include <zlib.h>
|
|
|
|
//=================================================================================================
|
|
// Helpers:
|
|
|
|
|
|
// Reads an input stream to end-of-file and returns the result as a 'char*' terminated by '\0'
|
|
// (dynamic allocation in case 'in' is standard input).
|
|
//
|
|
char* readFile(gzFile in)
|
|
{
|
|
char* data = xmalloc<char>(65536);
|
|
int cap = 65536;
|
|
int size = 0;
|
|
|
|
while (!gzeof(in)){
|
|
if (size == cap){
|
|
cap *= 2;
|
|
data = xrealloc(data, cap); }
|
|
size += gzread(in, &data[size], 65536);
|
|
}
|
|
data = xrealloc(data, size+1);
|
|
data[size] = '\0';
|
|
|
|
return data;
|
|
}
|
|
|
|
|
|
//=================================================================================================
|
|
// DIMACS Parser:
|
|
|
|
|
|
static void skipWhitespace(char*& in) {
|
|
while ((*in >= 9 && *in <= 13) || *in == 32)
|
|
in++; }
|
|
|
|
static void skipLine(char*& in) {
|
|
for (;;){
|
|
if (*in == 0) return;
|
|
if (*in == '\n') { in++; return; }
|
|
in++; } }
|
|
|
|
static int parseInt(char*& in) {
|
|
int val = 0;
|
|
bool neg = false;
|
|
skipWhitespace(in);
|
|
if (*in == '-') neg = true, in++;
|
|
else if (*in == '+') in++;
|
|
if (*in < '0' || *in > '9') fprintf(stderr, "PARSE ERROR! Unexpected char: %c\n", *in), exit(1);
|
|
while (*in >= '0' && *in <= '9')
|
|
val = val*10 + (*in - '0'),
|
|
in++;
|
|
return neg ? -val : val; }
|
|
|
|
static void readClause(char*& in, Solver& 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) );
|
|
}
|
|
}
|
|
|
|
static bool parse_DIMACS_main(char* in, Solver& S) {
|
|
vec<Lit> lits;
|
|
for (;;){
|
|
skipWhitespace(in);
|
|
if (*in == 0)
|
|
break;
|
|
else if (*in == 'c' || *in == 'p')
|
|
skipLine(in);
|
|
else{
|
|
readClause(in, S, lits);
|
|
S.addClause(lits);
|
|
if (!S.okay())
|
|
return false;
|
|
}
|
|
}
|
|
S.simplifyDB();
|
|
return S.okay();
|
|
}
|
|
|
|
|
|
// Inserts problem into solver. Returns FALSE upon immediate conflict.
|
|
//
|
|
bool parse_DIMACS(gzFile in, Solver& S) {
|
|
char* text = readFile(in);
|
|
bool ret = parse_DIMACS_main(text, S);
|
|
free(text);
|
|
return ret; }
|
|
|
|
|
|
//=================================================================================================
|
|
|
|
|
|
void printStats(SolverStats& stats, double cpu_time)
|
|
{
|
|
printf("restarts : %"I64_fmt"\n", stats.starts);
|
|
printf("conflicts : %-12"I64_fmt" (%.0f /sec)\n", stats.conflicts , stats.conflicts /cpu_time);
|
|
printf("decisions : %-12"I64_fmt" (%.0f /sec)\n", stats.decisions , stats.decisions /cpu_time);
|
|
printf("propagations : %-12"I64_fmt" (%.0f /sec)\n", stats.propagations, stats.propagations/cpu_time);
|
|
printf("inspects : %-12"I64_fmt" (%.0f /sec)\n", stats.inspects , stats.inspects /cpu_time);
|
|
printf("CPU time : %g s\n", cpu_time);
|
|
}
|
|
|
|
Solver* solver;
|
|
static void SIGINT_handler(int signum) {
|
|
printf("\n"); printf("*** INTERRUPTED ***\n");
|
|
printStats(solver->stats, cpuTime());
|
|
printf("\n"); printf("*** INTERRUPTED ***\n");
|
|
exit(0); }
|
|
|
|
|
|
//=================================================================================================
|
|
|
|
|
|
int main(int argc, char** argv)
|
|
{
|
|
Solver S;
|
|
bool st;
|
|
|
|
gzFile in = argc == 1 ? gzdopen(0, "rb") : gzopen(argv[1], "rb");
|
|
if (in == NULL)
|
|
fprintf(stderr, "ERROR! Could not open file: %s\n", argc == 1 ? "<stdin>" : argv[1]),
|
|
exit(1);
|
|
st = parse_DIMACS(in, S);
|
|
gzclose(in);
|
|
|
|
if (!st)
|
|
printf("Trivial problem\nUNSATISFIABLE\n"),
|
|
exit(20);
|
|
|
|
S.verbosity = 1;
|
|
solver = &S;
|
|
signal(SIGINT,SIGINT_handler);
|
|
st = S.solve();
|
|
printStats(S.stats, cpuTime());
|
|
printf("\n");
|
|
printf(st ? "SATISFIABLE\n" : "UNSATISFIABLE\n");
|
|
|
|
return 0;
|
|
}
|