You are on page 1of 10

Tutorial Implementación Computacional de Modelos Matemáticos

Descargar Julia:
https://julialang.org/ (https://julialang.org/)

Descargar Code Interpreter:

Atom: https://atom.io/ (https://atom.io/)

Visual Studio Code: https://visualstudio.microsoft.com/es/ (https://visualstudio.microsoft.com/es/)

Jupyter: https://jupyter.org/ (https://jupyter.org/)

Descargar Solver:

Gurobi: https://www.gurobi.com/ (https://www.gurobi.com/)

Descargar lenguaje de modelado específico de dominio para la optimización matemática integrado en Julia:
Julia JuMP: https://jump.dev/JuMP.jl/stable/ (https://jump.dev/JuMP.jl/stable/)

Introducción a la Programación en Julia

https://introajulia.org/ (https://introajulia.org/)
In [2]: # Matriz
A = [[3 2 1];[0 1 0];[1 1 1]]

Out[2]: 3×3 Array{Int64,2}:


3 2 1
0 1 0
1 1 1

In [3]: # Vector
V = [ 1 2 3 4 5 6 7 ]

Out[3]: 1×7 Array{Int64,2}:


1 2 3 4 5 6 7

Modelo Optimización

Modelo simple

𝑚𝑖𝑛 20𝑥1 + 10𝑥2 + 15𝑥3


𝑠.𝑡. 𝑥1 ≥ 40
𝑥2 ≤ 100
3
∑ 𝑥𝑖 = 450
𝑖=1
          𝑥𝑖 ≥ 0    ∀ 𝑖 = 1,2,3
In [1]: using JuMP # Llamamos a entorno JuMP
using Gurobi # Llamamos a Solver
using XLSX # Llamamos a .Xlsx
using DataFrames # LLamamos a Dataframe

In [7]: # Definir un modelo


model = Model(Gurobi.Optimizer);

Academic license - for non-commercial use only - expires 2021-05-28

In [8]: # Variables
@variable(model, x[1:3] >= 0);

In [9]: # Objetivo
@objective(model, Min, 20*x[1] + 10*x[2] + 15*x[3])

Out[9]: 20𝑥1 + 10𝑥2 + 15𝑥3


In [10]: # Restricciones
@constraint(model, x[1] >= 40)
@constraint(model, x[2] <= 100)
@constraint(model, sum( x[i] for i in 1:3) == 450);
In [11]: # Resolver
JuMP.optimize!(model)

Gurobi Optimizer version 9.1.1 build v9.1.1rc0 (win64)


Thread count: 4 physical cores, 8 logical processors, using up to 8 threads
Optimize a model with 3 rows, 3 columns and 5 nonzeros
Model fingerprint: 0xe378979b
Coefficient statistics:
Matrix range [1e+00, 1e+00]
Objective range [1e+01, 2e+01]
Bounds range [0e+00, 0e+00]
RHS range [4e+01, 5e+02]
Presolve removed 3 rows and 3 columns
Presolve time: 0.00s
Presolve: All rows and columns removed
Iteration Objective Primal Inf. Dual Inf. Time
0 6.4500000e+03 0.000000e+00 0.000000e+00 0s

Solved in 0 iterations and 0.00 seconds


Optimal objective 6.450000000e+03

User-callback calls 29, time in user-callback 0.01 sec

In [12]: # Obtener resultados


println("x: ", JuMP.value.(x))
println("Objetivo: ", objective_value(model))

x: [40.0, 100.0, 310.0]


Objetivo: 6450.0

Modelo Intermedio

Ud. Está a cargo de la producción y venta en Chile de una nueva bebida energética a base de berries llamada "Big Energy". Dispone de un único tamaño de venta de 2.5 lts a un
precio de 5.000 pesos. Dispone de 8 ciudades posibles para instalar centros productivos en donde se estima que la demanda será de un 20% de la población de esta. Puede distribuir
los productos entre las ciudades mediante camiones de carga. El costo de arriendo de cada centro productivo es de 50 millones de pesos al año y el costo variable por producto es
600 pesos/unidad para las primeras 80.000 unidades y 200 pesos/unidad para las siguientes. Cada centro productivo puede producir máximo 300.000 unidades al año. Para
transportar el producto entre ciudades, existe un costo fijo de 50.000 pesos y variable de 1 pesos por km recorrido. El transporte de una ciudad a otra es directo (no puede pasar antes
por otras ciudades). Determine qué centros productivos abrirá, la cantidad a producir por cada uno, las cantidades transportadas de una ciudad a otra y el beneficio neto anual.

