Post on 27-Oct-2019
PATHFINDING WITH PROLOG
Simon Glumpler, Lukas Schelbert
AAI HS16
INHALT
• Einführung
• Verwendung
• Pathfinding Algorithmen
• Prolog
• Pathfinding mit Prolog
EINFÜHRUNG
• Meistens: Optimaler Weg zwischen zwei Punkten
• Suche nach der kostengünstigsten oder kürzesten Route mit den wenigsten
Hindernissen
• Große Anstrengungen um Pathfinding-Algorithmen zu optimieren
• Reduzierung von Laufzeit und Speicherbedarf
VERWENDUNG
• Games
• Routen-Planer
• Autonomes Navigieren
PATHFINDING ALGORITHMEN
• Depth First Search
• Breadth First Search
• Dijkstra
• A*
DEPTH FIRST SEARCH
S
1
862 4
5
97 103
DEPTH FIRST SEARCH
• Einfach zu implementieren
• Gefundener Pfad ist nicht immer der kürzeste Pfad
• Berücksichtigt Pfadkosten nicht
BREADTH FIRST SEARCH
S
1
653 4
2
98 107
BREADTH FIRST SEARCH
• Einfach zu implementieren
• Findet immer kürzesten Pfad
• Schlechte Laufzeit
• Berücksichtigt Pfadkosten nicht
DJIKSTRA
0
1 ?
4
7
6
2 3
1
7
32
4
0
1 7
3
7
6
2 3
1
7
32
4
DJIKSTRA
0
1 6
3
5
6
2 3
1
7
32
4
DJIKSTRA
0
1 6
3
5
6
2 3
1
7
32
4
DJIKSTRA
0
1 6
3
5
6
2 3
1
7
32
4
DJIKSTRA
DIJKSTRA
• Berücksichtigt Pfadkosten
• Greedy Algorithmus
• Kann nicht mit negativen Kantengewichten umgehen
A*
• Erweiterter Dijkstra-Algorithmus
• Nutzt Kenntnisse über die Suchstruktur zum Vorteil aus -> Heuristiken
• z. B. Luftlinie bzw. Euklidische Distanz
• Nächster zu besuchender Knoten wird gewählt mit
• Kosten total = Kosten bisher + geschätzte weitere Kosten
• Der nächste Knoten ist der mit den geringsten totalen Kosten
A*
• Schnellster Algorithmus für Pathfinding (falls Heuristik gut gewählt)
• Findet immer optimale Lösung
• Eventuell grosser Speicherverbrauch
PROLOG
• Deklarative Programmiersprache
• Wichtigste Logische Programmiersprache
• Programmation en Logique
• Alain Colmerauer
• Anfang 70er-Jahre
• Verschiedene Syntax-Dialekte und Implemenationen
• Computerlinguistik und Künstliche Intelligenz
• KI-Systems Watson aus Jeopardy!
PROLOG
• Wissensdatenbank (Fakten und Regeln)
• Anfragen an die Wissensdatenbank
• Resultat: True wenn ableitbar, sonst False
• Hello-World-Beispiel ist eine Wissensdatenbank mit Stammbauminformationen
PROLOG
Wissensdatenbank:
mann(adam).
mann(tobias).
frau(eva).
vater(adam,tobias).
mutter(eva,tobias).
Anfragen:
?- mann(tobias). => yes.
?- mann(stefan). => no.
?- mann(X).
X=adam
X=tobias
PROLOG
Relgeloperator :-
grossvater(X,Y) :- vater(X,Z), vater(Z,Y).
grossvater(X,Y) :- vater(X,Z), mutter(Z,Y).
?- grossvater(adam,anna). => yes.
?- grossvater(X,frank). => X=adam
PROLOG
Listen
[1,2,3,4] => Head: 1 und Tail: [2,3,4]
=> [ 1, [ 2, [ 3, [ 4, [] ] ] ] ]
PROLOG
member(X, [X|_]).
member(X, [_|T]) :- member(X, T).
?- member(2, ['anton', 'berta', 'caesar']).
false.
?- member('berta', ['anton', 'berta', 'caesar']).
true.
CODE BEISPIEL
• Bahnverbindungen
• Kürzeste Verbindung
• Wissensdatenbank:
kante(saintgall, zurich, 80). kante(zurich, basel, 85).
kante(basel, bern, 100). kante(fribourg, lausanne, 10).
kante(lausanne , geneve, 68). kante(zurich , bern, 120).
kante(bern, fribourg, 10). kante(bern , neuchatel, 48).
kante(neuchatel , lausanne, 78). kante(zurich , solothurn, 99).
kante(solothurn , biel, 27). kante(biel , neuchatel, 29).
CODE BEISPIEL
• Ziel:
?- go(zurich,geneve,Route).
Route = [zurich,bern,fribourg,lausanne,geneve]
CODE BEISPIEL
go(Start, Dest, Route) :-
kurz_pfad([r(0, [Start])], Dest, R),
reverse(R, Route).
[ r( 0, [ Start ] ) ]
CODE BEISPIEL
kurz_pfad([r(0, [Start])], Dest, R):
kurz_pfad(Routes, Dest, Route) :-
shortest(Routes, Shortest, RestRoutes),
proceed(Shortest, Dest, RestRoutes, Route).
CODE BEISPIEL
shortest(Routes, Shortest, RestRoutes):
shortest([Route|Routes], Shortest, [Route|Rest]):-
shortest(Routes, Shortest, Rest),
shorter(Shortest, Route),
!.
shorter(r(M1,_), r(M2,_)):- M1 < M2.
CODE BEISPIEL
proceed(Shortest, Dest, RestRoutes, Route):
proceed(r(Dist, [Last|Trail]), Dest, Routes, Route):-
findall(
r(D1, [Z, Last|Trail]),
legalnode(Last, Trail, Z, Dist, D1),
List
),
append(List, Routes, NewRoutes),
kurz_pfad(NewRoutes, Dest, Route).
CODE BEISPIEL
legalnode(Last, Trail, Z, Dist, D1):
legalnode(X, Trail, Y, Dist, NewDist) :-
(kante(X, Y, Z); kante(Y, X, Z)),
legal(Y, Trail),
NewDist is Dist + Z.
CODE BEISPIEL
go(Start, Dest, Route) :-
kurz_pfad([r(0, [Start])], Dest, R),
reverse(R, Route).
kurz_pfad(Routes, Dest, Route) :-
shortest(Routes, Shortest, RestRoutes),
proceed(Shortest, Dest, RestRoutes, Route).
CODE BEISPIEL
shortest: Sucht die aktuell kürzeste Route
proceed: Sucht alle benachbarte Knoten des temporären Endpunktes der
kürzesten Route. Anschliessend wird auf alle gesammelten Routen
wieder die Methode kurz_pfad aufgerufen.
DEMO
FRAGEN?