En lugar de unirse
Cuando los procesos de recolección y procesamiento de desechos se ajustan completamente en Rusia, no es fácil decirlo, pero no quiero participar en la reposición de los vertederos ahora. Por lo tanto, en muchas ciudades grandes, de una forma u otra, hay movimientos de voluntarios que participan en una recolección particular por separado.
En Novosibirsk, dicha actividad se forma alrededor de la campaña Ardilla verde, en la que una vez al mes, la gente del medio ambiente lleva los desechos domésticos reciclables acumulados a lugares predeterminados en un momento determinado. Al mismo tiempo, llega un camión alquilado, que lleva los materiales reciclables recogidos y ordenados al sitio, desde donde se redistribuye entre varias empresas de procesamiento. La acción ha existido desde 2014, y desde entonces el número de puntos de recolección de materiales reciclables, así como sus volúmenes, ha aumentado significativamente. Para el enrutamiento de camiones, solo una mirada no fue suficiente, y comenzamos a desarrollar modelos de optimización para minimizar los costos de transporte. El primero de estos modelos es el tema de este artículo.
En la sección 1, describiré en detalle y con ilustraciones el esquema para organizar la acción. Además, en la sección 2, la tarea de minimizar los costos de transporte se formalizará como la tarea de enrutar el problema de enrutamiento de vehículos de flota de vehículos heterogéneos con ventanas de tiempo. La Sección 3 está dedicada a resolver este problema usando un paquete distribuido libremente para resolver problemas de programación matemática lineal mixta entera GLPK.
1. La acción "Ardilla verde"
Desde 2014, el grupo de iniciativa
Living Earth ha estado realizando una campaña mensual para separar la colección de
Ardilla Verde reciclada en Novosibirsk. Al momento de escribir este artículo, se acepta el reciclaje con varias reservas de desechos plásticos etiquetados como PET, PE, PP, PS, vidrio, aluminio, hierro, electrodomésticos, papel de desecho y más. Más de 50 voluntarios participan en la preparación y realización de la acción. La acción no es comercial, su participación es gratuita y no implica una recompensa monetaria.
PuntosLa acción se lleva a cabo en 17 puntos de la ciudad, ubicados entre sí a distancias cubiertas por el automóvil en un período de 15 a 90 minutos. Uno de estos puntos en la foto: bolsas a la izquierda a lo largo de la pared para recoger varias fracciones de plástico, a la derecha, un camión, en el que todo está cargado en el futuro, y en el centro, un voluntario con orejas.