Parámetros
𝑁: Número de ciudades (𝑁 = 8)
𝑐𝑖 : ciudad i
𝑝𝑖 : poblacion ciudad i
𝑑𝑖 : demanda ciudad i
𝑟𝑖,𝑗 : distancia ciudad i a ciudad j
𝐶𝑎𝑟𝑟𝑖𝑒𝑛𝑑𝑜 : Costo arriendo centro productivo (𝐶𝑎𝑟𝑟𝑖𝑒𝑛𝑑𝑜 = 50.000.000 [pesos/año] )
𝑃 : Precio de Venta (𝑃 : 5.000 [pesos/unidad])
𝐶𝑉𝑎𝑝 : Costo Variable intervalo alta producción ( 𝐶 𝑉𝑎 𝑝 = 200 [pesos/unidad] )
𝐶𝑉𝑏𝑝 : Costo Variable intervalo baja producción ( 𝐶 𝑉𝑏 𝑝 = 600 [pesos/unidad] )
𝐶𝑇𝑣 : Costo de transporte variable ( 𝐶𝑇𝑣 = 1[pesos/(km)])
𝐶𝑇𝑓 : Costo de transporte fijo ( 𝐶𝑇𝑓 = 50.000 [pesos])
𝑃𝑟𝑜𝑑𝑚𝑎𝑥 : Producción máxima de cada centro productivo ( 𝑃𝑟𝑜𝑑𝑚𝑎𝑥 = 300.000 [unidades])
𝐼𝑝 : Límite intervalo producción baja - alta ( 𝐶𝑇𝑓 = 80.000 [unidades])
Variables
𝑥𝑖 : Cantidad bebidas producidos en la ciudad i
𝐴𝑖 : Decisión de arrendar centro en la ciudad i
𝑇𝑖,𝑗 : Decisión de transportar desde ciudad i a ciudad j
𝑦𝑖,𝑗 : Cantidad de productos transportada desde la ciudad i hasta la ciudad j
𝑤𝑖 : Representa el producto entre las variables x y z
𝑤𝑖 = 𝑥𝑖 · 𝑧𝑖
𝑍𝑖 : Nivel de producción en la ciudad i (alto o bajo])
𝑍𝑖 = 1 si ∑𝑖∈𝑁 > 𝐼𝑝
𝑍𝑖 = 0 si ∑𝑖∈𝑁 <= 𝐼𝑝
Función Objetivo
𝐼𝑛𝑔𝑟𝑒𝑠𝑜 = ∑ 𝑥𝑖 ⋅ 𝑃
𝑖∈𝑁
𝐶𝑜𝑠𝑡𝑜𝑉𝑎𝑟𝑖𝑎𝑏𝑙𝑒 = ∑ (𝑥𝑖 ⋅ 𝐶 𝑉𝑎𝑝 ) − (𝐶 𝑉𝑎𝑝 − 𝐶 𝑉𝑏𝑝) ⋅ (𝑤𝑖 − 𝐼𝑝 ∗ 𝑍𝑖 )
𝑖∈𝑁
𝐶𝑜𝑠𝑡𝑜𝐴𝑟𝑟𝑖𝑒𝑛𝑑𝑜 = ∑ 𝐴𝑖 ⋅ 𝐶𝑎𝑟𝑟𝑖𝑒𝑛𝑑𝑜
𝑖∈𝑁
𝐶𝑜𝑠𝑡𝑜𝑉𝑎𝑟𝑖𝑎𝑏𝑙𝑒𝑇𝑟𝑎𝑛𝑠𝑝𝑜𝑟𝑡𝑒 = ∑ ∑ 𝑟𝑖,𝑗 ⋅ 𝐶 𝑇𝑣 ⋅ 𝑦𝑖,𝑗
𝑖∈𝑁 𝑗∈𝐽
𝐶𝑜𝑠𝑡𝑜𝐹𝑖𝑗𝑜𝑇𝑟𝑎𝑛𝑠𝑝𝑜𝑟𝑡𝑒 = ∑ ∑ 𝐶 𝑇𝑓 ⋅ 𝑇𝑖,𝑗
𝑖∈𝑁 𝑗∈𝐽
𝐶𝑜𝑠𝑡𝑜𝑠 = 𝐶𝑜𝑠𝑡𝑜𝑉𝑎𝑟𝑖𝑎𝑏𝑙𝑒 + 𝐶𝑜𝑠𝑡𝑜𝐴𝑟𝑟𝑖𝑒𝑛𝑑𝑜 + 𝐶𝑜𝑠𝑡𝑜𝑉𝑎𝑟𝑖𝑎𝑏𝑙𝑒𝑇𝑟𝑎𝑛𝑠𝑝𝑜𝑟𝑡𝑒 + 𝐶𝑜𝑠𝑡𝑜𝐹𝑖𝑗𝑜𝑇𝑟𝑎𝑛𝑠𝑝𝑜𝑟𝑡𝑒
𝐵𝑒𝑛𝑒𝑓𝑖𝑐𝑖𝑜 = 𝐼𝑛𝑔𝑟𝑒𝑠𝑜 − 𝐶𝑜𝑠𝑡𝑜𝑠
Modelo
𝑚𝑎𝑥  𝐵𝑒𝑛𝑒𝑓𝑖𝑐𝑖𝑜
𝑠.𝑡 ∑ 𝑦𝑖𝑗 + 𝑥𝑖 − ∑ 𝑦𝑖𝑗 ≤ 𝑑𝑖     ∀𝑖
𝑗∈𝐽 𝑗∈𝐽
∑ 𝑦𝑖𝑗 ≤ 𝑥𝑖   ∀𝑖
𝑗∈𝐽
𝑦𝑖𝑗 ≤ 𝑀 ⋅ 𝑇𝑖𝑗     ∀𝑖,𝑗
𝑥𝑖 ≤ 𝑀 ⋅ 𝐴𝑖     ∀𝑖
𝑥𝑖 ≤ 𝑃𝑟𝑜𝑑𝑚𝑎𝑥     ∀𝑖
𝑍𝑖 ⋅ 𝐼𝑝 ≤ 𝑥𝑖     ∀𝑖
𝑤𝑖 ≤ 𝑥𝑖     ∀𝑖
𝑤𝑖 ≤ 𝑀 ⋅ 𝑧𝑖     ∀𝑖
𝑥,𝑦 𝐸𝑛𝑡𝑒𝑟𝑎𝑠
𝐴𝑖 , 𝑇𝑖𝑗 , 𝑍𝑖 ∈ [0,1]    ∀𝑖,𝑗
In [13]: function modelo()

