Maximiza la rentabilidad de tu negocio: Cómo optimizar la selección de proveedores de mercancías.
La programación lineal es una herramienta poderosa para optimizar decisiones en la gestión de la cadena de suministro. En este artículo, exploramos cómo seleccionar proveedores para maximizar la utilidad total, respetando restricciones como presupuesto, capacidad y demanda. Usaremos la biblioteca PuLP en Python para modelar y resolver este problema. ¡Acompáñanos en este recorrido técnico! 🚀
Gestión de proveedores para optimizar la cadena de suministro (Fuente: CEUPE).
El Problema de Selección de Proveedores
Imagina una empresa que necesita adquirir productos de varios proveedores para satisfacer una demanda específica. Cada proveedor ofrece productos a un costo y precio de venta distintos, con una capacidad máxima de suministro. El objetivo es maximizar la utilidad total (diferencia entre precio de venta y costo) mientras se respetan:
- Un presupuesto limitado para las compras.
- La capacidad máxima de cada proveedor.
- Un límite en el número de proveedores seleccionados.
- Una demanda mínima a cumplir.
Modelo Matemático
Formulamos el problema como un modelo de programación lineal con variables de decisión, una función objetivo y restricciones.
Variables de Decisión
- \( X_i \): Variable binaria que indica si el proveedor \( i \) es seleccionado (\( X_i = 1 \)) o no (\( X_i = 0 \)).
- \( Y_i \): Variable entera que representa la cantidad de productos adquiridos del proveedor \( i \).
Función Objetivo
Maximizar la utilidad total:
Restricciones
- Presupuesto: El costo total no debe exceder el presupuesto disponible:
\[ \sum_i \text{Costo}_i \cdot Y_i \leq \text{Presupuesto Total} \]
- Capacidad: La cantidad adquirida de cada proveedor no puede superar su capacidad:
\[ Y_i \leq \text{Capacidad}_i \cdot X_i, \quad \forall i \]
- Número de Proveedores: No se puede seleccionar más proveedores que el límite permitido:
\[ \sum_i X_i \leq \text{Número Máximo de Proveedores} \]
- Demanda: La cantidad total adquirida debe cumplir la demanda mínima:
\[ \sum_i Y_i \geq \text{Demanda} \]
- Restricciones de Dominio:
\[ X_i \in \{0, 1\}, \quad Y_i \geq 0, \quad \forall i \]
Implementación en Python con PuLP
Usamos la biblioteca PuLP para modelar y resolver el problema. A continuación, desglosamos el código paso a paso.
Configuración Inicial
Importamos PuLP y definimos el problema como uno de maximización:
from pulp import *
# Crear el problema de maximización
prob = LpProblem("Seleccion_Proveedores", LpMaximize)
Definición de Variables
Definimos los proveedores y las variables de decisión \( X_i \) (binarias) y \( Y_i \) (enteras):
# Lista de proveedores
proveedores = ["Proveedor1", "Proveedor2", "Proveedor3"]
# Variables binarias (selección de proveedores)
Xi = LpVariable.dicts("X", proveedores, 0, 1, LpBinary)
# Variables enteras (cantidad adquirida)
Yi = LpVariable.dicts("Y", proveedores, lowBound=0, cat="Integer")
Parámetros del Problema
Especificamos los costos, precios de venta, capacidades, demanda, presupuesto y número máximo de proveedores:
# Parámetros de los proveedores
parametros = {
"Proveedor1": {"costo": 10, "precio_venta": 20, "capacidad": 100},
"Proveedor2": {"costo": 15, "precio_venta": 25, "capacidad": 150},
"Proveedor3": {"costo": 12, "precio_venta": 18, "capacidad": 120}
}
# Restricciones globales
demanda = 150
presupuesto_total = 2000
num_max_proveedores = 2
Resumimos los parámetros en una tabla para mayor claridad:
| Proveedor | Costo ($/unidad) | Precio de Venta ($/unidad) | Capacidad (unidades) |
|---|---|---|---|
| Proveedor1 | 10 | 20 | 100 |
| Proveedor2 | 15 | 25 | 150 |
| Proveedor3 | 12 | 18 | 120 |
Tabla 1: Parámetros de los proveedores.
Función Objetivo
Maximizamos la utilidad total (precio de venta menos costo por unidad):
# Función objetivo: Maximizar utilidad
prob += lpSum([(parametros[i]["precio_venta"] - parametros[i]["costo"]) * Yi[i] for i in proveedores]), "Utilidad_Total"
Restricciones
Agregamos las restricciones del modelo:
# Restricción de presupuesto
prob += lpSum([parametros[i]["costo"] * Yi[i] for i in proveedores]) <= presupuesto_total, "Restriccion_Presupuesto"
# Restricciones de capacidad
for i in proveedores:
prob += Yi[i] <= parametros[i]["capacidad"] * Xi[i], f"Restriccion_Capacidad_{i}"
# Restricción de número máximo de proveedores
prob += lpSum([Xi[i] for i in proveedores]) <= num_max_proveedores, "Restriccion_Seleccion_Proveedores"
# Restricción de demanda
prob += lpSum([Yi[i] for i in proveedores]) >= demanda, "Restriccion_Demanda"
# Restricciones de no negatividad
for i in proveedores:
prob += Yi[i] >= 0, f"Restriccion_No_Negatividad_{i}"
Resolución y Resultados
Resolvemos el problema y mostramos los resultados:
# Resolver el problema
prob.solve()
# Mostrar el estado de la solución
print("Estado de la solución:", LpStatus[prob.status])
# Mostrar valores de las variables
for v in prob.variables():
print(f"{v.name} = {v.varValue}")
# Calcular y mostrar la utilidad total
utilidad_total = sum([(parametros[i]["precio_venta"] - parametros[i]["costo"]) * value(Yi[i]) for i in proveedores])
print(f"Utilidad Total = {utilidad_total}")
LpStatus[prob.status] para verificar si la solución es óptima, factible o no resoluble.
Resultados y Análisis
La solución óptima obtenida es:
- X_Proveedor1 = 1.0 (seleccionado)
- X_Proveedor2 = 1.0 (seleccionado)
- X_Proveedor3 = 0.0 (no seleccionado)
- Y_Proveedor1 = 100.0 unidades
- Y_Proveedor2 = 66.0 unidades
- Y_Proveedor3 = 0.0 unidades
- Utilidad Total = 1660.0 unidades monetarias
Resumimos los resultados en una tabla:
| Proveedor | Seleccionado | Cantidad (unidades) | Utilidad ($) |
|---|---|---|---|
| Proveedor1 | Sí | 100 | 1000 |
| Proveedor2 | Sí | 66 | 660 |
| Proveedor3 | No | 0 | 0 |
Tabla 2: Resultados óptimos de la selección de proveedores.
La solución selecciona a Proveedor1 y Proveedor2, adquiriendo 100 y 66 unidades respectivamente, para cumplir la demanda de 150 unidades dentro del presupuesto de 2000 y el límite de 2 proveedores. La utilidad total es 1660.
Diagrama conceptual de la selección de proveedores con restricciones (Fuente: Propia).
Conclusión
La programación lineal con PuLP permite optimizar la selección de proveedores de manera eficiente, maximizando la utilidad mientras se respetan restricciones prácticas. Este enfoque es ideal para problemas de la cadena de suministro en industrias reales. ¡Prueba el código completo en el Gist de GitHub y adapta los parámetros a tu caso! 🔍
¿Tienes un problema de optimización en tu negocio? ¡Comparte tu experiencia en los comentarios o en LinkedIn! 👇
Para profundizar, consulta libros sobre programación lineal en Amazon.
¡Únete a la Comunidad!
🔔 Suscríbete para más contenido sobre optimización y Python.
📢 Comparte este artículo en LinkedIn.