I have a formula in a .dimacs/.cnf file as in the following:
p cnf 6 9
1 0
-2 1 0
-1 2 0
-5 1 0
-6 1 0
-3 2 0
-4 2 0
-3 -4 0
3 4 -2 0
Is it possible to extract only those clauses that contain e.g., the variables 2, 3, and 4, in SAT4j ? Then, I need to check the consistency only for this new set of clauses, i.e., for:
p cnf 4 6
-2 1 0
-1 2 0
-3 2 0
-4 2 0
-3 -4 0
3 4 -2 0
I tried to use Assumptions, I tried to use Constraints, but I still cannot find a way to do this.
Thank you for any suggestion.
Edit
I thought that there is a method like solver.addClause(clause), but in reverse solver.getClause(clause)...Although, I am feeding the solver with clauses from a .cnf file.
Edit 2
First, assumptions have the same syntax with a clause,
val assumption: IVecInt = new VecInt(Array(1, 2))
val clause: IVecInt = new VecInt(Array(1, 2))
but the variables are conjunctions in assumptions and disjunctions in a clause. This is a difference. Right? My test examples are saying so. (I just needed to get an extra approval on this).
Second, my issue with using the selector variables is this one:
A simple formula a V b has three models:
(a, b),
(a, -b),
(-a, b)
When I add a selector variable, e.g., s, and its assumption is -s, then I have the same number of models, i.e., 3 models:
(a, b, -s),
(a, -b, -s),
(-a, b, -s)
When the assumption is true, i.e., s, then I have 4 models instead of 0 that I want:
(a, b, s),
(a, -b, s),
(-a, b, s),
(-a, -b, s)
Of course when s = T, then (s V a V b) = (T V a V b) = T, but is this a deletion way for the clause (a V b)? What I need are the number of models, real models! Is there a way to find the exact models while 'removing' somehow these variables (i.e., a and b) that we want to exclude by an assumption?
For this case, this is my current code in Scala:
object Example_01 {
val solver: ISolver = new ModelIterator(SolverFactory.newDefault())
val reader: DimacsReader = new DimacsReader(solver)
val problem: IProblem = reader.parseInstance("example_01.cnf")
def main(args: Array[String]): Unit = {
var nrModels: Int = 0
val assumptions: IVecInt = new VecInt(Array(10))
try {
while(solver.isSatisfiable(assumptions)) {
println(reader.decode(problem.model()))
nrModels += 1
}
} catch {
case e: ContradictionException => println("UnSAT: ", e)
}
println("The number of models is: " + nrModels)
}
Thank you, for any help.
The way to proceed is to prefix each clause with a new selector variable
And then you just need to assign the extra variable to true to discard a clause and to false to enable it, as assumptions. In your case, the assumption would be 7,-8,-9,10,11,-12,-13,14,-15.
This is not specific to Sat4j, it is a way to proceed proposed originally by minisat, and that most SAT solver provide.
edit 2:
Here is the way to use assumptions and model counting