Articulo de referencia

Algoritmos paralelos para árboles de expansión mínima

En teoría de grafos, un árbol de expansión mínima (MST) T {\displaystyle T} de un gráfico GRAMO = ( V , mi ) {\displaystyle G=(V,E)} con | V | = norte {\displaystyle |V|=n} y | ...

En teoría de grafos, un árbol de expansión mínima (MST)T{\displaystyle T}de un gráficoGRAMO=(V,mi){\displaystyle G=(V,E)}con|V|=norte{\displaystyle |V|=n}y|mi|=metro{\displaystyle |E|=m}es un subgrafo de árbol deGRAMO{\displaystyle G}que contiene todos sus vértices y tiene un peso mínimo.

Los MST son herramientas útiles y versátiles que se utilizan en una amplia variedad de campos prácticos y teóricos. Por ejemplo, una empresa que busca abastecer a varias tiendas con un determinado producto desde un único almacén podría usar un MST que se origine en el almacén para calcular las rutas más cortas a cada tienda. En este caso, las tiendas y el almacén se representan como vértices y las conexiones viales entre ellos, como aristas. Cada arista está etiquetada con la longitud de la conexión vial correspondiente.

SiGRAMO{\displaystyle G}En el caso sin ponderación de aristas, cada árbol de expansión posee el mismo número de aristas y, por lo tanto, el mismo peso. En el caso con ponderación de aristas , el árbol de expansión, cuya suma de los pesos de las aristas es la más baja entre todos los árboles de expansión deGRAMO{\displaystyle G}, se denomina árbol de expansión mínima (MST). No es necesariamente único. De manera más general, los grafos que no están necesariamente conectados tienen bosques de expansión mínima , que consisten en una unión de MST para cada componente conectado .

Como encontrar MST es un problema generalizado en la teoría de grafos, existen muchos algoritmos secuenciales para resolverlo. Entre ellos se encuentran los algoritmos de Prim , Kruskal y Borůvka , cada uno utilizando diferentes propiedades de los MST. Todos operan de manera similar: un subconjunto demi{\displaystyle E}se desarrolla iterativamente hasta que se descubre un MST válido. Sin embargo, dado que los problemas prácticos suelen ser bastante grandes (las redes de carreteras a veces tienen miles de millones de aristas), el rendimiento es un factor clave. Una opción para mejorarlo es paralelizando los algoritmos MST conocidos . [ 1 ]

El algoritmo de Prim

Este algoritmo utiliza la propiedad de corte de los MST. A continuación se proporciona una implementación sencilla en pseudocódigo de alto nivel :

T{\displaystyle T\gets \emptyset }S{s}{\displaystyle S\gets \{s\}}dóndes{\displaystyle s}es un vértice aleatorio enV{\displaystyle V}repetir|V|1{\displaystyle |V|-1}veces encontrar el borde más ligero(,v){\displaystyle (u,v)}calleS{\displaystyle u\in S}perov(VS){\displaystyle v\in (V\setminus S)}SS{v}{\displaystyle S\gets S\cup \{v\}}TT{(,v)}{\displaystyle T\gets T\cup \{(u,v)\}}devolver T

Cada arista se observa exactamente dos veces, es decir, al examinar cada uno de sus extremos. Cada vértice se examina exactamente una vez para un total deO(norte+metro){\displaystyle O(n+m)}operaciones aparte de la selección del borde más ligero en cada iteración del bucle. Esta selección a menudo se realiza utilizando una cola de prioridad (PQ). Para cada borde como máximo una operación decreaseKey ( amortizada enO(1){\displaystyle O(1)}) se realiza y cada iteración del bucle realiza una operación deleteMin (O(registronorte){\displaystyle O(\log n)}). Por lo tanto, utilizando montículos de Fibonacci, el tiempo total de ejecución del algoritmo de Prim es asintóticamente enO(metro+norteregistronorte){\displaystyle O(m+n\log n)}.

