Question about the syntax of the @constraint command

Hey guys!
I’ve just started programming in julia and I want to implement two constraints for my code using the JuMP library.
The constraints are:
for i in 1:N
for j in 1:N
If sum of Xji == 0 then sum of Xij >=2
If sum of Xji >= 1 then sum of Xij ==1

How to do this using the @constraint command?

Welcome in the Julia community! :grinning:

If you post code it is easier to read if you enclose it in triple backticks, like ```

Can you post a little bit more code? How is X defined?

1 Like

Simple example for using the sum of a vector as constraint:

using JuMP
using HiGHS

model = Model(HiGHS.Optimizer)

@variable(model, x[1:2])

@objective(model, Min, 12x[1] + 20x[2])

@constraint(model, c1, 6x[1] + 8x[2] >= 100)
@constraint(model, c2, 7x[1] + 12x[2] >= 120)

@constraint(model, c3, sum(x) <= 16)

optimize!(model)

objective_value(model)

println()
println("x[1]: ", value(x[1]))
println("x[2]: ", value(x[2]))
1 Like

This is not Julia code. I do not really understand what you want to achieve here. Could you re-write this
in a clearer form, e.g. Julia (or Matlab or Python) or a clearer mathematical notation?

If you have a mathematical notation in LaTeX you can also post it here (enclosed in $ signs), e.g.:

X_{i, j}

More about constraints in the documentation: Constraints · JuMP

1 Like

The current code is:

# c: Matrix with the associated cost of going from node i to node j.
# l: Matrix that identifies whether the connection from node i to node j exists.
# d: Vector with destination nodes.

using CPLEX, JuMP
function MILP(c, l, ps, d, time_limit)
    N = size(c,1) 

    model = Model(optimizer_with_attributes(CPLEX.Optimizer,
    "CPX_PARAM_TILIM" => time_limit,
    "CPX_PARAM_THREADS" => 1))

    @variable(model, X[i in 1:N, j in 1:N], Bin) 
    
    @objective(model, Min, sum(c[i,j]*X[i,j] for i in 1:N, j in 1:N))

    for i in 1:N
        for j in 1:N            
            if l[i, j] == 0
                @constraint(model, X[i, j] == 0)
            end
        end
    end  

    for i in 1:N
        if (i in ps)
            for j in 1:N
                if l[i,j] == 1
                    @constraint(model, (X[j,i])==0) 
                    @constraint(model, (X[i,j])==1) 
                end
            end
        end
        if !(i in ps) && !(i in d)
                @constraint(model,[j in 1:N; sum(X[j, i]) == 0], sum(X[i, j]) >= 2)
                @constraint(model,[j in 1:N; sum(X[j, i]) != 0], sum(X[i, j]) == 1)           
        end
        if (i in d)
            @constraint(model, sum(X[j,i] for j in 1:N)>=1) 
            @constraint(model, sum(X[i,j] for j in 1:N)==0) 
        end
    end

    status = optimize!(model)

    zIP = objective_value(model)
    tzIP = MOI.get(model, MOI.SolveTimeSec())
    X_values = value.(X)

    return zIP, tzIP, X_values 
end

The following error is occurring:

ERROR: Result index of attribute MathOptInterface.ObjectiveValue(1) out of bounds. There are currently 0 solution(s) in the 
model.

I tried to download CPLEX, but have not been successful yet. (The requested resource is not available. Try again later.)

So I cannot reproduce your problem yet.

Do you get the same error if you use an open source solver?

UPDATE:
I managed to download and install CPLEX. :slight_smile:

1 Like

OK, I can run your code:

julia> include("opt.jl")
MILP (generic function with 1 method)

Can you also share the code you use to call the function MILP(), which means example values for c, l, ps, d, time_limit ?

See: Please read: make it easier to help you point 4.

2 Likes

Hi @Artemisa_Fontinele, welcome to the forum.

You can achieve this using indicator constraints: Constraints · JuMP. The tricky part is that you need to introduce a binary variable with is 0 or 1 at the correct time.

Here’s how I would write your code. I haven’t tested it because I don’t know the values for c, l, etc, so let me know if there are any issues.

using CPLEX, JuMP
function MILP(c, l, ps, d, time_limit)
    N = size(c,1) 
    model = Model(
        optimizer_with_attributes(
            CPLEX.Optimizer,
            "CPX_PARAM_TILIM" => time_limit,
            "CPX_PARAM_THREADS" => 1,
        ),
    )
    @variable(model, X[1:N, 1:N], Bin) 
    @objective(model, Min, sum(c .* X))
    for i in 1:N, j in 1:N            
        if l[i, j] == 0
            fix(X[i, j], 0)
        end
    end  
    for i in 1:N
        if i in ps
            for j in 1:N
                if l[i, j] == 1
                    fix(X[j, i], 0)
                    fix(X[i, j], 1)
                end
            end
        end
        if !(i in ps) && !(i in d)
            # if sum(X[:, i]) == 0 => sum(X[i, :]) >= 2
            # if sum(X[:, i]) >= 1 => sum(X[i, :]) == 1
            # Define zi ∈ {0, 1}, which is 0 if sum(X[:, i]) == 0 and 1 otherwise
            zi = @variable(model, binary = true)
            @constraints(model, begin
                sum(X[:, i]) <= N * zi
                sum(X[:, i]) >= zi
                !zi --> {sum(X[i, :]) >= 2}
                zi --> {sum(X[i, :]) == 1}
            end)
        end
        if (i in d)
            @constraint(model, sum(X[:, i]) >= 1) 
            @constraint(model, sum(X[i, :]) == 0) 
        end
    end
    optimize!(model)
    zIP = objective_value(model)
    tzIP = solve_time_sec(model)
    X_values = value.(X)
    return zIP, tzIP, X_values 
end
2 Likes