How to use CryptoMiniSat 2.9 as a library | Wonderings of a SAT geek

# How to use CryptoMiniSat 2.9 as a library

June 20, 2012 Development, SAT library, programming msoos

There have been some questions asked about how to use CryptoMiniSat as a library. Here, I give a simple example usage to help any future potential users. If there are any question that seems unanswered, please feel free to add them as a comment to this post.

First, we initialize the solver with high verbosity:

    #include "cmsat/Solver.h"
    using namespace CMSat;

    SolverConf conf;
    conf.verbosity = 2;
    Solver solver(conf);

Then we add the variables 0..9:

    for(int i = 0; i < 10; i++) {
      solver.newVar();
    }

And add a clause that would look in the DIMACS input format as "2 -5 10 0":

    vec clause;
    clause.push(Lit(1, false));
    clause.push(Lit(4, true));
    clause.push(Lit(9, false));
    solver.addClause(clause);

We now create the assumptions that would look in DIMACS input format as "1 0" and "-5 0":

    vec assumps;
    assumps.push(Lit(0, false));
    assumps.push(Lit(4, true));

We now solve with these assumptions:

    lbool ret = solver.solve(assumps);

Let's see if the state of the solver after solving is UNSAT regardless of the assumptions:

    if (!solver.okay()) {
      printf("UNSAT!\n");
      exit(0);
    }

Note that okay() can only be FALSE if "ret" was "l_False". However, it is important to distinguish between two kinds of l_False: one where only the assumptions couldn't be satisfied, and one where no matter what the assumptions are, the problem is unsatisfiable. See below for more.

Now let's check that the solution is UNSAT relative to the assumptions we have given. In this case, let's print the conflicting clause:

    if (ret == l_False) {
      printf("Conflict clause expressed in terms of the assumptions:\n");
      for(unsigned i = 0; i != solver.conflict.size(); i++) {
        printf("%s%d ", (solver.conflict[i].sign()) ? "" : "-", solver.conflict[i].var()+1);
      }
      printf("0\n");
    }

The above will print an empty clause if solver.okay() is FALSE.

Now, let's see if the solution is SAT, and if so, print the solution to console, using DIMACS notation:

    if (ret == l_True) {
      printf("We have the solution, it's here: \n");
      for (unsigned var = 0; var != solve.nVars(); var++)
        if (S.model[var] != l_Undef) {
          printf("%s%d ", (solver.model[var] == l_True)? "" : "-", var+1);
          printf("0\n");
        }
    }

If `solver.okay()` is still TRUE (which it must be, if the ret was l_True), we can now add new clauses and new variables without restriction, and solve again (potentially with different assumptions). Note that most of the above applies to MiniSat as well.

When compiling the code, you have to pass the parameters such as:

    $ g++ -fopenmp -lcryptominisat myprogram.cpp -o myprogram

PS: Thanks go to Martin Albrecht for pointing out some ambiguities in my explanation of the library usage, which have now been fixed.