MultiObjectiveAlgorithms.jl (Error Message)

Hi everyone, I’ve modeled a simple model to assign instruments to procedures. I’ve implemented the model in JuMP using the solver Gurobi and package MOA.jl.

When I tried to solve the model, the message below appear to me:

Gurobi Optimizer version 10.0.0 build v10.0.0rc2 (win64)

CPU model: Intel(R) Core(TM) i5-8265U CPU @ 1.60GHz, instruction set [SSE2|AVX|AVX2]
Thread count: 4 physical cores, 8 logical processors, using up to 8 threads

Optimize a model with 94 rows, 128 columns and 678 nonzeros
Model fingerprint: 0x2ada338b
Variable types: 10 continuous, 118 integer (6 binary)
Coefficient statistics:
  Matrix range     [5e-02, 9e+01]
  Objective range  [1e-01, 5e-01]
  Bounds range     [0e+00, 0e+00]
  RHS range        [1e+00, 6e+00]
Found heuristic solution: objective 8.7745536
Presolve removed 34 rows and 34 columns
Presolve time: 0.00s
Presolved: 60 rows, 94 columns, 430 nonzeros
Variable types: 0 continuous, 94 integer (9 binary)
Found heuristic solution: objective 8.2703373

Root relaxation: objective 7.760417e+00, 47 iterations, 0.00 seconds (0.00 work units)

    Nodes    |    Current Node    |     Objective Bounds      |     Work
 Expl Unexpl |  Obj  Depth IntInf | Incumbent    BestBd   Gap | It/Node Time

*    0     0               0       7.7604167    7.76042  0.00%     -    0s

Explored 1 nodes (47 simplex iterations) in 0.01 seconds (0.00 work units)
Thread count was 8 (of 8 available processors)

Solution count 3: 7.76042 8.27034 8.77455

Optimal solution found (tolerance 1.00e-04)
Best objective 7.760416666667e+00, best bound 7.760416666667e+00, gap 0.0000%

User-callback calls 367, time in user-callback 0.00 sec
ERROR: In `MathOptInterface.ScalarAffineFunction{Float64}`-in-`MathOptInterface.LessThan{Float64}` constraint: Constant -1.25 of the function is not zero. The function constant should be moved to the set. You can use `MOI.Utilities.normalize_and_add_constraint` which does this automatically.