Toda la actividad en este punto está organizada por curadores que tienen restricciones en el momento en que están listos para cumplir con sus deberes. Al planificar una acción, los curadores informan el intervalo de tiempo dentro del cual la acción debe pasar en su punto.
También hay datos sobre los volúmenes promedio de reciclables recolectados en cada punto.
RutasLos puntos se organizan en rutas que son conducidas sucesivamente por un camión. Los movimientos de los camiones son monitoreados por supervisores de ruta que monitorean el entorno operativo y toman decisiones sobre el manejo de eventos especiales.
CamionesSe alquilan de forma común en el marco de propuestas de alquiler por hora de vehículos de carga. No es posible compactar el plástico en su lugar, por lo tanto, el parámetro principal que caracteriza al camión es el volumen de la carrocería. La capacidad de carga en nuestro caso no es un factor limitante.
Los principales gastos de la acción están relacionados con el pago del alquiler de camiones, por lo tanto, su reducción es crítica para la existencia y el desarrollo de nuestra participación, que adquiere importancia institucional en el sentido de formar ideas sobre el consumo responsable. A continuación, se describirá un enfoque para resolver este problema, basado en la aplicación de métodos de optimización discretos, a saber, la programación matemática.
2. Formalización
Al construir el modelo matemático, nos mantendremos dentro del marco de los programas lineales de enteros mixtos, para los cuales es suficiente el conocimiento del álgebra de clase 7.
La única dificultad puede estar asociada con el uso de notación abstracta y signos de suma en las fórmulas. Espero que esto no asuste a los lectores que tienen encuentros poco frecuentes con textos matemáticos.
En el modelo de optimización, se pueden distinguir cuatro componentes:
- la formación de grupos de puntos que forman una ruta separada;
- definición de un esquema de desvío para cada uno de los grupos;
- cumplir con los requisitos para la hora de llegada del camión en cada punto;
- determinación del tipo de camión necesario para dar servicio a cada una de las rutas.
Consideramos cada una de las partes, introduciendo la notación necesaria según sea necesario.
Agrupación de puntosDejar
V = \ {1, \ puntos, n \}V = \ {1, \ puntos, n \} hay muchos índices de puntos de recolección de materiales reciclables, y el sitio donde se transportan los reciclables recolectados, lo llamaremos
depósito , tiene un índice de 0. Poner
\ bar {V} = V \ cup \ {0 \}\ bar {V} = V \ cup \ {0 \}Cada grupo de puntos forma una ruta separada. A través de
R denotar el conjunto de números de ruta.
Deja la cantidad
zir,i enI,r enR es igual a uno si el punto
i incluido en la ruta con el número
r , y cero en caso contrario. Entonces el requisito de que el punto
i enV debe ingresar una de las rutas puede escribirse como
sumr inRzir=zi1+zi2+ dots+zin=1.
Depot debe ingresar todas las rutas:
z0r=1,r enRSutilezasDesafortunadamente, tal registro crea problemas computacionales asociados con la simetría de la región admisible. Se puede eliminar agregando una serie de restricciones que garantizan la elección de una descomposición lexicográfica mínima. Puedes leer más sobre esto en ruso, por ejemplo,
aquí .
1−zir leq sumi−1j=1 left(1− sumr−1k=1zjk right)+ sumr−1k=1zik, quadi inI,r inR,r leqi.
Definición de desvíoLas rutas son una secuencia alterna de puntos y cruces entre ellas. Formalmente, todos comienzan en uno de los puntos del set
V y terminar en el depósito, sin embargo, será más fácil suponer que todas las rutas son cíclicas. Esta suposición no cambia la esencia, pero hace que todos los vértices sean iguales: en este caso no hay vértices finales, todos son tránsito.
Por puntos
i,j in barV y ruta
r enR configurar una variable
xijr igual a uno si en la ruta con número
r camión moviéndose desde el punto
i hasta el punto
j , y cero en caso contrario.
Luego requerimos, en primer lugar, que el camión se mueva a lo largo de la ruta
r enR visitó el punto
i enV si ella, después de dividirse en grupos, cayó en el grupo con el número
r :
sumj in barVxjir=zir, quadi in barV,r inR.
En segundo lugar, el camión después de llegar al punto.
i in barV debe dejarla.
sumj in barVxjir= sumj in barVxijr, quadi in barV,r inR.
Puede notar que estas restricciones permiten las cantidades
xijr Definir rutas que son un conjunto de bucles disjuntos. Rutas de este tipo, por supuesto, no tienen sentido, y se requieren varias restricciones para evitar esto.
Sobre eliminar subciclosUna forma podría ser introducir cantidades auxiliares no negativas
fijr,i,j in barV,r inR El conjunto de relaciones registradas usando estas cantidades elimina combinaciones de valores
xijr definiendo rutas que no son un bucle conectado.
sumi inVf0jr= sumi inVzir, quadr inR,
fijr leqnxijr, quadi in barV,j in barV,r inR,
sumj in barVfjir= sumj in barVfijr+zir, quadi inV,r inR.
Estas proporciones especifican el flujo desde el depósito al resto de los puntos de ruta. En cada punto intermedio, se absorbe una unidad de flujo, por lo que para que la red tenga un flujo de energía igual al número de puntos menos uno, es necesario que la ruta esté conectada.
Satisfacer los requisitos en el momento de la llegada del camión en cada puntoEn otras palabras, debe visitar los puntos solo dentro de las ventanas de tiempo indicadas por los curadores. A través de
Bi y
Ei denotar, respectivamente, el comienzo y el final del intervalo de tiempo en el que el curador del punto
i Puede asistir.
Para rastrear la implementación de estas restricciones, necesitamos información sobre el tiempo que pasa el camión durante las paradas y cruces en la ruta. A través de
Li,i enV denota la duración de la carga en el punto
i y a través de
Dij,i,j in barV - tiempo de moverse desde un punto
i hasta el punto
j Hacemos una reserva que
D0i=0 para todos
i in barV y generalmente se puede realizar
Dij neqDji para cualquier
i neqjIntroducimos variables no negativas
ai,i in barV y
wir,i in barV,r inR igual a los tiempos de llegada y de espera en el punto
i al conducir por una ruta
r , respectivamente. Para los valores ingresados, se deben cumplir las siguientes relaciones.
El tiempo de espera no puede ser inferior al tiempo requerido para cargar
wir geqLizir, quadi in barV,r inR,
e igual a cero si el punto no pertenece a la ruta
rwir leqMzir, quadi in barV,r inR,
Hora de llegada al punto
j calculado en los momentos apropiados para el punto anterior
i Aquí hay una constante bastante grande
M Se utiliza para eliminar dependencias innecesarias al moverse entre
i y
j no hecho
ai+ sumr inRwir+Dij leqaj+M(1− sumr inRxijr), quadi inI,j enV,
La llegada y salida del camión debe estar dentro del intervalo indicado por el curador.
ai geqBi, quadi enV,
ai+ sumr inRwir leqEi, quadi inV.
Determinar el tipo de camión necesario para dar servicio a cada rutaDenota los muchos tipos de camiones disponibles para alquilar por
T Tipo de camión
t enT caracterizado por el volumen corporal
Ct y el costo de una hora de alquiler
Pt Tiempo mínimo de alquiler de camiones
t denotar por
U0t La cantidad de reciclables recogidos en el punto
i enV denotar por
GiIntroducimos variables
ytr,t enT,r enR igual a uno si el tipo de camión
t asignado a la ruta de servicio con número
r , y cero en caso contrario.
Variables enteras
utr,t enT,r enR establecer el momento de alquilar un tipo de camión
t sirviendo la ruta con número
rPara cada ruta,
r enR , debe asignar el tipo de camión:
sumt enTytr=1, quadr enR
De acuerdo con el desglose de puntos entre rutas, algunas rutas pueden resultar triviales, es decir, contener solo depósitos. Si la ruta
r no trivial, entonces el camión asignado se alquila al menos
U0t horas
utr geqU0t(ytr− sumi enVzir), quadt enT,r enR.
Al mismo tiempo, la duración del contrato de arrendamiento también debe exceder la duración total de estacionamiento y movimiento a lo largo de la ruta.
utr geq sumi inV sumj in barVDijxijr+ sumi in barVwir−M(1−ytr), quadr enR,t enT.
Agregue restricciones al proporcionar la propiedad: si el camión es de tipo
t no asignado a una ruta
r , su tiempo de alquiler es cero.
utr leqMytr.
Todos los reciclables recogidos en los puntos de ruta deben caber en la parte trasera del camión.
sumi enVGizir leq sumt enTCtytr, quadr enR.
Finalmente, nuestro objetivo es minimizar el costo de alquilar camiones, que, utilizando las designaciones introducidas, se escribe como
sumt inT sumr inRPtutrBusca una solución
Es fácil verificar que todas las expresiones involucradas en el modelo de optimización son funciones lineales de variables, por lo tanto, para encontrar las soluciones exactas y aproximadas, puede usar paquetes estándar para resolver problemas de programación de enteros mixtos como
Gurobi ,
CPLEX ,
Xpress ,
ORtools ,
SCIP ,
BLIS , etc.
Escribimos un modelo para minimizar los costos de transporte en el lenguaje GMPL. Esto nos permitirá usar el paquete
GLPK gratuito para nuestros propósitos. Para escribir código y depurar el modelo, será conveniente descargar el
entorno de desarrollo
GUSEK , que ya contiene GLPK en su composición.
GUSEK se ve así:

