Preamble: I'm playing with z3py and trying to implement some decompositions of global constraints, e.g. nvalue(n, x)
which ensures that there are exact n
number of distinct values in the vector/array x
. Constraint programming systems tend to have the possibility to extract lower and upper bounds of a decision variable - and I happen to be very fond of these global constraints.
My question is now if it is possible to get the lower and upper bounds of an variable, defined either as Int
, IntVector
, or Array("x", IntSort(), IntSort())
?
(I've done some decomposition of global constraints already - see http://hakank.org/z3/ - but whenever the decomposition requires upper/lower bounds, I have to add these limits in the method call.)
Here is an example. Note that it use some my convenience methods defined in http://hakank.org/z3/z3_utils_hakank.py which simplifies the port from my constraint programming models; sorry if this is confusing.
The point is that the two values min_value
and max_value
has to be explicit added to the method nvalue
.
from z3_utils_hakank import *
#
# ensure that there are exactly m distinct values in x
#
def nvalue(sol, m, x, min_val,max_val):
n = len(x)
sol.add(m == Sum([ If(Sum([ If(x[j] == i,1,0) for j in range(n)]) > 0,1,0) for i in range(min_val, max_val+1)]))
sol = Solver()
n = 5
min_val = 1 # <--
max_val = n # <--
# variables
m = makeIntVar(sol,"m",0,n) # number of distinct values
x = makeIntVector(sol,"x",n, 1,n)
# constraints
nvalue(sol,m,x,min_val, max_val)
# solutions
num_solutions = 0
while sol.check() == sat:
num_solutions += 1
mod = sol.model()
print "m:", mod.eval(m)
print "x:", [mod.eval(x[i]) for i in range(n)]
print
getDifferentSolution(sol,mod,x)
print "num_solutions:", num_solutions
If would be great it the method definition of nvalue
could be written something like this instead:
def nvalue(sol, m, x):
n = len(x)
min_val = sol.min_val(x)
max_val = sol.max_val(x)
sol.add(m == Sum([ If(Sum([ If(x[j] == i,1,0) for j in range(n)]) > 0,1,0) for i in range(min_val, max_val+1)]))
i.e. using some z3py function such as sol.min_value(x)
and sol.max_val(x)
.