Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

prolog list path and avoid certain route

Tags:

path

prolog

I have a list of data

city(portsmouth,london).
city(london,bristol).
city(portsmouth,plymouth).
city(plymouth,london).
city(london,plymouth).
city(london,birmingham).
city(birmingham,bristol).

I'm using a method which is

 ?-op(150,xfy,pathto).
 ?-op(150,xfy,avoid).
 X pathto Y:- city(X,Y).

and not so sure can be use like

X pathto Y avoid Z:-
    findall(Path,avoid_country(X,Y,Z,Path),Paths),write(Paths),nl.  

avoid_path(Start, End, Avoid,[]) :- 
    country(Start, End).

avoid_path(Start,End,Avoid,[Path|Result]):-
    city(Start,Path),
    Path\== Avoid,
    avoid_path(Path, End,Avoid, Result).

it actually works perfectly without the avoids thing as well as the Path\== Avoid,

the error result is

   | ?- portsmouth to bristol avoid birmingham.
   Error 1, Backtrack Stack Full, Trying city/2

it should be [[london],[plymouth,london]].

like image 306
foxy Avatar asked Apr 09 '26 09:04

foxy


1 Answers

Ok, so : first you got a loop in your facts : (london, plymouth) and (plymouth, london). That means that any attempt of backtracking will never end.
Then I'm not sure that you can use 2 operators this way, but since I'm not sure, other people will be more insightful on the matter :)
I took this convention : portsmouth to bristol-[london, birmingham] means from portsmouth to bristol avoiding london and birmingham (I took this convention not to manage the operators question), here is a working code that keeps track of visited cities to avoid infinite possibilities :

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),

don't go through cities to avoid...

    \+ member(Waypoint, Avoid),

this check allows us not to fall into loops. This way, backtracking ends.

    \+ member(Waypoint, Visited),
    get_waypoints(Waypoint, End, [Waypoint|Visited], Avoid, Result).
like image 88
m09 Avatar answered Apr 11 '26 00:04

m09



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!