Problemas de flujos. Existen muchos problemas de flujos en redes. Una red es un sistema de líneas o canales que conectan diferentes puntos y trasmiten algún tipo de información. Algunos ejemplos de redes son las líneas de comunicación, redes de ferrocarril, redes de tuberías de agua, redes de carreteras, redes de aviación, etc. En todas estas redes estaremos interesados en enviar alguna mercancía específica desde ciertos puntos de suministro a algunos puntos de demanda. Por ejemplo, en un sistema de tuberías podríamos enviar agua. Muchos de los problemas de flujos en redes se pueden formular como problemas de programación lineal y obtener su solución mediante el método del simplex. Sin embargo, se han desarrollado otras técnicas más eficientes que varían con el problema en cuestión. De entre este tipo de problemas destacamos destacamos los siguientes:
-
Problema de flujo máximo.
-
Problema de flujo a coste mínimo.
Problema de flujo Máximo. Se considera el problema de trasladar una cierta mercancía desde un punto específico, llamado fuente a un punto de destino, denominado sumidero. Para ello se considera un grafo dirigido G = (V,A), en el que se consideran dos nodos o vértices: uno denominado denominado nodo fuente y otro denominado nodo destino. Por supuesto, se considera que no existe un arco directo que conecte el nodo fuente con el nodo destino. Por supuesto, el grafo estará formado por unos nodos intermedios conocidos como puntos de transbordo a través de los cuales el flujo (la mercancía) es desviado. Sea V = conjunto de todos los vértices o nodos del grafo. f ijij = el flujo que circula por el arco (i,j). f = cantidad total de flujo que se lleva desde el el nodo fuente al nodo destino. k ijij = capacidad del arco (i,j). 1
Ejemplo: s = nodo fuente n = nodo destino 1, 2 = nodos intermedios
s
n 2
Objetivo: Determinar el máximo flujo f que se puede enviar desde el nodo fuente s al nodo destino n, teniendo en cuenta las capacidades k ij sobre el flujo de cada arco (i,j) y que el flujo se debe conservar.
Modelo de programación lineal:
Max
z = f
s.a.
∑ f +
ij
−
j∈Γ ( i )
∑ f −
ji
=0
∀i ∈ V - {s, n}
(1.1)
j∈Γ ( i )
0 ≤ f ij ≤ k ij
∀(i, j) ∈ A
(1.2)
Las ecuaciones (1.1) representan la conservación del flujo en los nodos. Mientras que las restricciones (1.2) son sobre el flujo que circula por cada arco, para que no sea negativo y no supere la capacidad del arco. En el ejemplo anterior se traduce en Max s.a.
z = f f s1 + f s 2 = f f 12 + f 1n = f s1 + f 21 f 21 + f 2 n = f s 2 + f 12 f 1n + f 2 n = f
0 ≤ f s1 ≤ k s1 0 ≤ f s 2 ≤ k s 2 0 ≤ f 12 ≤ k 12 0 ≤ f 21 ≤ k 21 0 ≤ f 1n ≤ k 1n 0 ≤ f 2 n ≤ k 2 n
Veamos un método eficiente para resolver el problema del flujo máximo directamente sin usar el método del simplex.
Conceptos previos: Definición: Dado cualquier nodo i todos los arcos que salen del nodo i se denominan arcos hacia delante con respecto al nodo i.
Definición: Dado cualquier nodo i todos los arcos que entran al nodo i se denominan arcos hacia atrás para el nodo i.
Definición: Un corte que separa el nodo fuente del nodo destino es una partición de los *
nodos de la red en dos subconjuntos S y S tal que el nodo fuente está en S y el nodo *
destino está en S . Un ejemplo de corte en el ejemplo anterior podría ser (S, S*) dado por S = {s,1,2}. 1 s
n 2
Corte Otro corte que separa s y n es el siguiente:
1 s
n 2
Corte
Definición: La capacidad de un corte es la suma de todas las capacidades de los arcos procedentes * * de los nodos de S a los nodos en S . Se denota K(S, S ). Esto es
K ( S , S ) = *
∑ k
ij ( i , j )∈( S , S * )
En los cortes anteriores, sus capacidades son: *
S = {s,1,2}, K(S,S ) = k 1n + k 2n S = {s,2}, K(S,S*) = k s1 + k 21 + k 2n
Definición: El corte con la capacidad más pequeña se denomina corte mínimo.
A partir de los ejemplos anteriores de cortes se puede apreciar que si todos los arcos de un corte se eliminan de la red entonces no existe un camino que una el nodo fuente con el nodo destino, de aquí que el flujo de s a n no seria posible. En otras palabras, cualquier flujo de s a n debe atravesar los arcos en el corte, y por consiguiente, el flujo f estará limitado por la capacidad de ese corte. La relación entre flujos y cortes vendrá dada por el siguiente lema:
Lema: Para cualquier red dirigida, si f es el flujo desde el nodo fuente al nodo destino, *
y (S, S ) es un corte, entonces el valor de f es menor o igual que la capacidad de ese *
corte K(S,S ). Como consecuencia de este lema se tiene que cualquier flujo compatible desde el nodo fuente al nodo destino no puede exceder la capacidad de ningún corte. Por tanto, el flujo máximo a través de la red está limitado por la capacidad del corte mínimo. El siguiente teorema establece que siempre es posible encontrar el flujo de s a n igual a la capacidad del corte mínimo.
Teorema de flujo máximo-corte mínimo: (Ford Fulkerson). Para cualquier red el flujo máximo desde el nodo fuente al nodo destino es igual a la capacidad del corte mínimo.
A partir de este teorema el problema de encontrar el flujo máximo en una red se traduce en encontrar las capacidades de todos los cortes y elegir la mínima capacidad. Por otra parte, dado el valor máximo de f no se especifica como este flujo es distribuido a través de los distintos arcos. Además este método es poco recomendable ya que el número de posibles cortes que separan el nodo fuente del destino son 2
n-2
.
Definición: Dada una red G = (V,A) llamamos Red Residual o Incrementeal R(f), a aquella red formada a
partir de G, con el mismo conjunto de nodos que ésta, y dado
cada arco dirigido (i,j) ∈ A en la red original, que no tiene arco en la dirección opuesta (es decir, (j,i) ∉ A), tal que 0 ≤ f ij ≤ k ij se consideran en la Red Incremental dos arcos (i,j) y (j,i) con capacidades
rij = k ij - f ij
y r ji = f ij , respectivamente.
A dichas
capacidades se las denomina capacidades residuales o incrementales .
Al principio que no circula ningún flujo por los arcos de la red original, la red residual difiere de la original en que para cada arco dirigido de la red original sin arco opuesto, ahora se le añade su opuesto con capacidad nula.
Definición: Se denomina Camino Incremental a todo camino dirigido desde el nodo fuente al nodo destino en la red incremental.
Definición: Llamamos Cuello de Botella y lo denotamos por δ a la menor capacidad residual de los arcos en un camino incremental, es decir, δ = min
(i,j) ∈P
rij. Dado el
siguiente camino P ⊂ R(f) 5 s
3
a
2 b
n
δ= 2
Definición: Un arco se dice saturado sí y solo sí f ij = k ij ó rij = 0 y k ij > 0.
El motivo de introducir el concepto de red residual o red incremental se debe a los siguiente, fijémonos en la red siguiente: 1 1
2 1
2
1
1 n
s
1 3
Si se elige como primer camino incremental P = {(s,1),(1,3),(3,2),(2,n)} entonces saturo los arcos (1,3),(3,2) y (2,n) y no podemos enviar más flujo de s a n consiguiendo un valor para f = 1, cuando el flujo máximo es f = 2. Sin
embargo,
tomando
ahora
el
camino
incremental
P’
=
{(s,1),(1,2),(2,3),(3,n)} podemos enviar una unidad más de s a n y deshacer el error cometido al enviar una unidad de flujo a través del arco (3,2). Notemos que ahora se ha enviado una unidad de flujo a través del arco (2,3), el cual no existe en la red original.
El algoritmo de flujo máximo consiste en encontrar un camino a través del cual se puede enviar un flujo positivo desde el nodo fuente al nodo destino. Tal camino es a lo que denominabamos camino incremental, y se usa para enviar tanto flujo como sea posible desde s a n. El proceso se repite hasta que no se pueda encontrar ningún otro camino incremental, que mejore el flujo total de s a n. En dicho caso, se ha encontrado el flujo máximo.
Proceso de etiquetado: Este proceso se usa para encontrar un camino incremental desde el nodo fuente al nodo destino. Comenzando con el nodo fuente s, se dice que cualquier nodo j se puede etiquetar si podemos enviar un flujo positivo desde s a j. En general, desde cualquier nodo i podemos etiquetar el nodo j si se satisface una de las siguientes condiciones: 1.- El arco que conecta los nodos i y j es un arco hacia delante y el flujo en el arco (i,j) es menor que su capacidad ( es decir, f ij ≤ k ij). 2.- El arco que conecta i y j es un arco hacia atrás y el flujo en el arco (j,i) es mayor que 0. Se continúa el proceso de etiquetado hasta que el nodo destino sea etiquetado. Entonces se ha conseguido un camino incremental.
Algoritmo del Flujo Máximo: El algoritmo se inicializa con un flujo nulo o cualquier flujo factible en todos los arcos, esto es, satisfaciendo las restricciones de capacidad y conservación de los flujos en todos los nodos. Para mejorar este flujo, se etiqueta inicialmente el nodo s y se aplica el proceso de etiquetado para etiquetar los otros nodos hasta alcanzar el destino. Cuando esto ocurra tendremos un camino incremental desde s a n a través del cual se puede enviar un flujo positivo. A continuación, volvemos hacia atrás en el camino incremental con la ayuda de las etiquetas de los nodos y calculamos el flujo máximo δ que puede ser enviado por el camino. Entonces incrementamos el flujo en δ unidades en todos los arcos hacia delante en el camino incremental y decrementamos el flujo en δ unidades en todos los arcos hacia atrás. Repetimos el proceso de etiquetado para encontrar otro camino incremental desde s a n. El algoritmo termina cuando no se pueda encontrar ningún otro camino incremental, lo que nos conduce al máximo flujo posible de s a n.
ALGORITMO:
Paso 0: Se inicializa f = 0 ( o cualquier flujo factible) y f ij = 0 ∀ (i,j) ∈ A. Se construye la red incremental, que coincide con la original. Esto es, rij = k ij para todo arco en la red original y se añade su opuesto con r ji = 0. Sea δ = ∝. Sea hace i = s el nodo fuente, se marca con Pred i = 0.
Paso 1: Se elige un j ∈ Γ(i) no marcado tal que r ij > 0 para el arco (i,j) y se marca con Pred j = i. Se asigna δ = min{δ,rPredj j}. En caso de que no exista y si i = s parar ya que se ha alcanzado el máximo flujo posible que se puede enviar desde s a n. Si i ≠ s se hace i = Pred i y se busca otro j ∈ Γ(i), no marcado con r ij > 0.
Paso 2: Si j = n, hacer f = f + δ, e ir al paso 3. En caso contrario, hacer i = j y repetir el paso 1.
Paso 3: Cambiamos rPredj j = rPredj j - δ y r j Predj = r j Predj + δ. Hacer j = Pred j, si j = s ir al paso 4. En otro caso, repetimos el paso 3.
Paso 4: Se borran todas las marcas menos la de s, sea s = i. Se vuelve a asignar δ =
∝ y se va al paso 1.
Ejemplo: Sea la siguiente red en la cual los números sobre los arcos representan las capacidades. 9
1
7
f=0
f=0 s
n
3
9
8
2
Camino incremental
1
7
s
n
3
8
2
9
1
4
3
f=3
f=3
s
n 3
0
9
3
5
2
Nuevo camino incremental 9
1
4
s
n
5
1
0
4
7
f = 12 s
0
f = 12 n
3
0
5
4
8
2
1 5
s
n 3
4
2
7
f = 15
7
1
0
2
f = 15
7
s
0
3
n 8
8 1
0
2
Extensiones: Caso dirigido: Consideremos una red que contiene aristas en lugar de arcos. Dada una arista que conecta los nodos i y j, con capacidad K lo interpretamos como sigue: f ij ≤ K f ji ≤ K f ij * f ji = 0 En otras palabras, un máximo de K unidades de flujo es posible entre los nodos i y j en cualquier dirección, pero el flujo se permite en una única dirección. Tengamos en cuenta que el algoritmo visto anteriormente sólo se puede aplicar a redes dirigidas donde la dirección del flujo se especifica en todos los arcos. Para encontrar el flujo máximo en una red no dirigida primero convertimos la red en una red equivalente dirigida, y entonces aplicamos el método de etiquetado.
Ejemplo: Consideremos una red de calles como se muestra en el grafo
30
1
40
3 50
s
15
s
25
20
30 30
2
50
4
Problema de flujo a coste mínimo.Sea G = (V,A) un grafo con dos vértices fijos, s el nodo fuente y t el nodo destino. Cada arco (i,j) ∈ A tiene asociada una capacidad k ij y un coste por unidad de flujo que circula por cada arco cij.
Sea Φ la cantidad de flujo demandada desde el nodo t, para ser
servida desde el nodo s. Entonces podemos plantear el problema de flujo a coste mínimo en los siguientes términos: enviar Φ unidades de flujo desde el nodo s al nodo t de G = (V,A) con el patrón de flujo cuyo coste asociado sea el mínimo, satisfaciendo las restricciones de capacidad y conservación en los nodos V – {s,t}. En este caso el patrón de flujo f de ser tal que :
∑ f − ∑ f Conservación del flujo
j∈Γi
+
ij
j∈Γi
∑ f j∈Γs
Restricciones de capacidad
+
sj
=
ij
−
∑ f −
=0
jt
∀V − {s, t }
=Φ
j∈Γt
0 ≤ f ij ≤ k ij
∀(i, j) ∈ A
Mientras que el coste del patrón de flujo viene dado por Z ( f ) =
∑ c f ij
ij
( i , j )∈ A
Red residual.La red residual R(f) correspondiente a un flujo f se define como sigue: Reemplazamos cada arco (i,j) ∈ A por dos arcos (i,j) y (j,i). El arco (i,j) tiene un coste cij y una capacidad residual de r ij = k ij – f ij, y el arco (j,i) tiene un coste de c ji = -cij y una capacidad residual de r ji = f ij. En la red residual se consideran sólo los arcos con capacidad positiva.
Algoritmo de Busacker. El algoritmo de Busacker y Gowen (1961) intenta enviar las Φ unidades de flujo de s a t eligiendo en cada iteración el camino de mínimo coste de s a t, que envía un flujo igual al cuello de botella del camino. El algoritmo termina cuando se han enviado las Φ unidades de flujo, o no hay camino de s a t. En este último caso el problema no tiene solución. Denotamos: CT = coste total del camino que envía las Φ unidades CC = coste del camino mínimo que se calcula en cada iteración. Sea G = (V,A) un grafo dado, y s y t dos vértices fijados a priori.
Paso 1: Asignar CT = 0. Construir la red incremental de G, y asignar ⎧k ij si (i, j ) ∈ A r ij = ⎨ ⎩0 en otro caso
⎧cij * cij = ⎨ ⎩∞
si (i, j ) ∈ A en otro caso
Paso 2: Buscar el camino mínimo de s a t en la red
incremental usando el
algoritmo de Ford, y almacenarlo en Pred i ∀ i = s,...,t. Asignar a CC el coste de tal camino . Si no existe tal camino Parar, no hay solución factible. Sea δ = ∝ e i = t.
Paso 3: Si i = s, hacer i = t e ir al Paso 4. En otro caso , si δ > rPredi,i entonces δ = rPredi,i . Hacer i = Pred i y repetir el paso 3.
Paso 4: Si Φ - δ > 0 entonces asignar θ = δ. En otro caso hacer θ = Φ.
Paso 5: Si i = s, ir al Paso 6. En otro caso, rPredi,i = rPredi,i - θ, ri,Predi = ri,Predi + θ *
*
ci,Predi = - cPredi,i
y para aquellos arcos tales que r Predi,i = 0 entonces c Predi,i = ∝. *
Hacer i = Predi y repetir el Paso 5.
Paso 6: Asignar CT = CT + θ * CC. Si Φ - δ > 0 hacer Φ = Φ - δ y buscar un nuevo camino de coste mínimo de s a t pero con los nuevos costes asignados a los arcos. Almacenarlo en Pred
∀ i = s,...,t y asignar a CC el coste de tal camino. Hacer δ = ∝ e i = t e ir al Paso 3. En otro caso de que no exista tal camino, parar puesto que no existe solución factible. Si Φ - δ ≤ 0, parar hemos encontrado el camino de flujo a coste mínimo.
Ejemplo:
1
(5,20)
2
(3,18)
(5,14)
(4,15)
s
t (8,12)
(8,20)
3
(3,17)
i