Решение простой TSP с использованием Z3

Я новичок в решателях SMT. Я хотел бы знать, как я могу закодировать простую задачу TSP с 4/6 узлами? Я не понимаю, как установить свои ограничения с помощью Z3pay APA. Любой намек или помощь будут высоко оценены.


person user1770051    schedule 22.05.2013    source источник
comment
Вы можете получить больше ответов, если опубликуете то, что уже пробовали. Если проблема в API Z3py, пытались ли вы закодировать его с использованием стандарта SMTLib2? Или используя кодировку псевдокода?   -  person Malte Schwerhoff    schedule 23.05.2013
comment
Привет, На самом деле я запутался, как я могу кодировать проблему оптимизации в Z3? Я думаю, что для решения задач TSP лучше всего использовать псевдобулевы решатели !! Но Z3 не является псевдобулевым решателем, верно? Не могли бы вы предложить мне какую-либо статью или документ, в котором реализовано псевдологическое кодирование проблемы TSP? Я ценю ваш совет .. спасибо   -  person user1770051    schedule 10.09.2013


Ответы (2)


Вы можете сформулировать свою проблему TSP как проблему ILP. Теперь вопрос заключается в том, как кодировать TSP как ILP. Есть два хорошо известных ответа: Миллер-Такер. –Землин и Данциг – Фулкерсон – Джонсон.

Основная идея такова: допустим, у нас есть n городов. Обозначим через d_ij расстояние между городами i и j, а через x_{ij} обозначим логическое значение (0 или 1) независимо от того, содержит ли TSP ребро от i до j. Тогда поиск наименьшего тура означает

minimize sum_{i,j} x_{ij} d_{ij}

такие, что x_{ij} описывают цикл. С этими двумя условиями мы получаем один или несколько циклов:

sum_{j} x_{ij} = 1 for all i              exactly one outgoing edge per city
sum_{i} x_{ij} = 1 for all j              exactly one ingoing edge per city

Теперь нам нужно исключить случай, когда решения состоят из нескольких циклов. Мы можем добавить это экспоненциальное число Dantzig-Fulkerson – Условия Джонсона:

sum_{i in S} sum_{j in S} x_{ij} < |S| for all proper subsets S of {1, ..., n}

Обратите внимание, что если наше решение содержит два цикла, то для множества вершин одного из циклов S сумма x_{ij} будет равна |S|. С другой стороны, если есть только один цикл, то сумма x_{ij} никогда не достигнет |S|, например, если вы удалите одну вершину из {1, ..., n}, то количество оставшихся ребер равно n-2, но |S| = п-1.

Конечно, экспоненциальное число ограничений — это не то, что нам нужно, поэтому мы ищем более умный способ исключить случаи подциклов. И вот где Миллер-Такер-Землин вскакивает.

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

person S. Huber    schedule 25.09.2020

Вот хороший пример, который может быть вам полезен: http://z3.codeplex.com/SourceControl/changeset/view/1235b3ea24d9#examples/python/hamiltonian/hamiltonian.py

person Nikolaj Bjorner    schedule 22.06.2013
comment
Привет, Бьорнер. Спасибо за ссылку. Я уже видел вашу ссылку раньше. Он просто проверяет, есть ли у данного промежутка цикл или нет? Но проблема TSP - это проблема оптимизации, где сумма стоимости выбранного пути должна быть минимизирована. У вас есть какие-либо другие предложения? Спасибо - person user1770051; 10.09.2013