Вот мое решение:
flightTime(X,Y,T,[Y]):- flightPath(X,Y,T,_).
flightTime(X,Y,T,[Z|TL]):-
flightPath(X,Z,T2,_),
transferTime(Z,T3),
flightTime(Z,Y,T1,TL),
T is T1+T2+T3 .
pathLength(Path, Lentgh):- length(Path,Lentgh).
shortestPath(X,Y,P):- once( (pathLength(P,_),flightTime(X,Y,_,P)) ).
Для flightTime/4
решение - это просто рекурсия, чтобы найти все возможные пути.Кроме того, pathLength/2
довольно ничего особенного.
Пример:
?- flightTime(X,Y,T,L).
X = fco,
Y = jfk,
T = 10,
L = [jfk] ;
X = fco,
Y = sin,
T = 12,
L = [sin] ;
X = sin,
Y = nrt,
T = 8,
L = [nrt] ;
X = lju,
Y = fco,
T = 4,
L = [fco]
... and continues
Теперь, чтобы найти кратчайший путь, есть много способов.Самый простой и очевидный способ - использовать что-то вроде:
Сохранить все пути -> Длина кодирования путей -> Сортировать по длине -> Выбрать путь с минимальной длиной:
custom_length(L,Len-L):- length(L,Len).
shortestPath2(X,Y,P):-
findall(P1,flightTime(X,Y,_,P1), L),
maplist(custom_length,L,L1),
sort(L1,[_-P|_]).
Пример:
?- shortestPath2(fco,nrt,P).
P = [sin, nrt].
Хорошо, это работает, но представьте, что список, который сгенерирует findall/3
, может быть довольно большим для большого графа с несколькими путями между двумя станциями, и тогда также может быть выполнена сортировкаочень много времени ... Лучшая практика здесь - позволить длине генерировать наименьшую длину пути:
shortestPath(X,Y,P):- once( (pathLength(P,_),flightTime(X,Y,_,P)) ).