![]() |
|||
| HSG |
|
Tiefensuche versucht durch stetiges Erweitern eines Weges zum Ziel zu gelangen. Im Misserfolgsfall werden durch Backtracking andere Verzweigungen gewählt.
pfeil(a,b).
pfeil(a,c).
pfeil(a,d).
pfeil(b,c).
pfeil(c,d).
pfeil(c,e).
pfeil(d,e).
pfeil(c,a).
weg(X,Y):-pfeil(X,_),pfeil(_,Y),tiefensuche(X,Y,Loesung).
tiefensuche(Start,Ziel,Loesung):-tiefensuche(Start,[Start],Ziel,Loesung).
tiefensuche(Ziel,Pfad,Ziel,Loesung):-Loesung = Pfad,!.
tiefensuche(KnotenA,Pfad,Ziel,Loesung):-pfeil(KnotenA,KnotenN),
not(member(KnotenN,Pfad)),
tiefensuche(KnotenN,[KnotenN|Pfad],Ziel,Loesung).
In "tiefensuche(Ziel,Pfad,Ziel,Loesung):-Loesung = Pfad,!." wird ein Cut verwendet und es kommt die 'Akkumulatortechnik' zur Anwendung.
Tiefensuche kann im Einzelfall sehr ungünstig verlaufen.
pfeil(a,b).
pfeil(a,c).
pfeil(a,d).
pfeil(b,c).
pfeil(c,d).
pfeil(c,e).
pfeil(d,e).
pfeil(c,a).
weg(X,Y):-pfeil(X,_),pfeil(_,Y),weg1(X,Y,[],[]).
weg1(Start,Ziel,Anwaerter,Besucht):-Start=Ziel,
append(Besucht,[Ziel],Route),write(Route).
weg1(Start,Ziel,Anwaerter,Besucht):-append(Besucht,[Start],BesuchtNeu),
findall(N,pfeil(Start,N),Nachfolger),
append(Nachfolger,Anwaerter,AnwaerterNeu),
subtract(AnwaerterNeu,BesuchtNeu,[K|R]),
weg1(K,Ziel,[K|R],BesuchtNeu).
'Schachteldiagramm' zu weg1(a,e,[ ],[ ]).
append (append(L1,L2,L3) fügt die Listen L1 und L2 zu L3 zusammen),
findall ( findall(X,p(X),L) sammelt in der Liste L alle X, die p(X) wahr machen) ,
subtract ( subtract(A,B,D) ermittelt die Differenzmenge D = A\B )
Der Abbruch bei leerer Anwärterliste geschieht in subtract(AnwaerterNeu,BesuchtNeu,[K|R]) , weil [ ] = [K|R] fehlschlägt.
Algorithmus 2 findet höchstens eine Lösung und ist aufwändiger, Algorithmus 1 findet alle Lösungen und ist kürzer.
| In der Aufgabe 21 auf Seite 26 von G.Röhner, Informatik mit Prolog soll ein Weg von a nach g gesucht werden. Herr Röhner schlägt vor, das Labyrinth durch die vorhandenen Türen zu beschreiben. Da man eine Tür in beiden Richtungen beschreiten kann, lässt sich mit pfeil(X,Y):-tuer(X,Y). und pfeil(Y,X):-tuer(X,Y). eine Anpassung an obige Notation vornehmen. |
|
tuer(a,b).
tuer(b,e).
tuer(b,c).
tuer(d,e).
tuer(c,d).
tuer(e,f).
tuer(g,e).
pfeil(X,Y):-tuer(X,Y).
pfeil(X,Y):-tuer(Y,X).
tiefensuche(Start,Ziel,Loesung):-pfeil(Start,_),pfeil(_,Ziel),
tiefensuche(Start,[Start],Ziel,Loesung).
tiefensuche(Ziel,Pfad,Ziel,Loesung):-Loesung = Pfad,!.
tiefensuche(KnotenA,Pfad,Ziel,Loesung):-pfeil(KnotenA,KnotenN),
not(member(KnotenN,Pfad)),
append(Pfad,[KnotenN],PfadNeu),
tiefensuche(KnotenN,PfadNeu,Ziel,Loesung).
Obiges Programm verwendet eine leicht modifizierte Tiefensuche: Neue Knoten werden mit append hinten an den Pfad angehängt. So wird der Pfad am Schluss in der richtigen Orientierung ausgegeben.
?- tiefensuche(a,g,L). L = [a, b, e, g] ; L = [a, b, c, d, e, g] ;