#Parámetros
path = "data.xlsx"
r = XLSX.readdata(path, "distancia_ciudades!B2:I9")
poblacion = XLSX.readdata(path, "demanda!B2:B9")
d = XLSX.readdata(path, "demanda!C2:C9")
ciudades = XLSX.readdata(path, "distancia_ciudades!A2:A9");
N = length(ciudades)
P = 5000 #Precio venta por producto

#Costos Variables de producir un producto


CV_ap = 200
CV_bp = 600
CT_v = 1
CT_f = 50000
C_arriendo = 50000000 #Costo Arriendo Fijo
M = 250000 #Big M
Prod_max = 200000
I_p = 80000 # Limite producción baja . Alta
#--------------------------------------------------------------
m = Model(with_optimizer(Gurobi.Optimizer, MIPGap = 0.001))
set_silent(m)
#definir variables
@variable(m, x[1:N], Int, lower_bound = 0, base_name = "produccion_i")
@variable(m, A[1:N], Bin, base_name = "Decision_Arrendar")
@variable(m, T[1:N, 1:N], Bin, base_name = "Decision_Transporte")
@variable(m, y[1:N, 1:N], Int, lower_bound = 0, base_name = "productos_entre_ciudades")
@variable(m, z[1:N], Bin, base_name = "nivel_productivo")
@variable(m, w[1:N], Int, lower_bound = 0, base_name = "x*z")

