Как я могу использовать алгоритм звезды, чтобы найти первые 100 кратчайших путей?

Как я могу использовать алгоритм звезды, чтобы найти первые 100 кратчайших путей?


person user1815763    schedule 30.12.2012    source источник
comment
Для чего вы надеетесь использовать эти пути? N-й кратчайший путь обычно будет кратчайшим путем с объездом в какой-то точке и не будет полезен ни для каких практических целей. Может быть какой-то разумный альтернативный путь, но трудная проблема заключается в том, как определить, выглядит ли путь разумным для человека.   -  person Jan Hudec    schedule 02.01.2013
comment
@Jan Hudec: В своей программе я собираюсь реализовать систему поиска рейсов. Стоимость ребер - это продолжительность полета. Я собираюсь найти решения с ценой полета. Но самый быстрый путь может быть недешевым. соответственно.   -  person user1815763    schedule 02.01.2013
comment
100 самых быстрых рейсов дадут вам кучу мусора и, возможно, не дадут вам никакого дешевого пути, потому что нет абсолютно никакого способа узнать, как далеко находится дешевый путь. Вместо этого вы либо хотите найти все минимальные пути на основе частичного упорядочения (созданного путем объединения различных критериев), либо запустить алгоритм несколько раз с разными целевыми функциями. Или применяйте эвристические ограничения по глубине и расстоянию и выполняйте исчерпывающий поиск; Я подозреваю, что это было бы целесообразно для полетов, но не для, скажем, автобусных сообщений.   -  person Jan Hudec    schedule 02.01.2013
comment
В любом случае, это совсем другой вопрос, поэтому более подробное обсуждение после того, как вы сформулируете новый вопрос - либо как искать в расписании с несколькими критериями (дешевле, короче, быстрее и т. д.) и найти все пути, которые минимальны в любом из них, либо как искать в расписании рейсов, когда требуется много альтернативных результатов. Или оба, если вам интересно.   -  person Jan Hudec    schedule 02.01.2013
comment
Если вы реализуете это для системы поиска рейсов, возможно, вы захотите изучить альтернативные маршруты: algo2 .iti.kit.edu/2073.php, algo2.iti.kit .edu/english/1805.php и т. д.   -  person Karussell    schedule 05.01.2013


Ответы (4)


Задача нахождения k-го кратчайшего пути — это NP-Hard, поэтому любая модификация A -Звезда, которая будет делать то, что вам нужно, будет экспоненциальной по размеру ввода.

Доказательство:
(Примечание: я покажу на простых путях)
Предположим, что у вас есть полиномиальный алгоритм, который выполняется за полиномиальное время и возвращает длину kсамого короткого пути. путь пусть алгоритм будет A(G,k)

Максимальное количество путей равно n!, и, применяя бинарный поиск в диапазоне [1,n!], чтобы найти кратчайший путь длиной n, вам потребуется O(log(n!)) = O(nlogn) вызовов A.
Если вы нашли путь длиной n - это гамильтоновский путь.
Повторяя процесс для каждого источника и цели на графике (O(n^2) из них), вы можете решить Задача Гамильтона о путях полиномиально, если такое A существует.
КЭД

Из этого мы можем сделать вывод, что если P=NP (а это очень маловероятно согласно большинству CS исследователи), задача не может быть решена полиномиально.

В качестве альтернативы можно использовать вариант поиска по единой цене без сохранения набора visited/closed. Возможно, вы также сможете изменить A*, отключив закрытые узлы и выдав/сгенерировав найденные решения вместо того, чтобы возвращать их и заканчивать, но я не могу придумать способ доказать это для A. * сейчас.

person amit    schedule 30.12.2012
comment
Не могли бы вы объяснить мне, как найти первые 100 кратчайших путей, используя A*? Я реализовал A*, чтобы найти кратчайший путь. A использовал допустимую эвристику. Теперь я хочу найти первые 100 кратчайших путей. - person user1815763; 02.01.2013
comment
Не могли бы вы объяснить мне, как найти первые 100 кратчайших путей, используя A*? Я реализовал A*, чтобы найти кратчайший путь. Также используется допустимая эвристика. Отключение списка закрытых узлов позволит нам повторно использовать ранее посещенные узлы. Но теперь я хочу найти первые 100 кратчайших путей. Пожалуйста, объясните, как это сделать. - person user1815763; 02.01.2013
comment
@user1815763, Вам нужно будет запихнуть в приоритетную очередь все пути (source->v1->v2->..->vn) (и его оценку, конечно) и на каждом шаге вставлять все следующие доступные пути, игнорируя которые вершину, которую вы уже посетили или нет (посетите все). Всякий раз, когда вы выталкиваете из очереди какой-либо элемент, который является пунктом назначения, вы находите путь. Я считаю (хотя не могу доказать на данный момент), что k-й раз, когда вы вытаскиваете пункт назначения из очереди, представляет k-й кратчайший путь. Обратите внимание, что это решение является экспоненциальным, потому что вы не ограничиваете себя и можете повторно посещать узлы много раз. - person amit; 02.01.2013
comment
@KillianDS: Нет, точно, отключая набор закрытых узлов и повторно посещая закрытые узлы, вы делаете алгоритм экспоненциальным - и это может привести к решению проблемы без доказательства P = NP (хотя я не могу доказать в данный момент, что это произойдет , но моя интуиция говорит, что будет). - person amit; 02.01.2013

