Задача коммивояжёра с возвратом в "магазин" - Prolog
Формулировка задачи:
Вроде и тема раскрытая (код можно найти, для этой задачи), но что-то я застрял на
По условию задачи продавец развозит топливо по городам. Если у него топливо закончилось - ему надо возвратиться в магазин (store). Города пройти по одному разу. Нашёл код, добавил обработку значений для запаса топлива продавца: если=0, то сразу в город; если меньше необходимого городу то уменьшаем данные у города, и оправляем продавца в магазин, если больше, уменьшаем запасы продавца и идём в следующий город.
За одно и путь считаю.
Решение задачи: «Задача коммивояжёра с возвратом в "магазин"»
textual
Листинг программы
:- dynamic way/3. :- dynamic way/2. :- dynamic oil/2. :- dynamic capacity/1. % *************************************************************************** % Distance between towns. way(town1,town2,50). way(town3,town4,50). way(town5,town4,35). way(town2,town6,55). way(town5,town6,35). way(town1,town7,40). way(town7,town3,35). % Distance between the well and the towns. way(town1,13). way(town2,19). way(town3,22). way(town4,34). way(town5,19). way(town6,22). way(town7,34). % oil(town1,3). oil(town2,9). oil(town3,2). oil(town4,4). oil(town5,9). oil(town6,2). oil(town7,4). % Bucket capacity. capacity(5). % *************************************************************************** % учёт двунаправленности каждой дороги между городами way_new(X,Y,Z):- way(X,Y,Z); way(Y,X,Z). % учёт двунаправленности каждой дороги между городом и магазином way_new(X,Y):- way(X,Y); way(Y,X). % отновной предикат наждения пути робота % Start - город, который уже обслужил коммивояжёр % Way - список городов, путь коммивояжёра % WayCost - длина этого пути com_way(Start, Way, WayCost):- % собираем список-множество всех городов setof(X,Y^Z^way_new(X,Y,Z), Tree_set), % находим любое соседний город (Finish) way_new(Finish, Start, Cost), % Удаляем Finish из множества городов delete_first(Finish, Tree_set, Tree_set1), capacity(V), oil(Start,W), get_oil(V, W, Start, 0, [well]), write(V), write(' '), write(W), write(' '), writeln(Start), % находим путь без циклов между Start и Finish, проходящий через все города path_com(Finish, Start, Way1, WayCost1, Tree_set1), % пересчитываем путь и его длину WayCost is WayCost1 + Cost, Way=[Start|Way1]. % Вспомогательный предикат: удаление элемента списка delete_first(X,[X|T],T):- !. delete_first(X,[Y|T],[Y|TY]):- delete_first(X,T,TY). % предикат поиска пути Way без циклов, длина пути WayCost, между городами Start и Finish, % проходящий через все города из множества City_set path_com(Start,Finish,Way,WayCost,City_set):- path(Start,Finish,Way,WayCost,City_set,[Finish],0). % базовый вспомогательный предикат поиска пути, % предпоследние два аргумента - накапливающие параметры для пути и его стоимости % когда все деревья уже посещены path(Finish,Finish,Way,WayCost,[],Way,WayCost). % иначе, идем путь из X в Finish через X path(Finish,Finish,Way,WayCost,[],Way,WayCost). % иначе, идем путь из X в Finish через X path(X,Finish,Way,WayCost,City_set,PartWay,PartCost):- % двигаемся к следующему дереву way_new(X,Y,Cost), % есть дорога к дереву member(Y,City_set), % Y ещё не посещён % удаляем Y из множества непосещённых деревьев delete_first(Y,City_set,City_set1), % пересчёт длины пройденного пути PartCost1 is PartCost+Cost, % рекурсивно ищем путь из Y в Finish path(Y,Finish,Way,WayCost,City_set1,[X|PartWay],PartCost1). % предикат нахождения самого короткого пути best_com_way(Start,Way):- % находим все пути с их именами findall(WayCost1/Way1, com_way(Start,Way1,WayCost1), AllWays), % находим минимальную длину пути min_cost(AllWays,MinCost), % выбор любого пути минимальной длины member(MinCost/Way,AllWays). % вспомогательный предикат вычисления минимальной длины пути: % если путь один, то его длина минимальная, % иначе выбор минимума из длины первого пути и длины минимального пути хвоста списка min_cost([WayCost/_],WayCost):- !. min_cost([WayCost1/_|Tail],MinCost):- min_cost(Tail,MinCost1), MinCost is min(WayCost1,MinCost1). % ************************************************************** % get_oil(5,9, 'town5', 0, ['town5']). get_oil(V, 0, Tree, Length, WellPath):- writeln('1'),!. get_oil(V, W, Tree, Length, WellPath):- writeln('2'), W<V, V2 is V-W, get_oil(V2, 0, Tree, Length, WellPath). get_oil(V, W, Tree, Length, WellPath):- writeln('3'), W>=V, W2 is W-V, capacity(V2), way(Tree,L), NewLength is Length+L*2, get_oil(V2, W2, Tree, NewLength, [Tree|[well|WellPath]]). % **************************************************************
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д