En este tutorial se utilizará la librería lpSolveAPI de R para resolver programas de optimización lineales, enteros y mixtos. En primer lugar, instalaremos el paquete lpSolveAPI mediante el comando:
library(lpSolveAPI)
En este tutorial vamos a resolver el siguiente modelo de programación lineal:
\[\text{max} \ -2x_{1}+3x_{2}\\ s.a.\\ 1 \leq x_{1}+2x_{2} \leq 3 \\ -3x_{1}+5x_{2} \leq 4\\ x_1, x_2 \geq 0\]
Para resolver un problema de programación lineal primero es necesario construir el modelo. Esto se hace con la función make.lp, esta función recibe como parametro el número de filas (número de restricciones) y el numero de columnas (número de variables). No es necesario especificar el numero de filas en esta parte, se puede dejar en 0, y despues se pueden agregar las restricciones mientras se va compilando el modelo.
model = make.lp(nrow = 0, ncol = 2)
Para especificar la función objetivo, se debe dar como parámetro un arreglo con cada uno de los coeficientes de la función objetivo, de la siguiente forma:
set.objfn(model, c(-2,3))
Para incluir las restricciones, se puede incluir restricción por restricción por medio de la función add.constraint, esta recibe varios parámetros, el primero es el modelo al que se agrega la restricción, el segundo es un arreglo con los coeficientes de cada variable, el tercero es el sentido de la restricción (“<=”, “>=”, “=”), el cuarto es el valor del lado derecho de la restricción (RHS), existe un quinto parámetro opcional para matrices esparsas, y el sexto parametro es opcional y es el valor del lado izquierdo de la restricción (LHS), siguiendo el ejemplo:
add.constraint(model, c(1,2),"<=",3,lhs = 1)
add.constraint(model, c(-1,5),"<=",4)
Debido a que las restricciones se pueden crear con el llamado de una restricción, es posible generar las restricciones mediante un ciclo for, en caso de que estas sean muchas.
En cualquier momento se puede consultar el estado del modelo llamando la variable model la cual contiene una referencia al modelo de optimización:
model
## Model name:
## C1 C2
## Minimize -2 3
## R1 1 <= 1 2 <= 3
## R2 -Inf <= -1 5 <= 4
## Kind Std Std
## Type Real Real
## Upper Inf Inf
## Lower 0 0
Podemos observar que el modelo esta en modo minimizar, para cambiar esta configuración por defecto podemos usar la función lp.control
lp.control(model, sense = "max")
## $anti.degen
## [1] "none"
##
## $basis.crash
## [1] "none"
##
## $bb.depthlimit
## [1] -50
##
## $bb.floorfirst
## [1] "automatic"
##
## $bb.rule
## [1] "pseudononint" "greedy" "dynamic" "rcostfixing"
##
## $break.at.first
## [1] FALSE
##
## $break.at.value
## [1] 1e+30
##
## $epsilon
## epsb epsd epsel epsint epsperturb epspivot
## 1e-10 1e-09 1e-12 1e-07 1e-05 2e-07
##
## $improve
## [1] "dualfeas" "thetagap"
##
## $infinite
## [1] 1e+30
##
## $maxpivot
## [1] 250
##
## $mip.gap
## absolute relative
## 1e-11 1e-11
##
## $negrange
## [1] -1e+06
##
## $obj.in.basis
## [1] TRUE
##
## $pivoting
## [1] "devex" "adaptive"
##
## $presolve
## [1] "none"
##
## $scalelimit
## [1] 5
##
## $scaling
## [1] "geometric" "equilibrate" "integers"
##
## $sense
## [1] "maximize"
##
## $simplextype
## [1] "dual" "primal"
##
## $timeout
## [1] 0
##
## $verbose
## [1] "neutral"
Es posible cambiar el nombre de las filas (restricciones) y columnas (variables) para facilitar la lectura del modelo, de la siguiente forma:
RowNames <- c("Restriccion 1","Restriccion 2")
ColNames <- c("x1","x2")
dimnames(model) <- list(RowNames, ColNames)
model
## Model name:
## x1 x2
## Maximize -2 3
## Restriccion 1 1 <= 1 2 <= 3
## Restriccion 2 -Inf <= -1 5 <= 4
## Kind Std Std
## Type Real Real
## Upper Inf Inf
## Lower 0 0
Para resolver el modelo es necesario llamar a la función solve, esta función retorna un valor entero con el estado de la optimización, de acuerdo con la siguiente tabla
| Estado | Interpretación |
|---|---|
| 0 | Optimal |
| 1 | Sub-optimal |
| 2 | Infeasible |
| 3 | Unbounded |
| 4 | Degenerated |
| 5 | Numeric Failure |
| 6 | Aborted Process |
| 7 | Timeout |
| 9 | Model Solved by pre-solver |
solve(model)
## [1] 0
El resultado obtenido es 0, por lo tanto el modelo se resuelve a optimalidad. Para verificar el valor de la función objetivo, de las variables y de las restricciones se puede realiza de la siguiente manera:
get.objective(model)
## [1] 2.4
get.variables(model)
## [1] 0.0 0.8
get.constraints(model)
## [1] 1.6 4.0
Plantee y resuelva el siguiente problema de programación lineal, puede consultar la guía de la libreria en el siguiente link
Lulo es una empresa que entrega domicilios dentro de diferentes universidades en Colombia. Para realizar sus entregas cuenta con 3 tipos de robots, los cuales tienen una capacidad en número de pedidos y un costo por cada vez que es usado, estos se especifican en la tabla 1. Por cada domicilio que se entregue se obtiene en promedio una ganacia de $500 pesos. El robot WALL-E se puede utilizar máximo 3 veces al día, EVA 2 veces y GO-4 2 veces y máximo se puede enviar 6 veces al día en total a los robots. Suponga que con una probabilidad de 0.5 el robot se envía completamente lleno, de lo contrario se envía con la mitad de su capacidad. Si Lulo quiere maximizar sus ganacias diarias, ¿cuántas veces debe enviar cada robot?
| Nombre robot | Capacidad (unidades) | Costo por uso (pesos) |
|---|---|---|
| WALL-E | 6 | $2000 |
| EVA | 4 | $1500 |
| GO-4 | 2 | $1000 |