Wikunia / ConstraintSolver.jl

ConstraintSolver in Julia: Blog posts ->
https://opensourc.es/blog/constraint-solver-1
MIT License
136 stars 13 forks source link

Sum of constraints: e.g. @constraint(model, sum([x[i,k] == 1 && x[j,k] == 1 for k in 1:n] <= 1) #254

Open hakank opened 3 years ago

hakank commented 3 years ago

In certain models, e.g. Steiner problem ( http://hakank.org/julia/constraints/steiner.jl ) there would be a great modelling benefit if one can sum over a list of constraints/conditions.

Example (from the Steiner model). Instead of the following, using booleans to first count the number of common elements and then constrain the sum to be atmost 1 (using the upcoming feature of && in reification which is a great feature in itself)

    # ...
    # atmost 1 element in common
    for i in 1:nb
        @constraint(model,sum(x[i,:]) == 3)
        for j in i+1:nb
            b = @variable(model, [1:n], Bin)
            for k in 1:n 
                @constraint(model, b[k] := { x[i,k] == 1 && x[j,k] == 1 })
            end
            @constraint(model, sum(b) <= 1)
        end
    end 
    # ...

the following formulation would be much simpler to state:

    # ...
    # atmost 1 element in common
    for i in 1:nb
        @constraint(model,sum(x[i,:]) == 3)
        for j in i+1:nb
            @constraint(model, sum([x[i,k] == 1 && x[j,k] == 1 for k in 1:n] <= 1)
        end
    end 
    # ...
Wikunia commented 3 years ago

Thanks for opening the issue. It seems like you forgot a bracket in the sum constraint but I'm quite surprised that this doesn't throw an error for me. Will open an issue at JuMP about this.

Wikunia commented 2 years ago

The user would need to write something like:

@constraint(
    model, 
    BooleanConstraint(sum(x == i && x == i for i = 1:2) <= 1),
)

which isn't implemented yet though but the suggested syntax here doesn't work due to how JuMP works internally.