Es importante señalar que el bucle es inherentemente secuencial y no se puede paralelizar correctamente. Este es el caso, ya que el borde más ligero con un extremo enS{\displaystyle S}y enVS{\displaystyle V\setminus S}podría cambiar con la adición de bordes aT{\displaystyle T}Por lo tanto, no se pueden realizar dos selecciones del borde más claro al mismo tiempo. Sin embargo, existen algunos intentos de paralelización .

Una posible idea es utilizarO(norte){\displaystyle O(n)}procesadores para admitir el acceso PQ enO(1){\displaystyle O(1)}en una máquina EREW-PRAM , [ 2 ] reduciendo así el tiempo total de ejecución aO(norte+metro){\displaystyle O(n+m)}.

El algoritmo de Kruskal

El algoritmo MST de Kruskal utiliza la propiedad de ciclo de los MST. A continuación se proporciona una representación en pseudocódigo de alto nivel.

T{\displaystyle T\gets }bosque con cada vértice en su propio subárbol para cada(,v)mi{\displaystyle (u,v)\in E}en orden ascendente de peso si{\displaystyle u}yv{\displaystyle v}en diferentes subárboles deT{\displaystyle T}TT{(,v)}{\displaystyle T\gets T\cup \{(u,v)\}}devolver T

Los subárboles deT{\displaystyle T}se almacenan en estructuras de datos de unión-búsqueda , por lo que es posible comprobar si dos vértices están o no en el mismo subárbol en amortizadoO(α(metro,norte)){\displaystyle O(\alpha (m,n))}dóndeα(metro,norte){\displaystyle \alpha (m,n)}es la función inversa de Ackermann . Por lo tanto, el tiempo total de ejecución del algoritmo es deO(sort(norte)+α(norte)){\displaystyle O(sort(n)+\alpha (n))}. Aquíα(norte){\displaystyle \alpha (n)}denota la función inversa de Ackermann de valor único, para la cual cualquier entrada realista produce un número entero menor que cinco.

Enfoque 1: Paralelización del paso de ordenación

De forma similar al algoritmo de Prim, existen componentes en el enfoque de Kruskal que no pueden paralelizarse en su variante clásica. Por ejemplo, determinar si dos vértices están o no en el mismo subárbol es difícil de paralelizar, ya que dos operaciones de unión podrían intentar unir los mismos subárboles al mismo tiempo. En realidad, la única oportunidad de paralelización reside en el paso de ordenación. Como la ordenación es lineal en el caso óptimo enO(registronorte){\displaystyle O(\log n)}procesadores, el tiempo total de ejecución se puede reducir aO(metroα(norte)){\displaystyle O(m\alpha (n))}.

Enfoque 2: Filtro-Kruskal

Otro enfoque sería modificar el algoritmo original aumentandoT{\displaystyle T}de forma más agresiva. Esta idea fue presentada por Osipov et al. [ 3 ] [ 4 ] La idea básica detrás de Filter-Kruskal es particionar las aristas de forma similar a quicksort y filtrar las aristas que conectan vértices que pertenecen al mismo árbol para reducir el costo de ordenación. A continuación se proporciona una representación en pseudocódigo de alto nivel.