#----------------------------------------------------

#Función Objetivo
Ganancia = sum(x[i] * P for i in 1:N)
Costos_Variables = sum(x[i] * CV_ap - (CV_ap - CV_bp)*(w[i] - I_p*z[i]) for i in 1:N)
Costos_Arriendo = sum(A[i] * C_arriendo for i in 1:N)
Costo_Transporte_var = sum(r[i,j]* CT_v * y[i,j] for i in 1:N for j in 1:N)
Costo_Transporte_fijo = sum(T[i,j] * CT_f for i in 1:N for j in 1:N)
f = Ganancia - (Costos_Variables + Costos_Arriendo + Costo_Transporte_var + Costo_Transporte_fijo)
@objective(m, Max, f)
#----------------------------------------------------------
#Restricciones del Problema

# Lo recibido - lo enviado <= Demanda


@constraint(m, dda[i = 1:N], sum(y[j,i] for j in 1:N) + x[i] - sum(y[i,j] for j in 1:N) <= d[i])

# No se puede enviar más de lo producido


@constraint(m, envio_produccion[i = 1:N], sum(y[i,j] for j in 1:N) <= x[i])

# Se produce sólo si se arrienda


@constraint(m, arriendo_produccion[i = 1:N], x[i] <= M * A[i])

# Se transporta sólo si se decide transportar


@constraint(m, transporte[i = 1:N, j = 1:N], y[i, j] <= T[i,j] * M)

# Límite producción
@constraint(m, max_produccion[i = 1:N], x[i] <= Prod_max)

# Producción alta - baja (estado)


@constraint(m, estado_productivo[i = 1:N], z[i] * I_p <= x[i])

# Definición de w_1
@constraint(m, def_w1[i = 1:N], w[i] <= x[i])

# Defición de w_2
@constraint(m, def_w2[i = 1:N], w[i] <= z[i] * M)

optimize!(m)
value_opt = objective_value(m)
produccion = JuMP.value.(x)
transporte_entre_cuidades =JuMP.value.(y)

return produccion, transporte_entre_cuidades, value_opt

end

Out[13]: modelo (generic function with 1 method)


In [14]: produccion, transporte_entre_cuidades, value_opt = modelo();

Academic license - for non-commercial use only - expires 2021-05-28

In [15]: # Unidades Transportadas entre ciudades (fila => columna)

path = "data.xlsx"
ciudades = XLSX.readdata(path, "distancia_ciudades!A2:A9");

DataFrames.rename!(convert(DataFrame, transporte_entre_cuidades), [Symbol(ciudades[i]) for i in 1:8])

Out[15]: 8 rows × 8 columns

valparaiso concepcion serena antofagasta talca arica calama valdivia

Float64 Float64 Float64 Float64 Float64 Float64 Float64 Float64

1 -0.0 -0.0 44210.0 -0.0 -0.0 -0.0 -0.0 -0.0

2 -0.0 -0.0 -0.0 -0.0 41213.0 -0.0 -0.0 30009.0

3 0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0

4 -0.0 -0.0 -0.0 -0.0 -0.0 40426.0 31515.0 -0.0

5 -0.0 0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0

6 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0

7 -0.0 -0.0 -0.0 -0.0 -0.0 0.0 -0.0 -0.0

8 -0.0 0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0


In [16]: # Producción por ciudad

produccion
DataFrames.rename!(convert(DataFrame, produccion'), [Symbol(ciudades[i]) for i in 1:8])

Out[16]: 1 rows × 8 columns

valparaiso concepcion serena antofagasta talca arica calama valdivia

Float64 Float64 Float64 Float64 Float64 Float64 Float64 Float64

1 103445.0 114729.0 0.0 141644.0 0.0 0.0 0.0 0.0

In [17]: # Beneficio Neto ($)


value_opt

Out[17]: 1.59440667027e9

You might also like