Help modeling a problem in Julia using JuMP (stock problem)


#1

Hello everyone,

I’m new to Julia, and I´m helping my wife with her Master degree. Unfortunately, we both lack a solid mathematical foundation, and that´s really making things more difficult for me.

I have started with the “Julia Programming for Operations Research - A Primer on Computing” book, from Changhyun Kwon (http://juliabook.chkwon.net/), and I am also trying to model some known problems to get a deeper understanding of the language.

I´ve been trying to model the problem below without success. Could you please give me a clue on that?

Thanks in advance!!

Best Regards,
GB

The stock problem

Month | 1 | 2 | 3 | 4 | 5 | 6 |
±----±----±----±----±----±----+
Demand | 50 | 100 | 30 | 80 | 110 | 60 |
P.Cost | 200 | 220 | 250 | 250 | 240 | 255 |

Maximum production per month: 70
Production w/ extra hour: +70 (+15% cost)
Monthly stock cost: 10,00 (per item)

x[n] = items produced using standard work hours
y[n] = items prodeced using extra hours
e[n] = items in stock (e[1] = 0)

Objective function:

Z min = (200 * x1) + (1.15 * 200 * y1) + (10 * e1)
(220 * x2) + (1.15 * 220 * y2) + (10 * e2)
(250 * x3) + (1.15 * 250 * y3) + (10 * e3)
(250 * x4) + (1.15 * 250 * y4) + (10 * e4)
(240 * x5) + (1.15 * 240 * y5) + (10 * e5)
(255 * x6) + (1.15 * 255 * y6) + (10 * e6)

Constraints:

x[n], y[n] >= 0, Int
e[n] >= 0, Int

x[n], y[n] <= 70

x[1] + y[1] + e[1] >= 50
x[2] + y[2] + e[2] >= 100
x[3] + y[3] + e[3] >= 30
x[4] + y[4] + e[4] >= 80
x[5] + y[5] + e[5] >= 110
x[6] + y[6] + e[6] = 60

e[n] + x[n] + y[n] - demand[n] = e[n+1]

What I´ve been trying…

using JuMP, Cbc

# Prepare the optimization model
m = Model(solver=CbcSolver())

# Problem data
demand = [50; 100; 30; 80; 110; 60]
cost = [200; 220; 250; 250; 240; 255]

# Variables
@variable(m, x[1:6] >=0, Int)
@variable(m, y[1:6] >=0, Int)
@variable(m, stock[1:6] >=0, Int)

# Objective function
@objective(m, Min, (x[n]*cost[n]) + (y[n]*cost[n]*1.15) + (stock[n]*10) = demand[n] for n = 1:6)

The result
syntax: "*(x[n],cost[n])" is not a valid function argument name


#2

Have you read the documentation? Especially the Quick Start Guide? It seems that you are having problems with the usage (syntax) of the specific package, not the modeling of the optimization problem itself.


#3

Everything looks good up to the objective function (though obviously you haven’t added your constraints yet). As written, your objective has a few issues:

  • There is an = assignment in your objective. It needs to be just the expression to be minimized (i.e. the total cost).
  • This is a generator expression, and is essentially returning an array with 6 entries. You probably want to wrap it in sum to get your total cost.
  • You’re using both indexes i and n. I believe this is the root of the error you get here.
  • It will be more clear if your multiplications use the * operator. I also think that numeric values have to come first for “adjacent” multiplication.

Hope this helps.


#4

Based on what @jkbest2 suggested:

@objective(m, Min, sum( (x[n] * cost[n]) + (y[n] * cost[n] *1.15) + (stock[n] * 10) for n = 1:6))


#5

Thanks for all the answers!

Arda,
Yes, I have read the quick start guide and some parts of the documentation, as well as Chang’s book. I came from IT, and I have some programming background. As I told you guys, my problem is the lack of math foundation.

John,

  • Sorry for the use of both “i” and “n” as indexes. I made a lot of tests before, and it was just a mistake when I copied that to a TXT at some point. It´s definitely not the root of the error.
  • Reflecting on your statement about the objective clarified things for me. Yes, all I want is just minimize the cost, so, the expression should reflect the cost only, all the rest should be contraints, right?
  • I am using the * operator. As it was my first message in the forum, it seems like it was edited by the moderator, or automatically formated in some way, and the operator is gone. The position of the numerical operator does not seem to affect the syntax.

Chang,
That did the job! :slight_smile:

I´ll try to finish the problem and let you know the results. Things looks a lot more clear for me in this specific problem now.


#6

No problem, the formatting still trips me up occaisionally as well. I bet that’s why it was bolded for me when I read it the first time. Numerical operator position only matters when you’re doing numeric literal multiplication. So in Julia 3x == 3 * x, but x3 != x * 3, because x3 is parsed as a variable.

Yes, this is correct.


#7

Here is the complete working solution. Thank you, guys!!! :sunglasses:

using JuMP, Cbc

# Prepara um modelo de otimização
m = Model(solver=CbcSolver())

# Dados do problema
demand = [50; 100; 30; 80; 110; 60]
cost = [200; 220; 250; 250; 240; 255]

# Declara variáveis
@variable(m, 0 <= x[1:6] <= 70, Int)
@variable(m, 0 <= y[1:6] <= 70, Int)
@variable(m, e[1:6] >=0, Int)

# Define a função objetivo
@objective(m, Min, sum( (cost[n] * x[n]) + (1.15 * cost[n] * y[n]) + (10 * e[n]) for n = 1:6))
            
# Define as restrições
@constraint(m, r1, x[1] + y[1] + e[1] >= demand[1])
@constraint(m, r2, x[2] + y[2] + e[2] >= demand[2])
@constraint(m, r3, x[3] + y[3] + e[3] >= demand[3])
@constraint(m, r4, x[4] + y[4] + e[4] >= demand[4])
@constraint(m, r5, x[5] + y[5] + e[5] >= demand[5])
@constraint(m, r6, x[6] + y[6] + e[6] >= demand[6])

@constraint(m, r7, x[1] + y[1] - demand[1] == e[2])
@constraint(m, r8, x[2] + y[2] + e[2] - demand[2] == e[3])
@constraint(m, r9, x[3] + y[3] + e[3] - demand[3] == e[4])
@constraint(m, r10, x[4] + y[4] + e[4] - demand[4] == e[5])
@constraint(m, r11, x[5] + y[5] + e[5] - demand[5] == e[6])
@constraint(m, r12, x[6] + y[6] + e[6] - demand[6] == 0)
@constraint(m, r13, e[1] == 0)
            
# Imprime o modelo
println("Modelo:")
print(m)

# Resolve o problema
solve(m)

# Imprime as soluções ótimas
println("\nSoluções ótimas:")
println("x = ", getvalue(x))
println("y = ", getvalue(y))
println("e = ", getvalue(e))

Returns

Modelo:
Min 200 x[1] + 229.99999999999997 y[1] + 10 e[1] + 220 x[2] + 252.99999999999997 y[2] + 10 e[2] + 250 x[3] + 287.5 y[3] + 10 e[3] + 250 x[4] + 287.5 y[4] + 10 e[4] + 240 x[5] + 276 y[5] + 10 e[5] + 255 x[6] + 293.25 y[6] + 10 e[6]
Subject to
 x[1] + y[1] + e[1] ≥ 50
 x[2] + y[2] + e[2] ≥ 100
 x[3] + y[3] + e[3] ≥ 30
 x[4] + y[4] + e[4] ≥ 80
 x[5] + y[5] + e[5] ≥ 110
 x[6] + y[6] + e[6] ≥ 60
 x[1] + y[1] - e[2] = 50
 x[2] + y[2] + e[2] - e[3] = 100
 x[3] + y[3] + e[3] - e[4] = 30
 x[4] + y[4] + e[4] - e[5] = 80
 x[5] + y[5] + e[5] - e[6] = 110
 x[6] + y[6] + e[6] = 60
 e[1] = 0
 0 ≤ x[i] ≤ 70, integer, ∀ i ∈ {1,2,…,5,6}
 0 ≤ y[i] ≤ 70, integer, ∀ i ∈ {1,2,…,5,6}
 e[i] ≥ 0, integer, ∀ i ∈ {1,2,…,5,6}

Soluções ótimas:
x (std hrs)   = [70.0,70.0,70.0,70.0,70.0,60.0]
y (extra hrs) = [20.0,0.0,0.0,0.0,0.0,0.0]
e (stock)     = [0.0,40.0,10.0,50.0,40.0,0.0]