Maximiza la rentabilidad de tu negocio: Cómo optimizar la selección de proveedores de mercancías.

Optimización de Proveedores con Programación Lineal en Python

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! 🚀

Ilustración de la gestión de proveedores en la cadena de suministro

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.
📌 Nota: Este problema es común en industrias como manufactura, retail o logística, donde la selección óptima de proveedores impacta directamente la rentabilidad.

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:

\[ \text{Maximizar} \quad \sum_i (\text{Precio de Venta}_i - \text{Costo}_i) \cdot Y_i \]

Restricciones

  1. Presupuesto: El costo total no debe exceder el presupuesto disponible:
    \[ \sum_i \text{Costo}_i \cdot Y_i \leq \text{Presupuesto Total} \]
  2. Capacidad: La cantidad adquirida de cada proveedor no puede superar su capacidad:
    \[ Y_i \leq \text{Capacidad}_i \cdot X_i, \quad \forall i \]
  3. 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} \]
  4. Demanda: La cantidad total adquirida debe cumplir la demanda mínima:
    \[ \sum_i Y_i \geq \text{Demanda} \]
  5. Restricciones de Dominio:
    \[ X_i \in \{0, 1\}, \quad Y_i \geq 0, \quad \forall i \]
💡 Tip: Las variables binarias \( X_i \) vinculan la selección del proveedor con la cantidad adquirida, asegurando que \( Y_i = 0 \) si el proveedor no es seleccionado.

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}")
      
💡 Tip: Usa 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 100 1000
Proveedor2 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 de optimización de selección de proveedores

Diagrama conceptual de la selección de proveedores con restricciones (Fuente: Propia).

📌 Nota: Proveedor3 no fue seleccionado porque su utilidad por unidad (6) es menor que la de Proveedor1 (10) y Proveedor2 (10), y el límite de 2 proveedores favorece a los más rentables.

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.

Entradas populares de este blog

Cómo Equilibrar Múltiples Productos con Pedidos a la Medida

Descubriendo el Poder de los Modelos de Clasificación en Machine Learning: Predicciones Precisas y Clasificaciones Sorprendentes

Optimización del Inventario Multiproducto en Espacios Reducidos: Una guía para la eficiencia en gestión de stocks

Domina tu Almacén sin arruinarte: El Juego del Modelo de Inventario Múltiproductos con Presupuesto ajustado

¡Plan Desagregado de Producción como un jefe!

El Desafío del Empaque en Contenedores: Optimizando Espacios en contenedores con Ingenio

Análisis ABC en Power BI con DAX: Guía Completa para Profesionales

¡Optimización de Portafolios de Productos: El arte de maximizar el rendimiento!