2

I have created this knowledge base in Prolog, which reflects a bus company wth busses going from and to places, leaving and arriving at set times:

connection(kerkrade, heerlen, 1100, 1200).
connection(kerkrade, bleijerheide, 1100, 1225).
connection(heerlen, kerkrade, 1115, 1230).
connection(heerlen, maastricht, 1230, 1330).
connection(maastricht, heerlen, 1430, 1530).
connection(maastricht, sittard, 1331, 1430).
connection(maastricht, sittard, 1345, 1445).
connection(sittard, maastricht, 1630, 1530).
connection(sittard, denbosch, 1530, 1700).
connection(denbosch, sittard, 1800, 1930).
connection(denbosch, amsterdam, 1000, 1330).

checkTime(X,Y,Z):-
    connection(X,Y,S,_),
    (Z =< S).

 aRoute(From, To, Time):-
    checkTime(From,To,Time).

testRoute(A,B,T):-
    walk(A,B,T,[]).


walk(A,B,Time,V) :-
    aRoute(A,X,Time),
    not(member(X,V)),
    (
        B = X;
        connection(A,X,_,S), walk(X,B,S,[A|V])
    ).

Whenever I ask my knowledge base if there is a route between two points, it returns whether that's possible; true or false:

testRoute(kerkrade, sittard, 900).
true; (signifies that there are three routes, of which two are possible)
true;
false.

However, this is not what I desire. In the best case I want to show the connections used to create the route between two points in the toplevel like this:

connection(kerkrade, heerlen, 1100, 1200)
connection(heerlen, maastricht, 1230, 1330)
/* and so on.. */

How do I do this? I think I have to pass a variable like X along with my call to testRoute, so that it can report the value of it. I'm having trouble writing the predicate for that, as I am unsure where to place it. My idea is that I have to add an extra parameter to walk(A,B,Time,V) but I wouldn't know what I could do with it after that in order to make it report the intermediate steps of the route.

Zimano
  • 1,870
  • 2
  • 23
  • 41

2 Answers2

2

You could keep a list with the connections by writing:

 checkTime(X,Y,Z, connection(X,Y,S,W)):-
    connection(X,Y,S,W),
    (Z =< S).

 aRoute(From, To, Time,Head):-
    checkTime(From,To,Time,Head).

testRoute(A,B,T,L):-
    walk(A,B,T,[],L).


walk(A,B,Tijd,V,[Head|L]) :-
    aRoute(A,X,Tijd,Head),
    not(member(X,V)),
    (
        B = X,L=[];
        connection(A,X,_,S), walk(X,B,S,[A|V],L)
    ).

Example:

?- testRoute(kerkrade, sittard, 900,L).
L = [connection(kerkrade, heerlen, 1100, 1200), connection(heerlen, maastricht, 1230, 1330), connection(maastricht, sittard, 1331, 1430)] ;
L = [connection(kerkrade, heerlen, 1100, 1200), connection(heerlen, maastricht, 1230, 1330), connection(maastricht, sittard, 1345, 1445)] ;
false.
coder
  • 12,832
  • 5
  • 39
  • 53
  • Your answer worked flawlessly, thank you! What does the `L=[ ]` do exactly? Does it evaluate equality between an empty list and L? – Zimano Oct 13 '16 at 12:10
  • It unifies L with the empty list since you instantiated the Head of the list and you finish there so the tail of the list must be empty (there are no other elements to add). – coder Oct 13 '16 at 12:18
2

I want to show the connections used to create the route between two points [...] How do I do this? I think I have to pass a variable like X along with my call to testRoute, so that it can report the value of it.

Yes: I suppose you have to pass another variable for the route

I propose the following solution

walk(Stop, Stop, _, ReverseRoute, DirectRoute):-
  reverse(ReverseRoute, DirectRoute).

walk(Start, Stop, TimeMin, ReverseRoute, DirectRoute) :-
  connection(Start, Mid, TimeStart, TimeArrival),
  TimeMin =< TimeStart,
  not(member(Mid, ReverseRoute)),
  walk(Mid, Stop, TimeArrival, [Mid | ReverseRoute], DirectRoute).

testRoute(Start, Stop, TimeStart, Route) :-
  walk(Start, Stop, TimeStart, [Start], Route).
max66
  • 65,235
  • 10
  • 71
  • 111