PuLP-MiA: complemento de índices múltiples para PuLP (biblioteca de programación lineal de Python)

¡Hola, Habr! Ahora habrá una mini publicación sin una sola línea de código para aquellos que se ocupan de problemas de LP (programación lineal) de múltiples índices en Python y los resuelven usando la biblioteca de puertos PuLP ... No es por mucho tiempo :-)



Al formalizar problemas de PL, a menudo hay que lidiar con variables de índices múltiples. Cuando se trabaja con problemas de grandes dimensiones, esto es, francamente, algo común.



Las interrelaciones de tales variables de índices múltiples en la función objetivo (la forma lineal es también un criterio de optimización lineal) y las restricciones (en forma de igualdades y desigualdades lineales) deben generarse mediante programación. Cuando se trabaja con PuLP (puerto de biblioteca LP para Python), se utilizan dos enfoques principales para dicha generación:



  1. Generación de la matriz A (matriz de restricciones) utilizando generadores de listas de Python explícitamente. Por ejemplo, así: problema de Sudoku
  2. Generación de variables simbólicas con vinculación a índices a través de diccionarios de forma implícita. Esto se puede hacer manualmente a través de un dictado o usando un complemento PuLP


El problema clásico de LP de casi cualquier dimensión puede formalizarse fácilmente de cualquiera de estas formas, pero cuando se desarrollan nuevas estructuras de restricciones (especialmente cuando la lógica de las interrelaciones de las variables se vuelve más complicada, aparecen nuevas variables de significado, se abandonan algunos índices o se introducen nuevos índices) agregación / descomposición de grupos de variables, etc.) requiere un fácil seguimiento de las variables de múltiples índices en el código Python, que está directamente ausente en los enfoques anteriores.



Para solucionar este problema, se propone utilizar el complemento PuLP-MiA (enlace al repositorio con una breve descripción de la funcionalidad).



El autor está lejos de pensar que esta es una solución a todos los problemas que surgen en la formalización y solución de problemas de PL con una estructura compleja de restricciones, sin embargo, en muchos años de práctica (especialmente cuando la modificación ocurre con intervalos de tiempo largos), el enfoque ha demostrado su eficacia, principalmente debido a las siguientes comodidades:



  • La creación / vinculación a variables existentes ocurre automáticamente
  • Asociación explícita de un nombre de variable y sus índices
  • Nombre de variable: cadena arbitraria
  • Índices: valores numéricos
  • El número de índices es condicionalmente ilimitado (puede que no haya ningún índice)
  • Los resultados de resolver el problema de LP se muestran en forma de diccionario, donde las claves son variables de índices múltiples distintas de cero (el comportamiento se puede cambiar)


Quizás el complemento sea muy útil para alguien en una investigación de operaciones a largo plazo. Licencia MIT. Se instala tradicionalmente a través de pip .



PD Para aquellos que hayan terminado de leer, aún será pequeño



ejemplo de formación de una serie de restricciones))
from itertools import product
from pulp_mia import Task, Constraint

i_set = list(range(5))
j_set = list(range(5))
m_set = list(range(2))
g_set = list(range(4))
s_set = list(range(5))
k_set = list(range(5))

task = Task(debug=True)
for i, m, g, s, k in product(i_set, m_set, g_set, s_set, k_set):
    a_new = Constraint('<=')
    for j in j_set:
        a_new.setCoeff(('x', i, j, m, g, s, k), 1)
    a_new.setBValue(1)
    task.addConstraint(a_new)

print(task)
#TASK info:
#    NAME: test-task
#    SIZE: 5000 x 1000
      
      







(para el resto, vea la breve descripción del complemento )



PPS sí, en algún lugar profundo debajo del capó vive un diccionario común.



All Articles