%% Introduction to Artificial Intelligence %% DCS 440, Matthew Stone, mdstone@cs.rutgers.edu %% Prolog code for the week of Sept 25-27, 2000 %% %% %% A bit of Busch campus. %% %% I've encoded the segment relation -- %% there is a segment of path running %% from place S to place E in direction %% D for distance L, a segment called N -- %% in terms of some more basic predicates %% to derive the symmetries of a walking %% path automatically. basicSegment(lsm, arc, south, 100, s1). basicSegment(arc, psych, west, 10, s2). basicSegment(arc, serc, south, 50, s3). basicSegment(serc, hill, south, 30, s4). basicSegment(hill, core, south, 20, s5). basicSegment(arc, sc, south-east, 150, s6). basicSegment(serc, sc, east, 120, s7). basicSegment(hill, sc, east, 100, s8). oppDir(south,north). oppDir(east,west). inverse(A,B) :- oppDir(A,B). inverse(A,B) :- oppDir(B,A). inverse(A-B,C-D) :- inverse(A,C), inverse(B,D). segment(S, E, D, L, N) :- basicSegment(S, E, D, L, N). segment(S, E, D, L, N) :- basicSegment(E, S, OD, L, N), inverse(D, OD). %% An example predicate. %% %% Connected is (meant to be) true of two places %% S and E if there's a sequence of path segments %% connecting S and E. Note that the symmetry %% of connections means that this predicate has %% bad search behavior; and note that this predicate %% offers no facilities for working with a %% specific path between two places. connected(Start, Start). connected(Start, End) :- segment(Start, Mid, _, _, _), connected(Mid, End). %% More useful relationships, defined %% in terms of prolog data structures. %% %% Construct path representations. %% %% Basic version. %% %% A relation isPath that holds of two places S and %% E and a path P just in case P is a path that goes %% from S to E. isPath(S, S, []). isPath(S, E, [ path(S, M, D, L, N) | Rest ]) :- segment(S, M, D, L, N), isPath(M, E, Rest). %% Loop-checking version. %% %% A relation newPath that holds of two places S and E, %% a path P and a list of places A if P is a path %% between S and E and the intermediate nodes in P %% don't loop back on the path and don't visit the %% nodes in A. %% %% Uses an auxilary relation new that holds of an object %% and a list if the object is not an element of the list. newPath(S, S, [], _). newPath(S, E, [ path(S, M, D, L, N) | Rest ], A) :- segment(S, M, D, L, N), new(M,A), newPath(M, E, Rest, [S|A]). new(_,[]). new(A,[B|R]) :- A \== B, new(A,R). %% Describe path representations. %% %% A relation describePath that's always true %% of a path, but which, as a side effect, %% prints out a description of the path to %% the user. describePath( [] ) :- write('You are there.'), nl. describePath( [ path(_S, M, D, L, _N) | Rest ] ) :- write('Go '), write(L), write(' meters '), write(D), write(' to '), write(M), write('.'), nl, describePath(Rest). %% Put it together. %% %% A relation go that holds of two points S and E %% if there is a path between them and which, as %% a side effect of proof, describes one path %% between them to the user. %% %% The basic version. go1(S, E) :- isPath(S, E, P), describePath(P). %% The more effective version. go(S,E) :- newPath(S, E, P, []), describePath(P). %% An aside on reversal. %% Two implementations of a relation %% true of L1 and L2 if list L1 contains %% the same elements as list L2 but in %% the opposite order. %% reverse1: the slow way. reverse1([],[]). reverse1([A|R], X) :- reverse1(R, Y), append1(Y, [A], X). append1([], Y, Y). append1([A|X], Y, [A|Z]) :- append1(X,Y,Z). %% reverse2: the fast way. reverse2(X,Y) :- rapp(X,[],Y). rapp([], Y, Y). rapp([A|R], Y, Z) :- rapp(R,[A|Y],Z).