Обход определенных вершин графа с условиями

У меня есть неориентированный граф, похожий на приведенный ниже, мне нужно реализовать алгоритм обхода графа. Пример:
http://i.imgur.com/15L6m.png

Идея состоит в том, что каждая вершина — это город, а каждое ребро — дорога.
Вес ребра представляет собой время, необходимое для прохождения указанного ребра.
Условия следующие:

  1. Каждое ребро открыто для обхода в указанном временном окне: Time Open1, Time Open2, TimeClose1, Time Close2 — текущее время должно находиться в этих интервалах для прохождения ребра.
  2. Только некоторые вершины должны быть посещены. Вершины должны быть посещены по крайней мере один раз в указанном временном окне для каждой из них: Time Open1, Time Open2, TimeClose1, Time Close2 - текущее время должно быть в этих интервалах, чтобы вершина была помечена как посещенная.
  3. Начальной точкой всегда является вершина 0

Для моего примера у меня есть:
Вершины, которые необходимо посетить, и их временное окно (значения с -1 не учитываются):

Vertex To1  Tc1  To2  Tc2
  1    0    260  340  770
  4    0    240  -1   -1 
  5    170  450  -1   -1 

Ребра открыты в следующем временном окне (значения с -1 не учитываются):

Edge To1  Tc1  To2  Tc2
0-1  0    770  -1   -1 
0-4  0    210  230  770
0-5  0    260  -1   -1 
1-2  0    160  230  770
1-5  40   770  -1   -1 
2-4  80   500  -1   -1 
3-4  60   770  -1   -1 
3-5  0    770  -1   -1 

Итак, основная идея состоит в том, чтобы начать с вершины 0 и найти кратчайший путь к вершинам 1, 4 и 5 с учетом заданного времени.
Также, если, например, вы сделали 0-1, но не можете использовать 1-5, вы можете сделать 0-1-0-1-5.

Возможное решение, с которым я сейчас работаю, таково:
Начните с 0. Найдите ближайшую вершину для отметки за кратчайший период времени (я использую модифицированный алгоритм Дейкстры). Делайте это до тех пор, пока я не отмечу все необходимые вершины.
Проблема заключается в том, что я не думаю, что нахожу все возможности, потому что, как я уже сказал, вы также можете перемещаться, как комбинация 0-1-0-1-5 и в конце концов, вы можете получить более короткий маршрут.

Чтобы сделать это более ясным, я должен найти кратчайший путь, чтобы я начал с вершины 0, закончил одной целевой вершиной, в то время как я посетил все остальные целевые вершины хотя бы один раз, соблюдая условия, наложенные на ребра и целевые вершины.
Например:
Возможное решение 0 - 4 - 3 - 5 - 1 с общим временем 60+50+60+50=220
От 0 я также могу сразу перейти к 5, но, как указано в условиях, чтобы отметить вершину 5, у меня должно быть совокупное время между 170 и 450. Также, если я иду 0-4, я не могу использовать ребро 4-2, потому что оно открывается на 80, а мое совокупное время равно 60 , Обратите внимание, что я могу использовать 0-4-3, потому что 4-3 открывается на 60, а для выполнения 0-4 требуется время, равное 60.

Прежде всего ограничения заключаются в том, что я буду использовать не более 20 вершин и не более 50 ребер.

Решение 1:
0
1 4 5 0 2 5 0 2 3 0 1 3

Что я делаю, так это обхожу граф, посещая каждую соседнюю вершину, строя что-то похожее на дерево. Я перестаю расширять ветку, когда:
1. У меня слишком много дубликатов, например, у меня есть 0 1 0 4 0 1 0, поэтому я останавливаюсь, потому что у меня есть заданное количество повторяющихся значений 0, равное 4
2 . Я нашел дорогу, содержащую все вершины, которые нужно отметить
3. Я нашел дорогу, которая занимает больше времени, чем другая полная дорога
4. Я не могу создать еще один узел, потому что ребро закрыто

Решение 2.

Применяю пример @Boris Strandjev, но у меня есть некоторые проблемы:

Я должен посетить узлы 1,4 и 5 хотя бы один раз в их интервале, посещения вне интервалов разрешены, но не отмечены. Для вершины у меня есть {(‹ id1, id2id3id4>, время)}, где id1 — это ide текущей вершины, а id2-4 представляют логические значения для 1,4,5, если были посещены в указанные интервалы, время — текущее время в пути

Step1: 
{<0, 000>, 0} I can visit - {<1, 100>, 60} - chosen first lowest val
                          - {<4, 010>, 60}
                          - {<5, 000>, 60}
Step2:
{<1, 100>, 60} - {<0, 100>, 120} 
               - {<2, 100>, 110}   - chosen 
               - {<5, 100>, 110}    
