Un problema de programación lineal (PPL) es una situación compleja en la que el responsable debe tomar decisiones del tipo:
de modo que se cumpla con ciertas limitaciones, como:
y de manera que, tanto la función objetivo (a maximizar o minimizar), como las limitaciones se pueden escribir como ecuaciones lineales en las variables de decisión.
Una forma estándar en la que todo PPL puede escribirse es:
\[ \begin{array}{rrrrrrrrc} \text{max } z(\vec{x}) = &c_1 x_1 & + & c_2 x_2 & + & \cdots & + & c_n x_n & &\\ \text{s.a} & & & & & & & & & \\ &a_{11} x_1 & + &a_{12} x_2 & + &\cdots & + &a_{1n} x_n & = &b_1 \\ &a_{21} x_1 & + & a_{22} x_2 & + & \cdots & + & a_{2n} x_n & = & b_2 \\ & \vdots & \vdots &\vdots & \vdots &\ddots & \vdots &\vdots & \vdots &\vdots \\ &a_{m1} x_1 & +& a_{m2} x_2 & + &\cdots & +& a_{mn} x_n & =& b_m \\ & x_1, & & x_2, & & \ldots, & & x_n & \geq & 0 \end{array} \]
donde todas las restricciones quedan como ecuaciones lineales.
El conjunto de valores que cumplen las restricciones se llama región factible y se denota por \(F\).
La resolución “manual” de un PPL pasa por:
Algunos detalles de la región factible \(F\) son:
El algoritmo Simplex (George B. Dantzig, 1947) se basa en esto último. Mediante sencillas operaciones:
Existen muchos programas para la aplicación del algoritmo simplex, y algunos permiten tratar el PPL sin estar en forma estándar, lo cual quita trabajo al usuario.
Este algoritmo no está exento de inestabilidad numérica, ya que en la actualización de la tabla simplex, al saltar de un extremo a otro, se calculan divisiones con un elemento pivote como denominador. Si se trata de un valor cercano a 0 la exactitud del algoritmo peligra.
simplex()
del package boot
Sirve para problemas de tamaño no muy grande (leer Nota en la ayuda help(simplex)
). Instalar y cargar package previamente.
simplex(a, A1, b1, A2, b2, A3, b3, maxi, n.iter, eps)
a
: coeficientes de la función objetivoA1
: matriz de restricciones de tipo \(\leq\) (sólo la parte de coeficientes)b1
: vector de términos independientes de las restricciones de tipo \(\leq\) (correspondientes a la matriz A1
)A2
: idem con restricciones de tipo \(\geq\)b2
: idem correspondientes a la matriz A2
A3
: idem con restricciones de tipo \(=\)b3
: idem correspondientes a la matriz A3
maxi
: Poner a TRUE
si se desea maximizar la función objetivon.iter
: número máximo de iteraciones en cada fase (usa método de dos fases)eps
: tolerancia de coma flotantesimplex
, que es una lista con componentes (entre otras):
$soln
: solución óptima, si se alcanza$solved
: código de terminación:
1
indica solución óptima encontrada0
indica que se ha alcanzado el número máximo de iteraciones sin acabar-1
indica que no existe solución factible$value
: valor de la función objetivo en la solución $soln
$val.aux
: valor de las variables artificiales en el óptimoEjemplo 1: Resuelve el PPL expresado como: \[ \begin{array}{rl} \text{max} &x_1 + 5x_2 - x_3 \\ \text{s.a} & \\ & x_1 + x_2 + x_3 \geq 100 \\ & 5x_1 - x_2 + 8x_3 \leq 500 \\ & - x_1 + x_2 + 2x_3 = 0 \\ & 2x_1 + x_2 + 12x_3 \leq 800 \\ & x_1, x_2, x_3 \geq 0 \end{array} \]
Ejemplo 2: Resuelve el PPL expresado como: \[ \begin{array}{rl} \text{max} &15 x_1 + 10x_2\\ \text{s.a} & \\ & x_2 \leq 50 \\ & 1.5 x_1 - x_2 \geq 20 \\ & x_1, x_2 \geq 0 \end{array} \]
Ejemplo 3: Resuelve el PPL expresado como: \[ \begin{array}{rl} \text{min} &50 x_1 -20 x_2\\ \text{s.a} &\\ & - 1.5 x_2 \leq 15 \\ & x_1 + x_2 \geq 10 \\ & x_1, x_2 \geq 0 \end{array} \]
lp()
del package lpSolve
Se trara de otra función para resolver PPLs, pero más completa pues admite variables enteras (programación entera) y variables binarias (programación 0-1). Para usarla hay que instalar y cargar el package previamente.
lp (direction, objective.in, const.mat, const.dir, const.rhs, int.vec, binary.vec)
direction
: por defecto vale 'min'
. Cambiar a 'max'
si se quiere maximizar la función objetivoobjective.in
: vector con coeficientes de la función objetivoconst.mat
: matriz de coeficientes de las restriccionesconst.dir
: vector de cadenas de texto indicando la dirección de cada restricción ("<="
, "=,"
o ">="
)const.rhs
: vector de términos independientes de las restriccionesint.vec
: Vector indicando qué variables son enterasbinary.vec
: Vector indicando qué variables son 0-1lp
, que es una lista con componentes (entre otras):
$objval
: valor de la función objetivo en el óptimo$solution
: solución óptima$status
: indicador numérico:
0
: éxito2
: no hay solución factibleEjemplo 4: Resuelve los ejemplos 1, 2 y 3 por medio de la función lp
.
set.seed(20200507) # PON TU FECHA DE NACIMIENTO AÑOMESDIA
misproblemas = sort(sample(x=1:6, size=2))
LISTA DE PROBLEMAS (hacer sólo los 2 indicados en el enunciado):
# AQUÍ EL CÓDIGO
Y AQUÍ LOS COMENTARIOS SOBRE LA SOLUCIÓN QUE TE HA DADO, O NO PUNTUARÁ
# AQUÍ EL CÓDIGO
Y AQUÍ LOS COMENTARIOS SOBRE LA SOLUCIÓN QUE TE HA DADO, O NO PUNTUARÁ
# AQUÍ EL CÓDIGO
Y AQUÍ LOS COMENTARIOS SOBRE LA SOLUCIÓN QUE TE HA DADO, O NO PUNTUARÁ
# AQUÍ EL CÓDIGO
Y AQUÍ LOS COMENTARIOS SOBRE LA SOLUCIÓN QUE TE HA DADO, O NO PUNTUARÁ
# AQUÍ EL CÓDIGO
Y AQUÍ LOS COMENTARIOS SOBRE LA SOLUCIÓN QUE TE HA DADO, O NO PUNTUARÁ
# AQUÍ EL CÓDIGO
Y AQUÍ LOS COMENTARIOS SOBRE LA SOLUCIÓN QUE TE HA DADO, O NO PUNTUARÁ
Ejercicio 2: Inicia la programación del algoritmo simplex en lenguaje R, en una versión lo más simplificada posible. Instrucciones:
simplex0 = function(c, A, b) {
# comprobaciones necesarias
stopifnot( is.numeric(c), is.numeric(b), is.matrix(A))
n = length(c); m = length(b)
stopifnot(b>=0, n>=m, dim(A)[1]==m, dim(A)[2]==n)
ident = diag(x=m)
stopifnot( identical(A[,(m+1):n], ident) )
base = (m+1):n # columnas base inicial
x.base = b # primera sol básica
c.base = c[base] # coeficientes de las var. básicas
Y = A # la matriz de coeficientes y_kj
zj.minus.cj = apply(X=c.base * Y, MARGIN=2, FUN='sum') - c # los zj menos cj
z.base = sum(c.base*x.base)
# a partir de aquí te toca a ti, suerte
}
Comprueba con un ejemplo completo de clase.