% ---------------------------------------------------------------------- % Axiomatizations of finite-graph properties and their applications % Chuck Liang, for CPSC 203, December 1998. % Graphs are represented as lists of edges as in [(a,b), (b,c), (a,c)]. domain([1,2,3,4]). % domain of the relation graph1([(a,b), (a,c), (b,a), (c,a)]). % a sample graph reflexive(G) :- domain(Ns), % domain can also be passed in as an arg. nott( (inlist(N,Ns), nott(inlist((N,N), G))) ). symmetric(G) :- nott( (inlist((X,Y),G), nott(inlist((Y,X),G))) ). transitive(G) :- nott( (inlist((X,Y), G), inlist((Y,Z), G), nott(inlist((X,Z), G))) ). antisymmetric(G) :- nott( (inlist((X,Y),G), inlist((Y,X),G), nott(X=Y)) ). irreflexive(G) :- nott( inlist((X,X),G) ). eqrelation(R) :- reflexive(R), symmetric(R), transitive(R). % weak and strict (strong) partial orders: wpo(R) :- reflexive(R), antisymmetric(R), transitive(R). spo(R) :- irreflexive(R), antisymmetric(R), transitive(R). r1([(1,2), (2,2)]). r2([(1,2), (2,3), (1,3), (2,1)]). r3([(1,1),(2,2),(2,3),(3,2),(3,3)]). r4([(1,2),(2,3)]). % Closure operations: % --- refclosure(G,RG) iff RG is the reflexive closure of G: refclosure(G,G) :- reflexive(G). refclosure(G,RG) :- domain(Ns), inlist(N,Ns), nott(inlist((N,N), G)), refclosure([(N,N)|G],RG). % --- symclosure(G,SG) iff SG is the symmetric closure of G: symclosure(G,G) :- symmetric(G). % G is already symmetric symclosure(G,SG) :- inlist((X,Y), G), nott(inlist((Y,X), G)), symclosure([(Y,X)|G], SG). % --- transclosure(G,TG) iff TG is the transitive closure of G: transclosure(G,G) :- transitive(G). transclosure(G,TG) :- inlist((X,Y), G), inlist((Y,Z), G), nott(inlist((X,Z), G)), transclosure([(X,Z)|G], TG). % --- reachable(A,B,G) iff node B is reachable from node A in graph G reachable(A,B,G) :- transclosure(G,TG), inlist((A,B),TG). % complete(G) iff G is a complete graph ( (A,B) in G for all points A, B): complete(Domain,G) :- nott( (inlist(C1,Domain), inlist(C2,Domain), nott(C1=C2), nott(inlist((C1,C2),G))) ). % another sample graph: graph2([(a,c), (c,e), (b,e), (e,d)]). % ------------------------------------------------------------------- % Robust Road Systems % Want: a network of (2-way) roads connecting a number of towns such that: % if any road becomes impassable it will still be possible to go from % any town to any other town. Such a network of roads is called "robust". % domain: towns([hartford,manchester,weathersfield,rockyhill,newington]). roads([ (hartford,manchester), (hartford,weathersfield), (weathersfield,rockyhill), (hartford,newington), (weathersfield,manchester), (newington,manchester), (newington,rockyhill) ]). % graph (symmetic closure of roads) twoways(R) :- roads(Rs), symclosure(Rs,R). % all roads are two-way safe(Towns,Len,N) :- N > Len. safe(Towns,Len,N) :- N =< Len, roads(Normroads), deleteNth(N,Normroads,R2), symclosure(R2,Newroads), % forms two-way roads transclosure(Newroads,TC), !, % (! is for efficiency; ignore) complete(Towns,TC), !, % is the reachability relation complete? N2 is (N + 1), safe(Towns,Len,N2). robust(R) :- towns(Ts), length(R,Len), safe(Ts,Len,0). % goal: twoways(R), robust(R) implies the roads are robust. % Alternative definition of transitive closure that will not add % edges of the form (A,A): trans2(G) :- nott( (inlist((X,Y),G), inlist((Y,Z),G), nott(X=Z), nott(inlist((X,Z),G))) ). transclose2(G,G) :- trans2(G). transclose2(G,TG) :- inlist((X,Y), G), inlist((Y,Z), G), nott(X=Z), nott(inlist((X,Z), G)), transclose2([(X,Z)|G], TG). % utilities % the following definition of negation is needed in some versions of Prolog nott(G) :- G, !, 5 = 4. nott(G). inlist(X,[X|T]). inlist(X,[H|T]) :- inlist(X,T). % deleteNth(N,L,M) iff M is L with the Nth element deleted. deleteNth(0,L,L). deleteNth(1,[H|T],T). deleteNth(N,[H|T],[H|T2]) :- N2 is (N - 1), deleteNth(N2,T,T2).