11 votos

El camino más corto entre un punto y cada uno de los otros puntos

Estoy tratando de averiguar cómo encontrar todos los caminos más cortos desde cada punto y cada nodo de una línea a los otros puntos y nodos de líneas de este mapa.

enter image description here

He intentado hacerlo en Python usando NetworkX. Para probarlo, recorté el mapa y traté de buscar sólo los caminos más cortos de cada nodo de una línea a todos los demás nodos de otras líneas de este mapa: enter image description here

Con esa red de carreteras, tengo 214 nodos (lo que debería resultar en 214x214 caminos más cortos, creo). He intentado hacer el gráfico de la red de carreteras con este código:

#Create the network graph
G = nx.DiGraph()
for k,v in idict.items():
    G.add_edge(v[0],v[1], weight = v[2]) # v[0] = first (x,y) of a linestring, v[1] = last (x,y) of a linestring, v[2] = distance
    G.add_edge(v[1],v[0], weight = v[2]) #  return path

len(G.edges())

pos = nx.spring_layout(G)
nx.draw_networkx_nodes(G, pos = pos, node_size=20,arrows = True)
nx.draw_networkx_edges(G, pos = pos)
plt.show()

Y el resultado muestra:

enter image description here

También he tratado de aplicar la función warshall de Networkx Floyd para calcular todos los caminos más cortos de cada punto a otro punto, pero algunos de los resultados regresan al infinito (ya que creo que dice que no se encuentra ningún camino entre los puntos, mientras que en realidad todos los caminos están conectados). En total, sólo vuelve a unos 1720 caminos más cortos

¿Cómo debo proceder para tener el camino más corto de cada nodo a todos los demás nodos del mapa?

4voto

Steve Puntos 8

NetworkX all_shortest_paths o single_source_dijkstra

Hay que calcular todos los caminos más cortos desde el origen y luego resumir los pesos de las aristas de cada camino. También estoy absolutamente seguro de que hay una manera mucho más simple de hacer esto porque el algoritmo Dejkstra calcula todos los caminos en el gráfico para devolver uno solo. Así que no es necesario calcular de nuevo.

0 votos

No lo entiendo bien, ¿tengo que hacerlo manualmente con el método? También he probado con esto networkx.github.io/documentation/stable/reference/algorithms/ Pero aparentemente, sólo devuelve algunos caminos más cortos de cada punto, y también vi el número infinito como resultado.

0 votos

Estás utilizando el método del gráfico no ponderado. Es un error, porque el resultado será "el paso con menos cruces". Prueba esto: networkx.github.io/documentation/stable/reference/algorithms/

0 votos

Gracias por la referencia. Estoy tratando de hacer eso y ahora tengo más caminos más cortos, pero todavía no todos los caminos más cortos que quiero (por ejemplo, sólo tengo 8000 caminos en lugar de 14000 y pico caminos para 120 nodos que tengo). ¿Sabéis por qué?

4voto

Jordan Stewart Puntos 524

Desgraciadamente, la insinuación de Ahlfors es muy engañosa, y de hecho hay una forma más sencilla de resolver este problema, sobre todo porque a estas alturas del libro Ahlfors ha demostrado los teoremas de Mittag-Leffler y Weierstrass.

Dejemos que gg sea una función entera con ceros simples en anan . Recordemos que el Teorema de Mittag-Leffler no sólo afirma la existencia de funciones meromórficas con polos en anan pero nos permite controlar la parte singular de la función en cada anan . Así que dejemos hh sea una función meromorfa sobre C con postes simples en cada an con la parte de singuar cn/(zan) . Entonces f:=gh tiene las propiedades deseadas.

4voto

RETAS Puntos 129

Primero hay que definir qué se entiende por camino más corto. Si no ponderas tu grafo (G), el camino más corto es simplemente el camino que conecta los nodos que pasa por el menor número de otros nodos. Si quieres incorporar la longitud real de las líneas, necesitas crear un grafo ponderado:

# Compute weights
weights = lengths of each link in idict.items # square root of sum of squares or whatever

#Create the network graph
G = nx.Graph()
for k,v, wt in zip(idict.items(), weights):
    G.add_edge(v[0],v[1], weight = wt) 

Tenga en cuenta que, dado que su gráfico aparentemente no tiene direccionalidad, no debería utilizar un DiGraph. Un gráfico normal debería ser suficiente. Ahora G contiene enlaces ponderados, y puedes utilizar los algoritmos dijkstra para encontrar los caminos más cortos.

Debería consultar esta página para conocer sus opciones: https://networkx.github.io/documentation/stable/reference/algorithms/shortest_paths.html Desplácese hasta "Algoritmos del camino más corto para grafos pesados".

Por su pregunta, parece que querrá uno de los all_pairs_xxx -- La elección depende del resultado que se quiera obtener. Si quiere los nodos reales a lo largo de cada camino más corto, utilice all_pairs_dijkstra_path . Si sólo necesita las longitudes, utilice all_pairs_dijkstra_path_length . Si necesita ambos, utilice all_pairs_dijkstra .

Tenga en cuenta que todas estas funciones devuelven un iterador: los caminos más cortos no se calculan realmente hasta que se descompone el iterador. Esto significa que estas funciones se calcularán muy rápidamente, pero el verdadero trabajo pesado ocurre después de desempaquetarlas. Puedes descomprimirlas de forma sencilla:

blah = nx.all_pairs_dijkstra_path(G)
shortest_paths = list(blah)

shortest_paths debe tener la misma longitud que el número de nodos de G.

Tenga en cuenta que hay cierta redundancia en este enfoque, y no estoy seguro de si networkX aprovecha el hecho de que el camino más corto de n0->n1 es el mismo que n1->n0 para un grafo no dirigido.

0 votos

¡Gracias por la respuesta! Sí, he puesto las distancias de cada arco como peso (tal y como has hecho tú). Mi objetivo es calcular el camino más corto desde cada nodo a todos los demás nodos, dado que, por ejemplo, un coche irá de un punto a otro y volverá por la misma ruta. Entonces, en este caso, creo que aplicar pesos como símbolo de dirección es bueno? ¿O cómo debo dar las direcciones?

0 votos

Ya he probado con el all_pairs_dijkstra_path y creo que es el que quiero utilizar. Pero actualmente, sigo obteniendo 55000 caminos más cortos en lugar de 63756 caminos más cortos (tengo 253 nodos así que 253x(253-1))

1 votos

@botibo Re: direcciones, sigo sin ver la necesidad de la direccionalidad. Si un coche va de n1->n2, y luego vuelve por n2->n1, la longitud total del camino es simplemente la longitud de n1->n2 multiplicada por 2 y ya conoces los nodos a lo largo del camino, así que puedes simplemente invertirlos. En cuanto al número incorrecto de nodos, ¿es posible que tengas algunos nodos encima de otros, es decir, con las mismas coordenadas? La raíz cuadrada de 55.000 indica que hay aproximadamente 234 nodos únicos.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X