Step3:
{<2, 100>, 110} - {<1, 100>, 160} - if I choose 1 again I will have a just go into a loop 
                - {<4, 110>, 170}   
Step4:
{<4, 110>, 170} - {<0, 110>, 230}
                - {<2, 110>, 230} 
                - {<3, 110>, 220}   - chosen

Step5:
{<3, 110>, 220} - {<4, 110>, 270} - again possible loop
                - {<5, 111>, 280} 
Step6:
{<5, 111>, 280} - I stop Path: 0-1-2-4-3-5 cost 280

Изменить:

В итоге я использовал комбинацию двух решений выше. Кажется, все работает нормально.


person hDan    schedule 15.09.2012    source источник
comment
Вы ищете кратчайшие пути от вершины 0 до каждой из вершин назначения или одиночный тур, который начинается с 0 и посещает каждую из вершин назначения? Последняя задача связана с задачей коммивояжера и является NP-трудной.   -  person krjampani    schedule 15.09.2012
comment
Вместо того, чтобы выполнять эти «обратные пути» (0-1-0-1-5), можно ли также ждать на каком-то узле, пока требуемое ребро не станет доступным? В этом случае вы можете искать путь, игнорируя временные ограничения, а затем выполнять некоторую «постобработку», чтобы добавить время ожидания к пути.   -  person tobias_k    schedule 16.09.2012
comment
Нет, вы не можете ждать, пока ребро или вершина станут доступны, вы должны найти лучшее решение со всеми условиями, которые у вас есть. Время движется только тогда, когда вы пересекаете ребро.   -  person hDan    schedule 16.09.2012
comment
@mUncescu: То, что вы делаете, не совсем Дейкстра, это больше похоже на поиск луча. В Дейкстре куча увеличивающих путей расширяется на каждом шагу, но это не означает, что вы отбрасываете старые, неиспользуемые пути. Таким образом, шаг 3 для вас должен был быть {<4, 010>, 60} или {<5, 000>, 60}, потому что он занимает меньше времени, чем {<2, 100>, 110}. Всего после шага 2 у вас есть 5 аугментирующих путей на выбор: {<4, 010>, 60}, {<5, 000>, 60}, {<0, 100>, 120} , {<2, 100>, 110}, {<5, 100>, 110}. Извините, может быть, мой пример немного сбивает с толку, в конце концов...   -  person Boris Strandjev    schedule 23.09.2012


Ответы (1)


Я не видел строгого ограничения на количество вершин или ребер, которые у вас есть в графе, поэтому, пожалуйста, извините меня, если мое решение не сработает для вас. Дайте более строгие ограничения, если вам нужно какое-либо улучшение.

Одним из возможных решений является расширение определения node. Вместо того, чтобы рассматривать только город как узел на графике, добавьте еще несколько атрибутов. Держите определение края неявным, генерируя исходящие края на ходу, чтобы сэкономить память.

Смотрите сейчас:
Вы определяете узел комбинацией трех вещей: - город, к которому относится узел. - время посещения - битовая карта посещенных целевых узлов (чтобы вы могли сказать, посетили ли вы уже все целевые узлы).

Теперь ребра немного сложнее — они ведут вас из города в город, но каждое ребро также меняет время для соседнего узла. Также продолжайте обновлять растровое изображение целевого узла с каждым шагом.

Вот пример:
Вы начинаете с <city:=0, time:=0, bitmap:= (0 - true, 1...k - false)>
Если вы пройдете ребро 0-4, вы окажетесь в узле <city:=4, time:=60, bitmap:= ({0,4} - true, {1...k} / {4} - false)>

Продолжайте двигаться таким образом между узлами, используя алгоритм Дейкстры, и вы найдете свое решение (по мере того, как вы расширяете определение узла, теперь будут учитываться даже окольные пути). Вы нашли свое решение всякий раз, когда оказывались в узле, в растровом изображении которого установлены все биты.

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

ИЗМЕНИТЬ

Вот расширенный пример, который вы просили:

Представьте, что у вас есть такой ввод (я использую ваши обозначения):

 Vertex To1  Tc1  To2  Tc2
   1    0    40   80  120
   2    40   80   -1   -1
   3    0   400   -1   -1 
   4    30   80   120 190

 Edge To1  Tc1  Weight
 1-2   0    770  50
 1-4  30     70  30
 1-3   0    400  30
 3-4 100    200  50
 2-4   0    400  20

Вершины представлю в следующем виде: <1,1100> значение: текущая вершина 1, а вторая: первая и вторая вершины посещаются уже в найденном пути. Расстоянием до каждой вершины будет минимальное время, необходимое для достижения этой вершины.

