Estimados compañeros programadores,
Estamos desarrollando software que simula el tráfico vehicular. Parte del proceso llamado "asignación" se refiere a la asignación de vehículos a sus rutas y tiene que usar algún tipo de algoritmo de búsqueda de ruta más corta.
Tradicionalmente, las personas hacen esto con Dijkstra, y cierta literatura científica parece indicar que A * y otras alternativas no ofrecen ninguna mejora significativa, tal vez debido a la naturaleza del gráfico.
Por lo tanto, también estamos usando Dijkstra. Surgió un pequeño problema porque, si trata los enlaces de tráfico (tramos de carreteras entre intersecciones) como bordes e intersecciones como nodos, no puede obtener un gráfico unidireccional clásico: al acercarse a una intersección, el lugar donde puede girar con frecuencia depende de de dónde vienes, mientras que en un gráfico tradicional puedes tomar cualquier ventaja de un nodo.
Resolvimos este problema con bastante facilidad al representar un par de enlace-intersección (llámelo "listón") como un nodo. Dado que necesitaría atravesar un enlace para llegar a cualquier "listón" o punto de elección subsiguiente, un borde se definiría como este recorrido y obtendrá un gráfico típico.
Los resultados se almacenan en una tabla simple, N x N, donde N es el número de "listones".
Aquí está el inconveniente (¿inevitable?). Si una red típica para nuestra simulación puede tener, digamos, 2000 intersecciones, tendrá alrededor de 6000 enlaces, es decir, N = 3V. Obviamente, si se cuenta en términos de intersecciones (V), ahora estamos hasta O (log (3V) * (3V + E)).
Podría argumentar que 3 (o 9) es un factor constante, pero desde el punto de vista práctico, ralentiza bastante las cosas y aumenta el espacio de almacenamiento a 3V x 3V.
¿Alguien tiene alguna idea de cómo podemos reestructurar esto para mejorar el rendimiento? ¿No es necesariamente un algoritmo alternativo, tal vez remodelar las estructuras de datos para que se ajusten a un gráfico de alguna otra manera?
fuente
Respuestas:
Dijkstra encuentra el camino más corto entre un nodo dado y todos los demás nodos, por lo que espero que sea más costoso que A *. Sin embargo, ¿parece que está tratando de calcular previamente el costo y la ruta de un nodo a otro? Entonces Dijkstra es el camino a seguir.
En cuanto a una representación más simple, me vienen a la mente algunas cosas:
En muchas intersecciones, puede venir y salir de la forma que desee. Es solo un subconjunto que tiene restricciones como "no girar a la izquierda". Por lo tanto, podría usar los "listones" solo para intersecciones donde realmente los necesita. Eso debería reducir en gran medida el tamaño allí mismo.
Puede hacer esto automáticamente buscando "listones equivalentes" y combinándolos. Dos listones son equivalentes si todos los enlaces que salen son iguales. Por ejemplo, si "Intersección X viene del Oeste" e "Intersección X viene del Sur", ambas conducen al mismo conjunto de otros nodos, con el mismo costo, entonces simplemente combínelos en un solo nodo.
¿Está seguro de que necesita / desea calcular previamente el mejor camino, en lugar de calcularlo en línea? Los videojuegos suelen calcular estas cosas en línea.
Además, ¿cómo estás representando los caminos? En su matriz, solo necesita representar el primer enlace en la ruta. Por ejemplo, para ir de la casa de Bob al trabajo de Bob, solo necesita conocer el primer enlace, ya que cuando lleguen allí, ahora puede buscar en su matriz cómo llegar desde el primer enlace al trabajo de Bob, lo que le dará el segundo enlace, etc.
fuente
Tienes un gráfico grande y lo hiciste aún más grande. Martinc C. Martin aconsejó usar tornos solo cuando sea necesario, por lo que no entraré en esto.
Una de las cosas que podrían ayudarlo es transformar su gráfico en gráficos más pequeños.
La primera simplificación que me ayudó mucho (trabajé con redes de carreteras de estados europeos) fue "eliminar" nodos con digree 1 y 2 de forma recursiva. De esta manera, no tiene caminos sin salida, y las intersecciones en T (originalmente grado 3) se convierten en grado 2 y eso no es interesante, si no está siguiendo ese nodo o nodo en ese cull de sac eliminado.
Después de eso, puede intentar dividir su gráfico en partes que tengan una gran cantidad de nodos internos y bordes, pero que tengan una conexión mínima con otras partes. Para encontrarlos, utilicé un corte mínimo donde el sumidero y la fuente estaban tan lejos uno del otro (en los bordes) uno del otro y los bordes cercanos a ellos tenían una gran capacidad y los bordes en algún punto intermedio eran pequeños.
fuente