A la izquierda vemos una descripción del modelo, y a la derecha hay una ventana para mostrar información sobre el progreso del cálculo, que el solucionador proporcionará después del lanzamiento.
Descripción completa del modelo.param numOfPoints > 0, integer; # param numOfTypes > 0, integer; # param numOfRoutes = numOfPoints;# set V := 1 .. numOfPoints; # set Vbar := V union {0}; # () set T := 1 .. numOfTypes; # set R := 1 .. numOfPoints; # ############### param WDL >= 0, default 8; # param B{i in Vbar} >= 0; # param E{i in Vbar} >= 0; # param L{i in Vbar} >= 0; # param D{i in Vbar, j in Vbar} >= 0, <= WDL; # param G{i in V}, >= 0; # , 3 ########## param C{t in T}, >= 0; # param P{t in T}, >= 0; # param U0{t in T}, >= 0; # , /********************************************** * **********************************************/ var z{Vbar, R} binary; # , , st pointToGroup 'point to group' {i in V}: sum{r in R} z[i, r] == 1; st depotToGroup 'depot to group' {r in R}: z[0, r] == 1; st lexMinGroups 'lexicographycally minimal division' {i in V, r in R: r <= i}: 1 - z[i, r] <= sum{j in V: j <= i - 1}(1 - sum{k in R: k <= r - 1} z[j, k]) + sum{k in R: k <= r - 1}z[i, k] ; /********************************************** * **********************************************/ var x{Vbar, Vbar, R} binary; # , c r i j, . st visitPoint 'visit point' {i in Vbar, r in R}: sum{j in Vbar} x[i, j, r] = z[i, r]; st keepMoving 'keep moving' {i in Vbar, r in R}: sum{j in Vbar} x[j, i, r] = sum {j in Vbar} x[i, j, r]; var f{Vbar, Vbar, R} >= 0; #, . st flowFromDepot 'flow from depot' {r in R}: sum{i in V} f[0, i, r] == sum{i in V} z[i, r]; st flowAlongActiveArcs 'flow along active arcs' {i in Vbar, j in Vbar, r in R}: f[i, j, r] <= numOfPoints * x[i, j, r]; st flowConservation 'flow conservation' {i in V, r in R}: sum{j in Vbar} f[j, i, r] == sum{j in Vbar} f[i, j, r] + z[i, r]; var a{i in V} >= 0; # var w{i in Vbar, r in R} >= 0; # st wait 'wait'{i in Vbar, r in R}: w[i, r] >= L[i] * z[i, r]; st dontWait 'dont wait'{i in Vbar, r in R}: w[i, r] <= (E[i] - B[i]) * z[i, r]; st arrivalTime 'arrival time' {i in V, j in V}: a[i] + sum{r in R}w[i, r] + D[i,j] <= a[j] + 3 * WDL * (1 - sum{r in R} x[i, j, r]); st arriveAfter 'arrive after' {i in V}: a[i] >= B[i]; st departBefore 'depart before' {i in V}: a[i] + sum{r in R}w[i, r] <= E[i]; /********************************************** * , **********************************************/ var y{t in T, r in R}, binary; # , t r, . var u{t in T, r in R}, integer, >= 0; # t, rst assignVehicle 'assign vehicle' {r in R}: sum{t in T} y[t,r] == 1; st rentTime 'rent time' {r in R, t in T}: u[t, r] >= sum{i in V, j in Vbar}D[i, j] * x[i, j, r] + sum{i in Vbar}w[i, r] - WDL * (1 - y[t, r]); st minRentTime 'minimal rent time' {r in R, t in T}: u[t, r] >= U0[t] * (y[t, r] - sum{i in V}z[i, r]); st noRent 'no rent' {t in T, r in R}: u[t, r] <= WDL * y[t, r]; st fitCapacity 'fit capacity' {r in R}: sum{i in V} G[i] * z[i, r] <= sum{t in T} C[t] * y[t, r]; minimize rentCost: sum{t in T, r in R} P[t] * u[t, r]; solve; /********************************************** * **********************************************/ printf{i in V, r in R} (if 0.1 < z[i,r] then "point %s to group %s\n" else ""), i, r, z[i,r]; printf{r in R, i in Vbar, j in Vbar} (if 0.1 < x[i, j, r] then "route %s: %s -> %s\n" else ""), r, i, j; printf{i in V} "point %s arrive between %s and %s (actual = %s)\n", i, B[i], E[i], a[i]; end;
Para comenzar rápidamente, también agregaré datos tomados de mi cabeza preparados para su uso en el modelo:
Datos de entrada data; param numOfPoints := 9; # param numOfTypes := 6; # ############### param : B E L := 0 0 8 1 1 0 8 1 2 0 8 1 3 0 8 1 4 0 8 1 5 0 8 1 6 0 8 1 7 0 8 1 8 0 8 1 9 0 8 1; param D default 0 : 0 1 2 3 4 5 6 7 8 9 := 0 . . . . . . . . . . 1 0.1 0.3 0.2 0.1 0.2 0.1 0.2 0.1 0.2 0.1 2 0.3 0.2 0.2 0.1 0.2 0.1 0.2 0.1 0.2 0.1 3 0.4 0.3 0.2 0.1 0.2 0.1 0.2 0.1 0.2 0.1 4 0.4 0.4 0.2 0.1 0.2 0.1 0.2 0.1 0.2 0.1 5 0.1 0.2 0.2 0.1 0.2 0.1 0.2 0.1 0.2 0.1 6 0.5 0.5 0.2 0.1 0.2 0.1 0.2 0.1 0.2 0.1 7 0.3 0.2 0.2 0.1 0.2 0.1 0.2 0.1 0.2 0.1 8 0.2 0.1 0.2 0.1 0.2 0.1 0.2 0.1 0.2 0.1 9 0.5 0.2 0.2 0.1 0.2 0.1 0.2 0.1 0.2 0.1; param G := 1 1 2 2 3 1 4 2 5 1 6 2 7 1 8 2 9 1; ########## param : C P := 1 8 500 2 10 500 3 14 600 4 18 650 5 25 700 6 35 800; param U0 default 2; # , end;
Después de copiar el código del modelo en un archivo con el nombre, por ejemplo, model.mod, y los datos de entrada al archivo data.dat, todo está listo para ejecutarse. Establecemos un límite en el tiempo de cálculo de 100 segundos (esto se hace usando la tecla --tmlim [tiempo en segundos]), transferimos la ruta al archivo con los datos de entrada (usando la tecla -d [ruta del archivo]),