Как вы знаете, в процессе алгоритма Дейкстры вы рассматриваете увеличивающие пути (имеются в виду лучшие пути, которые вы нашли к каждой вершине фронта уже достигнутых вершин). Я буду обозначать каждый увеличивающий путь следующим образом: (<1,1100>, 400) означает, что на данный момент лучшее время, за которое вы можете достичь вершины <1,1100>, равно 400.

Вы начинаете алгоритм с набором увеличивающих путей {(<1, 1000>, 0)} и расстояний до всех вершин infinity. Теперь выполните следующие шаги.

Первая вершина достигается наилучшим увеличивающим путем. От него возможные ребра 1-2 и 1-3 (1-4 недоступен на 0-й секунде. они запускают еще два увеличивающих пути: {(<2, 1100>, 50), (<3, 1010>, 30)} расстояние до <1, 1000> меняется на 0.

На следующем шаге рассматривается лучший увеличивающий путь (<3, 1010>, 30). Однако для добавления увеличивающего пути можно использовать ни одно из исходящих ребер: 1-3 нельзя использовать, поскольку вершину 1 нельзя посетить в момент времени 60. Ребро 3-4 также нельзя использовать из-за временного интервала. Таким образом, увеличивающие пути теперь: {(<2, 1100>, 50)}.

Следующий шаг: (<2, 1100>, 50) и новые пути увеличения: {(<1, 1100>, 100), (<4, 1101>, 70)}.

Следующий шаг: (<4, 1101>, 70), но он также не добавляет новый путь: вершину 2 нельзя посетить в момент времени 90, а 3-4 больше нельзя использовать. Таким образом, увеличивающих путей {(<1, 1100>, 100)}.

Следующий шаг: (<1, 1100>, 100), который меняет увеличивающие пути на: {(<3, 1110>, 130)}.

Следующий шаг: (<3, 1110>, 130), который меняет увеличивающие пути на: {(<4, 1111>, 180)}.

Следующий шаг: (<4, 1111>, 180), который является последним шагом — мы находимся в состоянии, в котором посещаются все целевые вершины. Итак, итог: посетить все вершины в ограничениях можно за 180 секунд.

Я надеюсь, что этот пример поможет вам понять мою идею. Возможно, вам придется записать все соображения на листе бумаги, чтобы убедиться, что я не ошибаюсь с увеличивающими путями.

person Boris Strandjev    schedule 16.09.2012
comment
@mUncescu: в моем решении вы переопределяете узел, но после этого вы выполняете обычную Дейкстру вместе с реконструкцией его пути. вам никогда не нужно будет повторно посещать узел (как в обычном Дейкстре). Узел в моем случае не просто представляет вершину, а скорее включает в себя свойства пути, который вы использовали, чтобы добраться до этой вершины (таким образом, растровое изображение и время). Вот почему растровое изображение является свойством каждого узла: потому что в глобальном масштабе у вас много путей, и я хочу локализовать только один в каждом узле. - person Boris Strandjev; 17.09.2012
comment
@mUncescu прочитайте сообщение выше, если вам все еще нужна дополнительная помощь - я постараюсь ее предоставить. - person Boris Strandjev; 17.09.2012
comment
Для узла вы сохраняете только те, которые вам нужно посетить, так где же вы указываете свой точный путь? Также в ситуации, когда лучший путь содержит 0-4-2-4, минимальное расстояние для 4 отличается, как и время посещения, и когда я выбираю лучший узел в Дейксте, мой выбор основан на минимальном расстоянии, но в этом случае у меня есть несколько лучших расстояний? Можете ли вы привести более развернутый пример. - person hDan; 17.09.2012
comment
В основном проблема заключается в том, как мне выбрать следующий узел для посещения, потому что, если вы находитесь в узле 4, у вас есть ‹city:=4, time:=60, bitmap:= ({0,4} - true, {1.. .k} / {4} - false)› затем я перехожу к 2, у вас есть ‹city:=2, time:=60, bitmap:= ({0,4} - true, {1...k} / { 4} - false)› тогда, если мне нужно вернуться к 4, что мне делать? создать еще один узел? потому что я меняю время посещения узла 4 - person hDan; 18.09.2012
comment
@mUncescu: Да, извините, вчера у меня не было времени привести вам пример. Как-нибудь сегодня постараюсь добавить. - person Boris Strandjev; 18.09.2012
comment
Я пробовал другую реализацию. Первую с Дейкстрой я до сих пор не понимаю - person hDan; 19.09.2012
comment
@mUncescu: я добавил довольно расширенный пример. Надеюсь, это поможет вам понять мою мысль. - person Boris Strandjev; 21.09.2012