Я пытался продемонстрировать, как вы можете добиться того, над чем работаете, чтобы лучше понять, как это работает. Так как ваш ОП не был очень полным, я взял на себя смелость! Вот факты, с которыми я работаю:
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 (middle, end).
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.
Надеюсь, это будет вам полезно.