Хорошо, так: сначала у вас есть петля в ваших фактах: (Лондон, Плимут) и (Плимут, Лондон). Это означает, что любая попытка возврата никогда не закончится.
Тогда я не уверен, что вы можете использовать 2 оператора таким образом, но так как я не уверен, другие люди будут более проницательными в этом вопросе:)
Я взял это соглашение: «Портсмут в Бристоль» [Лондон, Бирмингем] означает «от Портсмута до Бристоля», избегая Лондона и Бирмингема (я принял это соглашение, чтобы не задавать вопросы операторам), вот рабочий код, который отслеживает посещенные города, чтобы избежать бесконечности возможности:
city(portsmouth,london).
city(london,bristol).
city(portsmouth,plymouth).
city(plymouth,london).
city(london,plymouth).
city(london,birmingham).
city(birmingham,bristol).
:- op(150, xfy, to).
Start to End-Avoid :-
findall(Waypoint, get_waypoints(Start, End, [Start], Avoid, Waypoint), Waypoints),
!,
write(Waypoints).
Start to End :-
findall(Waypoint, get_waypoints(Start, End, [Start], [], Waypoint), Waypoints),
write(Waypoints).
get_waypoints(Start, End, _Visited, _Avoid, []) :-
city(Start, End).
get_waypoints(Start, End, Visited, Avoid, [Waypoint|Result]) :-
city(Start, Waypoint),
не ходите по городам, чтобы избежать ...
\+ member(Waypoint, Avoid),
эта проверка позволяет нам не зацикливаться. Таким образом, откат заканчивается.
\+ member(Waypoint, Visited),
get_waypoints(Waypoint, End, [Waypoint|Visited], Avoid, Result).