ConstraintSolver.jl
ConstraintSolver.jl copied to clipboard
Another constraint request: modulo (%)
Would it be possible to add a modulo constraint (as mod(x,y)
or x % y
or x mod y
)?
The mod constraint is quite handy for certain CSP problems. e.g. puzzles and special algorithms.
I'll focus on the element constraints for not but this should be fairly easy to add I think. For now you might want to solve it using the TableConstraint
BTW if you're interested in special constraints please feel free to open a PR yourself if interested. I can guide you through the necessary steps.
I'll focus on the element constraints for not but this should be fairly easy to add I think. For now you might want to solve it using the TableConstraint
Thanks, I'll test implementing modulo with Table constraint. (And I agree that element
is more important than modulo
.)
And thanks for the offer about PR:s regarding constraints. However, I want to implement "all" my models before doing more advanced stuff in Julia.
I guess that you mean "proper" constraints and not just decompositions. I've already write some decompositions that I've needed, e.g. increasing
, decreasing
, scalar_product
, and to_num
(the last converts between an array of digits in some base and a number).
FYI: Here's a simple decomposition using TableConstraint
, but I think the creation of the table can be a little better with some more thoughts. I'll test it with some proper models later on.
#
# modulo(model, x, y, z)
#
# Ensures that x mod y == z
#
function modulo(model, x, y, z)
lbx = round(Int, JuMP.lower_bound(x))
ubx = round(Int, JuMP.upper_bound(x))
lby = round(Int, JuMP.lower_bound(y))
uby = round(Int, JuMP.upper_bound(y))
table = resize_matrix([ [i,j,i % j] for i in lbx:ubx, j in lby:uby if j != 0])
@constraint(model, [x, y, z] in CS.TableSet(table))
end
I first tried to port my ECLiPSe modulo propagator (http://hakank.org/eclipse/modulo_propagator.ecl ) to ConstraintSolver.jl:
function modulo2(model, x, y, z)
@constraint(model, y != 0)
lbx = round(Int, JuMP.lower_bound(x))
ubx = round(Int, JuMP.lower_bound(x))
lbx_neg = -lbx
ubx_neg = -ubx
min_x = min(lbx,ubx_neg)
max_x = max(ubx,lbx_neg)
@variable(model, min_x <= d <= max_x,Int)
@constraint(model, x == y*d + z)
@constraint(model,-abs(Y) <= z ) # should be < but it's not supported
@constraint(model,-abs(Y) != z )
@constraint(model, z <= abs(Y)) # should be < but it's not supported
@constraint(model, z != abs(Y))
@constraint(model, min_x <= d)
@constraint(model, d <= max_x)
end
abs
constraint is not supported (I realized), and is was a very messy error regarding ScalarQuadraticFunction
.