Question: Is it possible to control some sort of preference for model return values in z3?
Example: Given the following propositional logic formula, there are 2 possible models.
- a: True, b: True, c: False(preferred)
- a: True, b: False, c: True(still valid, just "second choice")
I would like to control, via the boolean formula/assertions itself, that the model where a and b are True should have preference over the model where a and c are True. But given the case that b could not be True because additional constraints are added, the model with a and c being True should be returned.
SMT2 Formula: Here is the SMT2 example formula, which can be tested via rise4fun.
(declare-const a Bool)
(declare-const b Bool)
(declare-const c Bool)
(assert (= a true))
(assert (or
    (and (= b true) (not (= c true)))
    (and (= c true) (not (= b true)))
))
(check-sat)
(get-model)
Observation: I noticed that it seems actually possible to control wether or not b or c are True in the returned model, by actually switching the order of the and clauses in the or clause. Is this in some way reliable or just happening by chance for this trivial example?
 
                        
This is an alternative answer, which uses the
assert-softcommand.Alternative Encoding #1
I provide an encoding for OptiMathSAT first, and then explain how to modify these formulas to achieve the same result in z3. Compared with the other approach, this encoding is more suitable when there are many Boolean variables which share the same priority level, as it allows the OMT solver to use either a dedicated MaxSAT engine for each step of the lexicographic search or Cardinality Networks to enhance the standard OMT-based search.
I conflated the two toy-examples I have shown in the other answer in one incremental formula as follows:
This is the output:
To use this encoding with z3, it is sufficient to comment out the following three lines:
The reason for this is that z3 implicitly defines the objective of an
assert-softcommand and implicitly minimizes it. Its output is:Please note that, since z3 implicitly declares the minimization objectives for you, the
assert-softcommands should appear in the same order of priority that you would like to assign to their associated objective function.As I mentioned in the incipit, this encoding is much better than the one in the other answer in the case in which some variables share the same level of priority. To place two variables
a1anda2at the same level of priority, you can use the sameidfor theirassert-softcommand.For example:
with the output
Alternative Encoding #2
The interesting fact about
assert-softis that it can be used to solve lexicographic-optimization problems without any Lexicograpic-optimization engine: it is sufficient to play a bit with the weights to achieve the same result. This is what it is traditionally done in the case of SAT/MaxSAT solving. The only caveat is that one needs to place the weights carefully. Other than that, this approach might be even more efficient than the above encoding, because the entire optimization problem is solved with a single-call to the internal single-objective engine.This is the output:
I mentioned this in a comment to the other answer, but another potentially interesting solution could be to try a Bit-Vector encoding of the formula and then use the OBVBS (see "Bit-Vector Optimization" by Nadel et al.) engine for BV-optimization over a vector in which the Most Significant Bit represents the highest-priority variable and the Least Significant Bit represents the lowest-priority variable.
In case you want to give it a try, some time ago we introduced in OptiMathSAT a re-implementation of the OBVBS engine described in the paper. Z3 supports Bit-Vector optimization too.