The answer provided by Levent Erkok is valid in general and, in most practical cases, it is the only one which is worth being considered.
However, technically speaking, this is not a problem that is completely beyond the reach of OMT solvers, at least when the domain of values being considered is finite and, possibly, small. In this case, it is possible to simply enumerate all possible values in the formulation of the problem. Naturally, this approach should not be expected to scale very well.
Example.
The goal of this model is to find the largest interval delta
, contained in [low, upp]
, such that for all the values inside the interval a certain Boolean property Prop
holds.
File: test.smt2
(set-option :produce-models true)
(declare-fun low () (_ BitVec 4))
(declare-fun upp () (_ BitVec 4))
(declare-fun delta () (_ BitVec 4))
(declare-fun Prop () Bool)
(assert (bvule low upp))
(assert (= delta (bvadd upp (bvneg low) (_ bv1 4))))
; Put in relation a domain value with the desired Property
(assert (=> (and (bvule low (_ bv0 4)) (bvule (_ bv0 4) upp)) Prop))
(assert (=> (and (bvule low (_ bv1 4)) (bvule (_ bv1 4) upp)) Prop))
(assert (=> (and (bvule low (_ bv2 4)) (bvule (_ bv2 4) upp)) Prop))
(assert (=> (and (bvule low (_ bv3 4)) (bvule (_ bv3 4) upp)) Prop))
(assert (=> (and (bvule low (_ bv4 4)) (bvule (_ bv4 4) upp)) Prop))
(assert (=> (and (bvule low (_ bv5 4)) (bvule (_ bv5 4) upp)) Prop))
(assert (=> (and (bvule low (_ bv6 4)) (bvule (_ bv6 4) upp)) Prop))
(assert (=> (and (bvule low (_ bv7 4)) (bvule (_ bv7 4) upp)) Prop))
(assert (=> (and (bvule low (_ bv8 4)) (bvule (_ bv8 4) upp)) Prop))
(assert (=> (and (bvule low (_ bv9 4)) (bvule (_ bv9 4) upp)) Prop))
(assert (=> (and (bvule low (_ bv10 4)) (bvule (_ bv10 4) upp)) Prop))
(assert (=> (and (bvule low (_ bv11 4)) (bvule (_ bv11 4) upp)) Prop))
(assert (=> (and (bvule low (_ bv12 4)) (bvule (_ bv12 4) upp)) Prop))
(assert (=> (and (bvule low (_ bv13 4)) (bvule (_ bv13 4) upp)) Prop))
(assert (=> (and (bvule low (_ bv14 4)) (bvule (_ bv14 4) upp)) Prop))
(assert (=> (and (bvule low (_ bv15 4)) (bvule (_ bv15 4) upp)) Prop))
; These are just to make the solution "interesting"
; Your problem should already entail some values bvX for
; which Prop is false
(assert (=> (and (bvule low (_ bv5 4)) (bvule (_ bv5 4) upp)) (not Prop)))
(assert (=> (and (bvule low (_ bv6 4)) (bvule (_ bv6 4) upp)) (not Prop)))
(assert (=> (and (bvule low (_ bv13 4)) (bvule (_ bv13 4) upp)) (not Prop)))
(maximize delta)
(check-sat)
(get-objectives)
(get-model)
A short explanation. The goal of the objective function is to maximize the size of the interval [low, upp]
, which is measured by delta
. The largest value of delta
is 2^N
, which corresponds to the interval [0, 2^N - 1]
.
The constraint:
(assert (=> (and (bvule low (_ bv0 4)) (bvule (_ bv0 4) upp)) Prop))
says that, if the value bv0
is contained in the current interval [low, upp]
, then the property Prop
must hold.
The constraint:
(assert (=> (and (bvule low (_ bv5 4)) (bvule (_ bv5 4) upp)) (not Prop)))
says that, for the value bv5
, the property Prop
does not hold. Same for bv6
and bv13
. These constraints are just to make the solution interesting. Your problem should already contain some values bvX
for which property Prop
cannot be true.
The optimal solution matches the desired value:
~$ time ./optimathsat test.smt2
sat
(objectives
(delta (_ bv6 4))
)
( (low (_ bv7 4))
(upp (_ bv12 4))
(delta (_ bv6 4))
(Prop true) )
real 0m0,042s
user 0m0,029s
sys 0m0,013s
Naturally, the same formula can also be solved with z3
.