Resolución de problemas de optimización con Docplex en Python

Resolución de problemas de optimización con Docplex en Python

La optimización es un campo de las matemáticas aplicadas que se ocupa de encontrar la mejor solución a un problema dado, sujeto a una serie de restricciones. Los problemas de optimización se encuentran en una amplia gama de aplicaciones, desde la gestión empresarial hasta la ciencia y la ingeniería.

Docplex es una biblioteca de Python para la resolución de problemas de optimización. Es una herramienta poderosa y flexible que puede utilizarse para resolver una amplia gama de problemas, desde problemas lineales simples hasta problemas no lineales complejos.

En este tutorial, aprenderemos a utilizar Docplex para resolver problemas de optimización en Python.

Instalación

La primera etapa es instalar Docplex. Para ello, podemos utilizar el administrador de paquetes de Python:

pip install docplex

Creación de un problema

Para crear un problema de optimización con Docplex, necesitamos definir la función objetivo y las restricciones.

La función objetivo es una expresión matemática que representa el objetivo que queremos optimizar. Las restricciones son desigualdades que limitan los valores que pueden tomar las variables de decisión.

Por ejemplo, supongamos que tenemos un problema de transporte en el que tenemos que transportar una cantidad determinada de bienes de un conjunto de origenes a un conjunto de destinos. La función objetivo podría ser minimizar el costo del transporte. Las restricciones podrían ser que la cantidad total de bienes transportados desde cada origen sea igual a la cantidad total de bienes recibidos en cada destino.

Definición de la función objetivo

La función objetivo se define utilizando la clase Objective(). El constructor de la clase Objective() requiere una expresión matemática que represente la función objetivo.

Por ejemplo, para el problema de transporte anterior, la función objetivo podría definirse de la siguiente manera:

Python
from docplex.mp.model import Model

model = Model("problema_de_transporte")

# Definición de la función objetivo
funcion_objetivo = model.Objective(expr=sum(
    model.x[i, j] * model.c[i, j] for i in model.origenes for j in model.destinos
))

En esta expresión, model.x[i, j] es una variable de decisión que representa la cantidad de bienes que se transportan desde el origen i al destino j. model.c[i, j] es el costo de transportar una unidad de bienes desde el origen i al destino j.

Definición de las restricciones

Las restricciones se definen utilizando la clase Constraint(). El constructor de la clase Constraint() requiere una expresión matemática que represente la restricción.

Por ejemplo, para el problema de transporte anterior, las restricciones podrían definirse de la siguiente manera:

Python
# Definición de las restricciones
for i in model.origenes:
    model.add_constraint(
        expr=sum(model.x[i, j] for j in model.destinos) == model.d[i]
    )

for j in model.destinos:
    model.add_constraint(
        expr=sum(model.x[i, j] for i in model.origenes) == model.s[j]
    )

En estas expresiones, model.d[i] es la demanda en el destino i. model.s[j] es la oferta en el origen j.

Solución del problema

Una vez que hemos definido la función objetivo y las restricciones, podemos resolver el problema utilizando el método solve() del objeto Model().

Python
# Solución del problema
model.solve()

Si el problema tiene una solución factible, el método solve() devolverá un objeto Solution() que contiene la solución.

Obtención de la solución

La solución se puede obtener utilizando los métodos get_objective_value() y get_values() del objeto Solution().

El método get_objective_value() devuelve el valor de la función objetivo.

El método get_values() devuelve un diccionario que mapea cada variable de decisión a su valor.

Por ejemplo, para el problema de transporte anterior, la solución podría obtenerse de la siguiente manera:

Python
# Obtención de la solución
solucion = model.solve()

# Valor de la función objetivo
valor_objetivo = solucion.get_objective_value()

# Valores de las variables de decisión
valores_variables = solucion.get_values()

En este caso, valor_objetivo sería el costo total