Упрощенный комбинезон продавца в Prolog
-
25-10-2019 - |
Вопрос
Я просмотрел подобные вопросы, но не могу найти ничего, что имеет отношение к моей проблеме. Я изо всех сил пытаюсь найти алгоритм или набор «петлей», которые найдут путь от CityA
к CityB
, используя базу данных
distance(City1,City2,Distance)
факты Что мне удалось сделать до сих пор, но это всегда возвращается write(X),
А затем завершается с последней итерацией, что я хочу, чтобы это было делать, но только в определенной степени.
Например, я не хочу, чтобы он распечатал любые имена городов, которые являются мертвыми, или для использования окончательной итерации. Я хочу, чтобы он в основном прошел путь от CityA
к CityB
, написание названия городов, на которых он идет на пути.
Надеюсь, кто -нибудь может мне помочь!
all_possible_paths(CityA, CityB) :-
write(CityA),
nl,
loop_process(CityA, CityB).
loop_process(CityA, CityB) :-
CityA == CityB.
loop_process(CityA, CityB) :-
CityA \== CityB,
distance(CityA, X, _),
write(X),
nl,
loop_process(X, CityB).
Решение
Я попытался продемонстрировать, как вы можете достичь того, над чем вы работаете, чтобы вы могли лучше понять, как это работает. Так что, поскольку ваш OP не был очень полным, я взял несколько свобод! Вот факты, с которыми я работаю:
road(birmingham,bristol, 9).
road(london,birmingham, 3).
road(london,bristol, 6).
road(london,plymouth, 5).
road(plymouth,london, 5).
road(portsmouth,london, 4).
road(portsmouth,plymouth, 8).
Вот тот предикат, который мы будем называть, чтобы найти наши пути, get_road/4. Анкет Он в основном называет рабочую предикат, в котором есть два аккумулятора (один для уже посещенных точек и один на расстояние, которое мы проходили).
get_road(Start, End, Visited, Result) :-
get_road(Start, End, [Start], 0, Visited, Result).
Вот рабочий предикат,
get_road/6 : get_road ( +start, +end, +waypoints, +distanceacc, -visited, -totaldistance):
В первом пункте рассказывается, что если между нашим первым пунктом и нашей последней точкой есть дорога, мы можем закончить здесь.
get_road(Start, End, Waypoints, DistanceAcc, Visited, TotalDistance) :-
road(Start, End, Distance),
reverse([End|Waypoints], Visited),
TotalDistance is DistanceAcc + Distance.
Во втором пункте говорится, что если между нашей первой точкой и промежуточной точкой есть дорога, мы можем взять его, а затем решить get_road (промежуточный, конец).
get_road(Start, End, Waypoints, DistanceAcc, Visited, TotalDistance) :-
road(Start, Waypoint, Distance),
\+ member(Waypoint, Waypoints),
NewDistanceAcc is DistanceAcc + Distance,
get_road(Waypoint, End, [Waypoint|Waypoints], NewDistanceAcc, Visited, TotalDistance).
Использование выглядит следующим образом:
?- get_road(portsmouth, plymouth, Visited, Distance).
И доходность:
Visited = [portsmouth, plymouth],
Distance = 8 ;
Visited = [portsmouth, london, plymouth],
Distance = 9 ;
Visited = [portsmouth, plymouth, london, plymouth],
Distance = 18 ;
false.
Я надеюсь, что это будет полезно для вас.
Другие советы
Пожалуйста, отделить чистую часть от нечисто write/1
, nl/0
но и (==)/2
а также (\==)/2
) Пока они полностью переплетаются с вашим чистым кодом, вы не можете ожидать многого.
Вероятно, вам нужна связь между отправной точкой, конечной точкой и пути между ними.
Если этот путь будет ациклическим или вы разрешаете циклы?
Чтобы гарантировать, что элемент X
не происходит в списке Xs
Используйте цель maplist(dif(X),Xs).
Вам не нужны дополнительные вспомогательные предикаты, чтобы сделать это хорошим отношением!
Вы должны вернуть успешный список в качестве переменной Out в all_possible_paths. Затем напишите этот список. Не делайте оба в одной и той же процедуре.