filtroKruskal(GRAMO{\displaystyle G}): simetro<{\displaystyle m<}KruskalThreshold: devolver kruskal(GRAMO{\displaystyle G}) pivote = elegirAleatorio(mi{\displaystyle E}) (mi{\displaystyle (E_{\leq }},mi>){\displaystyle E_{>})\gets }dividir(mi{\displaystyle E}, pivote) A{\displaystyle A\gets }filtroKruskal(mi{\displaystyle E_{\leq }}) mi>{\displaystyle E_{>}\gets }filtrar(mi>{\displaystyle E_{>}}) AA{\displaystyle A\gets A}{\displaystyle \cup }filtroKruskal(mi>{\displaystyle E_{>}}) devolverA{\displaystyle A} dividir(mi{\displaystyle E}, pivote): mi{\displaystyle E_{\leq }\gets \emptyset }mi>{\displaystyle E_{>}\gets \emptyset }para cada(,v)mi{\displaystyle (u,v)\in E}: si peso(,v{\displaystyle u,v}){\displaystyle \leq }pivote: mimi(,v){\displaystyle E_{\leq }\gets E_{\leq }\cup {(u,v)}}demásmi>mi>(,v){\displaystyle E_{>}\gets E_{>}\cup {(u,v)}}devolver (mi{\displaystyle E_{\leq }},mi>{\displaystyle E_{>}}) filtrar(mi{\displaystyle E}): miFiltmirmid{\displaystyle E_{filtered}\gets \emptyset }para cada(,v)mi{\displaystyle (u,v)\in E}: si find-set(u){\displaystyle \neq }encontrar-conjunto(v): miFiltmirmidmiFiltmirmid(,v){\displaystyle E_{filtered}\gets E_{filtered}\cup {(u,v)}}devolvermiFiltmirmid{\displaystyle E_{filtrado}}

El algoritmo Filter-Kruskal es más adecuado para la paralelización, ya que la ordenación, la partición y el filtrado tienen paralelismos intuitivamente sencillos en los que las aristas simplemente se dividen entre los núcleos.

El algoritmo de Borůvka

La idea principal detrás del algoritmo de Borůvka es la contracción de aristas . Una arista{,v}{\displaystyle \{u,v\}}se contrae eliminando primerov{\displaystyle v}desde el gráfico y luego redirigiendo cada arista{w,v}mi{\displaystyle \{w,v\}\in E}a{w,}{\displaystyle \{w,u\}}Estas nuevas aristas conservan sus pesos originales. Si el objetivo no es solo determinar el peso de un MST, sino también qué aristas lo componen, debe tenerse en cuenta entre qué pares de vértices se contrajo una arista. Representación en pseudocódigo de alto nivel:

T{\displaystyle T\gets \emptyset }mientras|V|>1{\displaystyle |V|>1}S{\displaystyle S\gets \emptyset }paravV{\displaystyle v\in V}SS{\displaystyle S\gets S}{\displaystyle \cup }más ligero{,v}mi{\displaystyle \{u,v\}\in E}para{,v}S{\displaystyle \{u,v\}\in S} contrato{,v}{\displaystyle \{u,v\}}TTS{\displaystyle T\gets T\cup S}devolver T

Es posible que las contracciones den lugar a múltiples aristas entre un par de vértices. La forma intuitiva de elegir la más ligera de ellas no es posible enO(metro){\displaystyle O(m)}Sin embargo, si todas las contracciones que comparten un vértice se realizan en paralelo, esto es factible. La recursión se detiene cuando solo queda un único vértice, lo que significa que el algoritmo necesita como máximoregistronorte{\displaystyle \log n}iteraciones, lo que lleva a un tiempo de ejecución total enO(metroregistronorte){\displaystyle O(m\log n)}.

Paralelización

Una posible paralelización de este algoritmo [ 5 ] [ 6 ] [ 7 ] produce una complejidad temporal polilogarítmica , es decirT(metro,norte,pag)pagO(metroregistronorte){\displaystyle T(m,n,p)\cdot p\in O(m\log n)}y existe una constantedo{\displaystyle c}de modo queT(metro,norte,pag)O(registrodometro){\displaystyle T(m,n,p)\in O(\log ^{c}m)}. AquíT(metro,norte,pag){\displaystyle T(m,n,p)}denota el tiempo de ejecución para un gráfico conmetro{\displaystyle m}bordes,norte{\displaystyle n}vértices en una máquina conpag{\displaystyle p}procesadores. La idea básica es la siguiente:

mientras|V|>1{\displaystyle |V|>1} encontrar los bordes de incidencia más ligeros //O(metropag+registronorte+registropag){\displaystyle O({\frac {m}{p}}+\log n+\log p)} asignar el subgrafo correspondiente a cada vértice //O(nortepag+registronorte){\displaystyle O({\frac {n}{p}}+\log n)} contraer cada subgrafo //O(metropag+registronorte){\displaystyle O({\frac {m}{p}}+\log n)}

El MST consta entonces de todos los bordes más claros encontrados.

Esta paralelización utiliza la representación gráfica de matriz de adyacencia paraGRAMO=(V,mi){\displaystyle G=(V,E)}. Esto consta de tres matrices:Γ{\displaystyle \Gamma }de longitudnorte+1{\displaystyle n+1}para los vértices,γ{\displaystyle \gamma }de longitudmetro{\displaystyle m}para los puntos finales de cada uno de losmetro{\displaystyle m}bordes ydo{\displaystyle c}de longitudmetro{\displaystyle m}para los pesos de las aristas. Ahora para el vérticei{\displaystyle i}el otro extremo de cada borde incidente ai{\displaystyle i}se puede encontrar en las entradas entreγ[Γ[i1]]{\displaystyle \gamma [\Gamma [i-1]]}yγ[Γ[i]]{\displaystyle \gamma [\Gamma [i]]}. El peso deli{\displaystyle i}-º borde enΓ{\displaystyle \Gamma }se puede encontrar endo[i]{\displaystyle c[i]}. Entonces eli{\displaystyle i}-º borde enγ{\displaystyle \gamma }está entre vértices{\displaystyle u}yv{\displaystyle v}si y solo siΓ[]i<Γ[+1]{\displaystyle \Gamma [u]\leq i<\Gamma [u+1]}yγ[i]=v{\displaystyle \gamma [i]=v}.

Encontrar el borde de incidencia más ligero

