% Program realizuje algorytm Dijkstry poszukując najkrótszej ścieżki pomiędzy
% dwoma wierzchołkami. Korzysta z predykatów tworzonych dynamicznie, za pomocą
% których implementowana jest kolejka dla przeszukiwania wszerz.
% Przykładowy zestaw danych.
wierzcholki([a,b,c,d,e,f]).
sasiedzi(a,[b,d,f]).
sasiedzi(b,[c,f,a]).
sasiedzi(c,[d]).
sasiedzi(d,[a,e]).
sasiedzi(e,[f,d]).
sasiedzi(f,[d]).
:- dynamic bialy/1,
szary/1,
sciezka/2.
% Główny predykat: znajdź ścieżkę od Poczatek do Koniec i zapisz ją w Sciezka
szukaj(Poczatek,Koniec,Sciezka) :-
wierzcholki(V), % pobierz dostępne wierzchołki
inicjuj(V), % inicjuj predykaty
retract(bialy(Poczatek)),
assert(sciezka(Poczatek,[Poczatek])),
assert(szary(Poczatek)), % pierwszy wierzchołek w kolejce
dijkstra(Koniec,Sciezka), % znajdź scieżkę
!. % uniemożliwiamy nawroty
% Ustawia wszystkie wierzchołki w stanie 'bialy'.
inicjuj([]).
inicjuj([X|Y]) :-
assert(bialy(X)),
inicjuj(Y).
% Wyszukaj ścieżkę do Koniec i zapisz ją w Sciezka.
dijkstra(Koniec,Sciezka) :-
retract(szary(Koniec)),
sciezka(Koniec,Sciezka).
dijkstra(Koniec,Sciezka) :-
retract(szary(Wierzcholek)),
sasiedzi(Wierzcholek,Sasiedzi),
sprawdz_sasiadow(Wierzcholek,Sasiedzi),
dijkstra(Koniec,Sciezka).
dijkstra(_,[]). % Jeśli dotarł tutaj, to nie ma połączenia.
% Predykat dla każdego sąsiada aktualizuje ścieżkę do niego i dodaje jego
% sąsiadów do kolejki.
sprawdz_sasiadow(_,[]).
sprawdz_sasiadow(Wierzcholek,[Sasiad|Reszta]) :-
retract(bialy(Sasiad)),
sciezka(Wierzcholek,Sciezka), % pobierz ścieżkę do bieżącego wierzchołka
assert(sciezka(Sasiad,[Sasiad|Sciezka])),
assertz(szary(Sasiad)), % dodaj na końcu kolejki
sprawdz_sasiadow(Wierzcholek,Reszta).
sprawdz_sasiadow(Wierzcholek,[_|Reszta]) :- % jeśli poprzedni sąsiad nie był wolny
sprawdz_sasiadow(Wierzcholek,Reszta).