y presione F5. Si tiene éxito, aparecerán mensajes en la ventana de la derecha, y después de cien segundos tendremos la mejor solución que GLPK logró encontrar en el tiempo asignado.

En el texto azul, nos interesa el significado después de la inscripción "mip =". Como puede ver, disminuye de vez en cuando. Todas las nuevas soluciones están en proceso de trabajo, el valor de los costos de transporte en el mejor de los casos se muestra en esta columna (hay 14700 hasta ahora). El siguiente número es el límite inferior para la mejor solución existente, es decir,
óptima . Inicialmente, la estimación se subestima significativamente, pero se refina con el tiempo, es decir, aumenta. Los valores a la izquierda y a la derecha son convergentes, y la brecha relativa entre ellos en el momento de la captura de pantalla es del 54,1%. Tan pronto como este número sea cero, el algoritmo demostrará que la mejor solución encontrada es la mejor posible. No siempre se justifica esperar este evento en la práctica, y no solo porque es mucho tiempo, sino que es importante hacer una reserva de que, por regla general, una buena solución es relativamente rápida, y los costos de tiempo principales están asociados con el refinamiento de la estimación requerida para probar lo mejor posible.
En lugar de una conclusión
Los problemas de enrutamiento son extremadamente complejos desde el punto de vista informático, y con el aumento en el número de puntos que deben visitarse, el tiempo requerido para que un solucionador encuentre una solución y demuestre que su optimización está creciendo rápidamente. Sin embargo, para ejemplos bastante pequeños, en un período de tiempo razonable, el solucionador puede construir un conjunto exitoso de rutas y puede usarse para apoyar la toma de decisiones. El análisis de las opciones de enrutamiento propuestas por el modelo nos ayudó a descubrir oportunidades significativas para la reducción de costos, y esto es crítico para la existencia y el desarrollo del stock.
Nuestros esfuerzos adicionales se dirigieron al trabajo con incertidumbre en los volúmenes de reciclables recogidos en los puntos. Estamos desarrollando una serie de modelos de programación estocástica para tomar decisiones estratégicas y operativas en el enrutamiento de camiones. Si el tema resulta relevante y despierta interés, escribiré sobre esto también, porque pronto todos tendremos que profundizar más en la resolución de problemas ambientales, que es en lo que deseo que tengamos éxito.