Merge two predicates in one

I am a beginner at prolog and required to write a predicate path(Start, Dest, Path) for metro stations application using backtracking. Given some facts: connected(x,y) describing the connected stations, I managed to do the following

%% Some facts (for illustration):
connected(a,b).
connected(b,c).
connected(c,d).
connected(d,e).
connected(e,f).

%% Direction A (e.g from b to e)
path1(Start, End, [[Start,End]]):- (connected(Start,End) ; connected(End,Start)),!.
path1(Start, End, [[Start,X]|Path]):-
	connected(Start, X),
	path1(X, End, Path).

%% Direction B (e.g from f to A)
path2(Start, End, [[Start,End]]):- (connected(Start,End) ; connected(End,Start)),!.
path2(Start, End, [[Start,X]|Path]):-
	connected(X, Start),
	path2(X, End, Path). 

%% And for the required predicate:
path(Start, End, Path):-
	path1(Start, End, Path)
	;
	path2(Start, End, Path).

The above predicates works properly and as required, but what I want to do is to merge these two predicates path1 and path2 into a single one in a better way and I don’t know exactly how to do so. Anyone can help?

Thanks in advance.

1 Like

Just simplifing should work, but some check to avoid cycles is sorely needed…

%% Some facts (for illustration):
connected(a,b).
connected(b,c).
connected(c,d).
connected(d,e).
connected(e,f).

path(Start, End, [[Start,End]]):-
	connected2(Start,End),
	!.
path(Start, End, [[Start,X]|Path]):-
	connected2(Start, X),
	path(X, End, Path).

connected2(A,B) :-
  connected(A,B), !.
connected2(A,B) :-
  connected(B,A).

To avoid cycles you can table path/3:

:- table path/3.
1 Like

This only works in the direction (a → f), but not the other way.

Yes, forgive me for not testing my answer. Turns out we need mode directed tabling for this problem:

:- table path(_,_,-).

%% Some facts (for illustration):
connected(a,b).
connected(b,c).
connected(c,d).
connected(d,e).
connected(e,f).

path(Start,End,[[Start,End]]):-
	connected2(Start,End).
path(Start,End,[[Start,X]|Rest]):-
	connected2(Start,X),
	path(X,End,Rest).

connected2(A,B) :-
  connected(A,B).
connected2(A,B) :-
  connected(B,A).

This seems to work

?- path(a,f,P).
P = [[a, b], [b, c], [c, d], [d, e], [e, f]].

?- path(f,a,P).
P = [[f, e], [e, d], [d, c], [c, b], [b, a]].
1 Like