I need help to fix this error and solve my problem.
The model was defined as follows:

    using JuMP, Gurobi
    import DelimitedFiles
    import MultiObjectiveAlgorithms as MOA

    #Data reading
    data = DelimitedFiles.readdlm(filename.txt)
    instruments = data[1,1]
    trays = 6
    surgeries = data[1,3]
    capacity = 89 #data[1,5]
    freq = zeros(Float64, surgeries)
    for i = 1:surgeries
       freq[i] = data[2,i+1]
    end
    demand_max = zeros(Int, instruments)
    for i = 1:instruments
       demand_max[i] = data[3,i+1]
    end
    demand = zeros(Int, instruments, surgeries)
    for i = 1:instruments
       for j = 1:surgeries
         demand[i,j] = data[i+3,j]	
       end
    end

    #Normalizing the frequency
    max_freq = 0
    min_freq = 9999999
    for i = 1:surgeries
       if(freq[i] > max_freq)
          max_freq = freq[i]
       end
       if(freq[i] < min_freq)
          min_freq = freq[i]
       end
    end
    for i = 1:surgeries
       freq[i] = (freq[i] - min_freq)/(max_freq - min_freq)
    end

    #Creating the model and declaring variables
    #model = Model()
    #model = Model(Gurobi.Optimizer)
    model = Model(() -> MOA.Optimizer(Gurobi.Optimizer))
    set_attribute(model, MOA.Algorithm(), MOA.EpsilonConstraint())
    #set_optimizer_attribute(model, "TimeLimit", 600)
    #set_optimizer_attribute(model, "Presolve", 0)
    @variable(model, y[k = 1:trays], Bin)				#(Equação 9)
    @variable(model, x[i = 1:instruments, k = 1:trays] >= 0, Int)	#(Equação 10)
    @variable(model, e[i = 1:instruments, j = 1:surgeries] >= 0, Int)	#(Equação 11.1)
    @variable(model, n[i = 1:instruments, j = 1:surgeries] >= 0, Int)	#(Equação 11.2)
    @variable(model, a[j = 1:surgeries] >= 0)				#(Equação 12.1)
    @variable(model, b[j = 1:surgeries] >= 0)				#(Equação 12.2)

    #Defining the constraints
    for i = 1:instruments, j = 1:surgeries
       @constraint(model, e[i,j] >= demand[i,j] - sum(x[i,k] for k = 1:trays))	#(Equação 3)
       @constraint(model, n[i,j] >= sum(x[i,k] for k = 1:trays) - demand[i,j])	#(Equação 4)
    end
    for j = 1:surgeries
       #(Equação 5)
       @constraint(model, a[j] == sum((demand[i,j] - e[i,j]) for i = 1:instruments)/sum(demand[i,j] for i = 1:instruments))
       #(Equação 6)
       @constraint(model, b[j] == sum(n[i,j] for i = 1:instruments)/sum((demand_max[i] - demand[i,j]) for i = 1:instruments))
    end
    for k = 1:trays 
       @constraint(model, sum(x[i,k] for i = 1:instruments) <= capacity*y[k])	    #(Equação 7.1)
       @constraint(model, sum(x[i,k] for i = 1:instruments) >= 0.5*capacity*y[k])   #(Equação 7.2)
    end
    @constraint(model, sum(y[k] for k = 1:trays) <= 6) #(Equação 8.1)
    @constraint(model, sum(y[k] for k = 1:trays) >= 3) #(Equação 8.2)

    #Objective Functions
    @expression(model, instruments_expr, sum(x[i,k] for i = 1:instruments, k = 1:trays))
    @expression(model, eff_expr, sum((freq[j]*((1 - b[j] + a[j])/2)) for j = 1:surgeries))
    @expression(model, a_mean_expr, sum(a[j] for j=1:surgeries)/surgeries)
    @expression(model, b_mean_expr, sum(b[j] for j=1:surgeries)/surgeries)
    @expression(model, nb_trays_expr, sum(y[k] for k=1:trays))
    @objective(model, Min, [-eff_expr, instruments_expr])

    #Running the solver
    optimize!(model)
    status = termination_status(model)
    println("STATUS: ", status, " ---------------------------")
    print(solution_summary(model))

A simple instance of the problem is defined as follows:

7 Instruments, 5 Procedures, 15 Capacity
Procedures_Freq 10 11 12 13 14
Instruments_DemMax 4 4 4 5 4 5 4  

2 4 3 1 1
4 2 3 0 2
3 4 0 5 2
1 2 5 3 4
4 1 3 4 1
5 3 0 1 2
0 2 4 2 0
1 Like

Hi @IgorESMelo, welcome to the forum :smile:

I’ve already fixed this (Fix and add tests for constant offset in objective function by odow · Pull Request #76 · jump-dev/MultiObjectiveAlgorithms.jl · GitHub), so if you update your packages and restart Julia it should work.

import Pkg
Pkg.update()

You need MOA v1.3.1.

(The issue was the constant offset in the objective function :grimacing:. I should have caught this earlier, sorry for that.)

x-ref: optimization - MultiObjective problems using gurobi solver - which method is used? - Stack Overflow

1 Like

Hi again Oscar, thank you very much for your support and the time spent on my issue.

1 Like

No problem

1 Like

Oscar, could you take off a last doubt?
In this same example, I’m trying to get the value of the x[i,k] variables.
So, I coded something like

instr_chosen = [(i, k) for k in 1:trays, i in 1:instruments if value(x[i, k]; result = 1) > 0.9]

So, I received the follow error message:
ERROR: MethodError: no method matching value(::Float64; result::Int64)

I need to pass de x[i,k] as a float variable or like this?

And if I need to get the x[i,k] complete value, I’ve tried something like
instr_chosen = [(i, k, value.(x[i,k])) for k in 1:trays, i in 1:instruments if value(x[i, k]; result = 1) > 0.9], but didn’t work too.

Thank you very much.

This is saying that the first argument to value is a Float64. That probably means at some point in your code you have replaced the x decision variables with something else.

Do you have a line like x = value.(x)?

1 Like

It’s true. I redefined the variable name in someplace after the model definition, so the function value.() hadn’t been working how I imagined.

Sorry, my bad.
Thank you again for your help!!

1 Like

No worries. Feel free to ask any other questions.

1 Like