Primero, los bordes se distribuyen entre cada uno de lospag{\displaystyle p}procesadores. Eli{\displaystyle i}El procesador -ésimo recibe los bordes almacenados entreγ[imetropag]{\displaystyle \gamma [{\frac {im}{p}}]}yγ[(i+1)metropag1]{\displaystyle \gamma [{\frac {(i+1)m}{p}}-1]}. Además, cada procesador necesita saber a qué vértice pertenecen estas aristas (ya queγ{\displaystyle \gamma }(solo almacena uno de los puntos finales del borde) y lo almacena en el array.pagrmid{\displaystyle pred}. Obtener esta información es posible enO(registronorte){\displaystyle O(\log n)}usandopag{\displaystyle p}búsquedas binarias o enO(nortepag+pag){\displaystyle O({\frac {n}{p}}+p)}utilizando una búsqueda lineal . En la práctica, este último método a veces es más rápido, aunque asintóticamente sea peor.

Ahora, cada procesador determina la arista más tenue incidente en cada uno de sus vértices.

v{\displaystyle v\gets }encontrar(imetropag{\displaystyle {\frac {im}{p}}},Γ{\displaystyle \Gamma }) paramiimetropag;mi<(i+1)metropag1;mi++{\displaystyle e\gets {\frac {im}{p}};e<{\frac {(i+1)m}{p}}-1;e++}siΓ[v+1]=mi{\displaystyle \Gamma [v+1]=e}v++{\displaystyle v++}sido[mi]<do[pagrmid[v]]{\displaystyle c[e]<c[pred[v]]}pagrmid[v]mi{\displaystyle pred[v]\gets e}

Aquí surge el problema de que algunos vértices son manejados por más de un procesador. Una posible solución a esto es que cada procesador tenga su propiopagrmiv{\displaystyle prev}matriz que luego se combina con las de los demás mediante una reducción. Cada procesador tiene como máximo dos vértices que también son manejados por otros procesadores y cada reducción está enO(registropag){\displaystyle O(\log p)}. Por lo tanto, el tiempo total de ejecución de este paso es deO(metropag+registronorte+registropag){\displaystyle O({\frac {m}{p}}+\log n+\log p)}.

Asignación de subgrafos a vértices

Observe el grafo que consta únicamente de las aristas recopiladas en el paso anterior. Estas aristas se dirigen alejándose del vértice al que apuntan como la arista incidente más ligera. El grafo resultante se descompone en múltiples componentes débilmente conexas. El objetivo de este paso es asignar a cada vértice el componente del que forma parte. Tenga en cuenta que cada vértice tiene exactamente una arista saliente y, por lo tanto, cada componente es un pseudoárbol: un árbol con una arista adicional que corre en paralelo a la arista más ligera del componente, pero en dirección opuesta. El siguiente código transforma esta arista adicional en un bucle:

paralelo para todosvV{\displaystyle v\in V}wpagrmid[v]{\displaystyle w\gets pred[v]}sipagrmid[w]=vv<w{\displaystyle pred[w]=v\land v<w}pagrmid[v]v{\displaystyle pred[v]\gets v}

Ahora, cada componente débilmente conectado es un árbol dirigido cuya raíz tiene un bucle . Esta raíz se elige como representante de cada componente. El siguiente código utiliza la duplicación para asignar a cada vértice su representante:

mientrasvV:pagrmid[v]pagrmid[pagrmid[v]]{\displaystyle \exists v\in V:pred[v]\neq pred[pred[v]]}para todosvV{\displaystyle v\in V}pagrmid[v]pagrmid[pagrmid[v]]{\displaystyle pred[v]\gets pred[pred[v]]}

Ahora cada subgrafo es una estrella . Con algunas técnicas avanzadas, este paso necesitaO(nortepag+registronorte){\displaystyle O({\frac {n}{p}}+\log n)}tiempo.

Contraer los subgrafos

En este paso, cada subgrafo se contrae a un solo vértice.

k{\displaystyle k\gets }número de subgrafos V{0,,k1}{\displaystyle V'\gets \{0,\dots ,k-1\}} encontrar una función biyectivaF:{\displaystyle f:}raíz estrellada{0,,k1}{\displaystyle \rightarrow \{0,\dots ,k-1\}}mi{(F(pagrmid[v]),F(pagrmid[w]),do,miold):(v,w)mipagrmid[v]pagrmid[w]}{\displaystyle E'\gets \{(f(pred[v]),f(pred[w]),c,e_{old}):(v,w)\in E\land pred[v]\neq pred[w]\}}

Encontrar la función biyectiva es posible enO(nortepag+registropag){\displaystyle O({\frac {n}{p}}+\log p)}usando una suma de prefijo . Como ahora tenemos un nuevo conjunto de vértices y aristas, se debe reconstruir el arreglo de adyacencia, lo que se puede hacer usando Integersort enmi{\displaystyle E'}enO(metropag+registropag){\displaystyle O({\frac {m}{p}}+\log p)}tiempo.

Complejidad

Cada iteración ahora necesitaO(metropag+registronorte){\displaystyle O({\frac {m}{p}}+\log n)}tiempo y al igual que en el caso secuencial hayregistronorte{\displaystyle \log n}iteraciones, lo que resulta en un tiempo de ejecución total deO(registronorte(metropag+registronorte)){\displaystyle O(\log n({\frac {m}{p}}+\log n))}. SimetroΩ(pagregistro2pag){\displaystyle m\in \Omega (p\log ^{2}p)}La eficiencia del algoritmo está enΘ(1){\displaystyle \Theta (1)}y es relativamente eficiente. SimetroO(norte){\displaystyle m\in O(n)}Entonces es absolutamente eficiente.

Más algoritmos

Existen otros múltiples algoritmos paralelos que abordan el problema de encontrar un MST. Con un número lineal de procesadores es posible lograr esto enO(registronorte){\displaystyle O(\log n)}. [ 8 ] [ 9 ] Bader y Cong presentaron un algoritmo MST que era cinco veces más rápido en ocho núcleos que un algoritmo secuencial óptimo. [ 10 ]

Otro desafío es el modelo de memoria externa: existe un algoritmo propuesto por Dementiev et al. que afirma ser solo de dos a cinco veces más lento que un algoritmo que solo utiliza la memoria interna [ 11 ].

Referencias

  1. ^ Lijadoras; Dietzfelbinger; Martín; Mehlhorn; Kurt; Pedro (10 de junio de 2014). Algoritmos und Datenstrukturen Die Grundwerkzeuge . Springer Vieweg. ISBN 978-3-642-05472-3.
  2. Brodal, Gerth Stølting; Träff, Jesper Larsson; Zaroliagis, Christos D. (1998), "A Parallel Priority Queue with Constant Time Operations", Journal of Parallel and Distributed Computing , 49 (1): 4– 21, CiteSeerX 10.1.1.48.3272 , doi : 10.1006/jpdc.1998.1425 
  3. Osipov, Vitaly; Sanders, Peter; Singler, Johannes (2009), "El algoritmo del árbol de expansión mínima de Kruskal con filtro", Actas del Undécimo Taller sobre Ingeniería y Experimentos de Algoritmos (ALENEX). Sociedad de Matemáticas Industriales y Aplicadas : 52–61 , CiteSeerX 10.1.1.218.2574 
  4. Sanders, Peter. "Script de ingeniería de algoritmos" (PDF) . Página principal del KIT de ingeniería de algoritmos . Consultado el 25 de febrero de 2019 .
  5. Sanders, Peter. "Script de algoritmos paralelos" (PDF) . Página principal del KIT de algoritmos paralelos . Consultado el 25 de febrero de 2019 .
  6. Zadeh, Reza. "Algoritmos distribuidos y optimización" (PDF) . Algoritmos distribuidos y optimización. Página principal de la Universidad de Stanford . Consultado el 25 de febrero de 2019 .
  7. Chun, Sun; Condon, Anne (1996). «Implementación paralela del algoritmo del árbol de expansión mínima de Bouvka». Actas de la Conferencia Internacional sobre Procesamiento Paralelo . págs. 302–308 . doi : 10.1109/IPPS.1996.508073 . ISBN  0-8186-7255-2. S2CID 12710022 . 
  8. Chong, Ka Wong; Han, Yijie; Lam, Tak Wah (2001), "Hilos concurrentes y algoritmo óptimo de árboles de expansión mínima en paralelo", Journal of the Association for Computing Machinery , 48 (2): 297–323 , CiteSeerX 10.1.1.32.1554 , doi : 10.1145/375827.375847 , MR 1868718 , S2CID 1778676   
  9. Pettie, Seth; Ramachandran, Vijaya (2002), "Un algoritmo paralelo óptimo de tiempo y trabajo aleatorio para encontrar un bosque de expansión mínima" (PDF) , SIAM Journal on Computing , 31 (6): 1879–1895 , doi : 10.1137/S0097539700371065 , MR 1954882 
  10. Bader, David A. ; Cong, Guojing (2006), "Algoritmos rápidos de memoria compartida para calcular el bosque de expansión mínima de grafos dispersos", Journal of Parallel and Distributed Computing , 66 (11): 1366– 1378, doi : 10.1016/j.jpdc.2006.06.001
  11. Dementiev, Roman; Sanders, Peter; Schultes, Dominik; Sibeyn, Jop F. (2004), "Ingeniería de un algoritmo de árbol de expansión mínima con memoria externa", Actas del 18.º Congreso Mundial de Informática de la IFIP, 3.ª Conferencia Internacional TC1 sobre Ciencias de la Computación Teórica (TCS2004) (PDF) , págs. 195-208 , archivado del original (PDF) el 9 de agosto de 2011 , consultado el 24 de mayo de 2019. .