Коммивояжер - улучшение 2-Opt

Итак, я искал объяснение улучшения с двумя вариантами решения проблемы коммивояжера, и я понял его суть, но я не понимаю одной вещи.

Я понимаю, что ЕСЛИ два края сгенерированного пути пересекаются друг с другом, я могу просто переключить две точки, и они больше не будут пересекаться. ОДНАКО - я не понимаю, как я могу определить, пересекаются ли два ребра.

Чтобы прояснить мой вопрос, вот что я сделал до сих пор: (я делал это на java)

  1. У меня есть объект под названием Point, который представляет город с координатами x и y.
  2. У меня есть PointSet, в котором есть набор Points, содержащихся в List.
  3. У меня есть метод для PointSet, называемый computeByNN(), который довольно быстро упорядочивает PointSet с помощью алгоритма ближайшего соседа.

Итак, теперь у меня есть отсортированный PointSet (не оптимальный, но все же короткий), и я хочу сделать для него 2 варианта. Однако я не знаю, с чего начать. Должен ли я проверять каждый сегмент линии, чтобы увидеть, пересекаются ли они, и если да, то поменять местами две точки? Я чувствую, что это противоречит цели эвристики и становится своего рода решением грубой силы. Есть ли эффективный способ определить, пересекаются ли два сегмента маршрута?

Я аплодирую, если мой вопрос не ясен. Попробую отредактировать, чтобы было понятнее, если кому-нибудь понадобится.


person u3l    schedule 06.09.2013    source источник
comment
Проверка каждого края - только O(n²). Совершенно разумное время работы при аппроксимации NP-полной задачи (которая, очевидно, не имеет известного точного решения за полиномиальное время).   -  person Paul    schedule 06.09.2013


Ответы (1)


Если хотите, вы можете создать справочную таблицу для обнаружения пересеченных краев. Для n = 1000 порядок 10 ^ 12 записей явно слишком экстравагантен. Однако вас, вероятно, больше всего беспокоят более короткие края? Предположим, вы хотели включить ребра примерно до √n ближайших соседей для каждого узла. Тогда вы находитесь только в области мегабайт пространства и в любом случае предварительной обработки O (n ^ 2). Отсюда эвристика, удачи!

Также будет упомянуто, что это можно сделать на лету.

person clwhisk    schedule 06.09.2013
comment
В идеале я бы хотел исправить все пересекающиеся края (даже длинные). Если вы видели решатель Concorde TSP, он может найти ВСЕ пересекающиеся ребра и заменить их. Я не понимаю, как это происходит так быстро. Тем не менее, я попробую сделать это по-вашему, проверив только корневых (n) соседей, и посмотрю, как это пойдет. И что вы имеете в виду, когда говорите, что это можно делать "на лету"? (Я старшеклассник, действительно новичок во всем этом, так что простите меня за глупые вопросы). - person u3l; 07.09.2013
comment
Под «на лету» я имею в виду начало с таблицы ввода, и если пара ребер действительно встречается в вашем графе, только тогда запоминайте, пересекаются они или нет. Извините, я не очень хорошо знаю TSP. Это стоит делать только в том случае, если вы ожидали снова и снова тестировать одни и те же пары. Поскольку не существует очевидного быстрого способа реализовать √n часть моей идеи, я предлагаю вам сосредоточиться на том, как проверять скрещенные края. Например, если наивысшее значение y края A меньше самого низкого значения края B, вам не нужно выполнять никаких других проверок. - person clwhisk; 07.09.2013
comment
Можно уменьшить временную сложность путем вычисления сегментов линии тени, которые покрывает каждый край в измерениях x и y. Тогда, вероятно, есть алгоритм, чтобы найти те, которые пересекаются под O (n ^ 2). Затем вы проверяете пересечение только тех ребер, которые могут пересекаться. - person clwhisk; 07.09.2013
comment
Хорошо, теперь я понимаю, о чем вы говорите, и обозначу ваш ответ как принятый, хотя я постараюсь найти лучший способ сделать это. Если что-то найду, опубликую ответ на свой вопрос. Спасибо за помощь! Это немного сбивает с толку ... - person u3l; 07.09.2013
comment
Имеет ли это смысл? Для сортировки конечных точек потребуется O (n log n). Затем вы проходите через конечные точки слева направо (O (n)) и поддерживаете список (O (n log n)) ребер, из которых вы видели ровно одну конечную точку до сих пор. Когда пришло время удалить ребро из этого списка, оно может пересечь только те ребра в списке. И повторяем, это каждая координата x, y ... - person clwhisk; 07.09.2013