Помимо того, что эта задача NP-сложная, с A* или dijkstra это невозможно сделать без серьезных модификаций. Вот несколько основных причин:

Во-первых, алгоритм сохраняет на каждом шаге только лучший на данный момент путь. Рассмотрим следующий график:

  A
 / \
S   C-E
 \ /
  B

Примите расстояния d(S,A)=1, d(S,B)=2, d(A,C)=d(B,C)=d(C,E)=10.

При посещении C вы выберете путь через A, но нигде не сохраните путь через B. Так что вам придется сохранить эту информацию.

Но, во-вторых, вы даже не рассматриваете все возможные пути, предположим следующий график:

S------A--E
 \    /
  B--C

Предположим, расстояния d(S,A)=1, d(S,B)=2, d(B,C)=1, d(A,E)=3. Ваш порядок посещения будет {S,A,B,C,E}. Поэтому при посещении A вы даже не можете сохранить объезд через B и C, потому что не знаете об этом. Вам нужно будет добавить что-то вроде «потенциального пути через C» для каждого непосещенного соседа.

В-третьих, вам придется включать циклы и тупики , потому что да, вполне возможно, что путь с петлей окажется одним из ваших 100 кратчайших путей. Вы, конечно, могли бы ограничить это, но это общая возможность. Рассмотрим, например, такие графики:

S-A--D--E
  |  |
  B--C

Понятно, что вы можете легко начать цикл здесь, если вы не запретите «возврат» (например, запретите D->A, если A->D уже находится в пути). На самом деле это даже проблема без явного графического цикла, потому что в общем случае вы всегда можете поиграть в пинг-понг между двумя соседями (путь A-B-A-B-A-...).

А сейчас я, наверное, даже забыл некоторые вопросы.

Обратите внимание, что большинство из этих вещей также очень затрудняют разработку общего алгоритма, особенно последней части, потому что с помощью циклов трудно ограничить количество возможных путей («бесконечный цикл»).

person KillianDS    schedule 02.01.2013

Это не жесткий алгоритм NP, а приведенная ниже ссылка представляет собой алгоритм Йена для вычисления K-кратчайших путей в графе за полиномиальное время. ссылка на алгоритм Йена

person ghedas    schedule 20.02.2017
comment
Алгоритм Йена на самом деле работает за псевдополиномиальное время, поскольку время выполнения зависит от числового значения k. Хотя для любого фиксированного k - здесь k = 100 - это действительно будет выполняться за полиномиальное время. - person templatetypedef; 30.06.2020

Используйте поиск *, когда пункт назначения k-й раз помещается в очередь. Это будет k-й кратчайший путь.

person LazyChild    schedule 30.12.2012
comment
Разве это не должен быть k-й раз, когда он выскочил из очереди, а не был отправлен? - person user541686; 30.12.2012
comment
Я не думаю, что это утверждение верно. Ты можешь доказать это? - person amit; 30.12.2012
comment
@Mehrdad Когда пункт назначения помещается в очередь впервые, значение должно быть кратчайшим путем. Это правильно? - person LazyChild; 30.12.2012
comment
@amit Правильность a * зависит от эвристической функции h. функция h должна быть допустимой эвристикой. - person LazyChild; 30.12.2012
comment
@LazyChild: Для кратчайшего пути - действительно. Предположим, у вас есть эвристика h(v) = 0 (которая всегда допустима и в основном означает, что ваша проблема не информирована. Не могли бы вы доказать, что алгоритм работает для k-го кратчайшего пути? (Я сомневаюсь в этом, так как я только что показал проблему для общего случая k NP-Hard , должны быть и другие модификации типа отключения набора closed) - person amit; 30.12.2012
comment
@амит Да. Я должен быть более конкретным. Мы должны использовать расстояние d от пункта назначения в качестве функции h. И да, отключение набора closed необходимо. Таким образом, один узел может встречаться в очереди много раз. - person LazyChild; 30.12.2012
comment
@ LazyChild, не могли бы вы объяснить, как найти первые k кратчайших путей (не k-й), используя A *? - person user1815763; 02.01.2013
comment
Это неправильно. Алгоритмы dijkstra (и, соответственно, A*) разрушительны, для любого узла вы рассматриваете только лучший путь на данный момент. На самом деле вам придется рассматривать любые возможные пути, даже пути через узлы, которые еще не были посещены, потому что любой небольшой обход может привести ко второму лучшему пути. - person KillianDS; 02.01.2013
comment
Рассмотрим, например, график с узлами {S,A,B,C,E}, связностью S-A, S-B, A-E, B-C, C-A и всеми расстояниями, равными 1. Вы никогда не будете рассматривать путь S-B-C-A-E. Почему? Ваш порядок посещений будет примерно таким: S,A,B,C,E. A и B могут поменяться местами, так же как и C и E, из-за равного расстояния, но это не имеет значения. Вы можете видеть, что при посещении A вы даже не знаете об объезде через C, потому что C никто не посещал. - person KillianDS; 02.01.2013