Iti0210lab8: erinevus redaktsioonide vahel

Allikas: Lambda
Mine navigeerimisribale Mine otsikasti
PriitJ (arutelu | kaastöö)
PriitJ (arutelu | kaastöö)
2. rida: 2. rida:


== Sissejuhatus ==
== Sissejuhatus ==
[[Image:Ifi6057lab81.png|150px|right|kollimaailm]]


Proovime Prologis teha teadmusbaasi, mis võimaldab teha järeldusi kollimaailma kohta. Kollimaailm on kirjeldatud õpikus [''AIMA''] 7.2.
Proovime Prologis teha teadmusbaasi, mis võimaldab teha järeldusi kollimaailma kohta. Kollimaailm on kirjeldatud õpikus [''AIMA''] 7.2.
[[Image:Ifi6057lab81.png|300px|right|kollimaailm]]


Teadmusbaas peaks koosnema kahest osast:
Teadmusbaas peaks koosnema kahest osast:
14. rida: 14. rida:
Ehk siis vaatame mingit kindlat ajahetke nagu näiteks joonisel:
Ehk siis vaatame mingit kindlat ajahetke nagu näiteks joonisel:


[[Image:Ifi6057lab82.png|300px|kolliolek]]
[[Image:Ifi6057lab82.png|150px|kolliolek]]


Teeme järeldusi selle ajahetkel kohta. Minimaalselt peaks saama järeldada, kas mingi ruut on turvaline, järgmine samm oleks järeldada, mis on õige järgmine käik.
Teeme järeldusi selle ajahetke kohta. Minimaalselt peaks saama järeldada, kas mingi ruut on turvaline, järgmine samm oleks järeldada, mis on õige järgmine käik.


== Abiks ==
== Abiks ==

Redaktsioon: 28. märts 2018, kell 16:44

Teadmusbaas Prologis

Sissejuhatus

kollimaailm
kollimaailm

Proovime Prologis teha teadmusbaasi, mis võimaldab teha järeldusi kollimaailma kohta. Kollimaailm on kirjeldatud õpikus [AIMA] 7.2.

Teadmusbaas peaks koosnema kahest osast:

  • reeglid, mis kirjeldavad, kuidas kollimaailm töötab
  • faktid, mis kirjeldavad, mida kollimaailmas tegutsev agent seni teinud ja kogenud on

Ehk siis vaatame mingit kindlat ajahetke nagu näiteks joonisel:

kolliolek

Teeme järeldusi selle ajahetke kohta. Minimaalselt peaks saama järeldada, kas mingi ruut on turvaline, järgmine samm oleks järeldada, mis on õige järgmine käik.

Abiks

  • http://learnprolognow.org
  • Adventure in Prolog
  • Lihtsaid katsetusi saab teha veebis, ilma midagi installimata: SWISH.
  • Arvutiklassis on olemas SWI-Prolog. Linuxi jaoks soovitaks GNU Prologi, mis on antud ülesande jaoks täiesti piisav.
  • SWI-Prologis pane faililaiendiks ".pl". Siis käsitleb SWI-Prolog seda kui Prologi koodi, muidu võivad menüüdest vajalikud asjad puudu olla.

Mõned lihtsamad reeglid:

 person(sokrates).              % Sokrates on inimene
 mortal(X):-                    % kõik inimesed on surelikud
   person(X).
 mortal(X):-                    % teine reegel surelikkuse kohta. Prolog vaatab ükshaaval kõiki reegleid
   dead(X).
 dead(platon).                  % veel üks fakt

Kui me teeme päringu ?- mortal(platon). või ?- mortal(sokrates)., siis mõlemale saame vastuseks "yes" (või midagi analoogset, sõltuvalt Prologi versioonist). ?- dead(sokrates). annab aga vastuse "no", kuna selle kohta otsest fakti, ega ka sobivat reeglit ei eksisteeri.

Rekursiivne reegel:

 % faktid
 parent(john,paul).             % paul on johni vanem  
 parent(paul,tom).              % tom on pauli vanem
 parent(tom,mary).              % mary on tomi vanem
   
 % reegel: esivanema leidmine
 ancestor(X,Y):-  % baasjuhtum. Kui Y on X otsene vanem, siis ta ongi kohe esivanem
   parent(X,Y).   
 ancestor(X,Y):-  % rekursiivne reegel
   parent(X,Z),   % Valime mingi Z-i, kes on X-i vanem ja vaatame, kas temale
   ancestor(Z,Y). % on võimalik rekursiivselt esivanemat leida. Z esivanem on ka X esivanem.

Prologis on küll sisse ehitatud debugger, aga esialgu võib vigade otsimise jaoks lihtsam olla teksti välja trükkida. See näeb välja protseduurilise programmeerimise moodi, aga write/1 ja nl/0 on lihtsalt loogikapredikaadid, mille väärtus on alati true.

 mortal(X):-
   write('kas X on inimene?'), nl,
   person(X).
 mortal(X):-
   write('kas X on surnud?'), nl,
   dead(X).

Cut ("!") on kasulik, kui tahetakse otsingut varakult lõpetada. Näiteks, kui ma teen eelnevate näidete puhul päringu ?- mortal(X)., pakutakse mulle nii Sokratest, kui Platonit. Kui ma tean ette, et mind huvitab ainult üks vastus, siis ma võin teha nii:

 existmortal(X):-
   mortal(X),
   !.                        % Kui Prolog ühe sobiva X väärtuse on leidnud ja siia kohta jõudnud
                             % siis ta rohkem enam ei proovi.

Eituse jaoks on sümbol "\+" (siin on pikem seletus):

 deceased(X):-
   mortal(X),
   \+ alive(X).
 mortal(mccartney).
 mortal(lennon).
 alive(mccartney).

Kui mingit asja tahetakse dünaamiliselt modifitseerida, siis tuleb seda Prologile ette deklareerida.

 :- dynamic(person/1).

Peale seda query ?- retract(person(sokrates)). õnnestub.

Kui mingi predikaat on dünaamiline, siis saab selle kohta ka reegleid teha, ilma et predikaat ise oleks defineeritud. Alljärgnev on OK, isegi kui breeze fakte Prologi andmebaasis ei leidu:

 :- dynamic(breeze/1).
 agentpos(1, 1, 1).  % agent asus ajahetkel 1 kohal 1, 1
 breezy(X, Y):-        % koordinaat X, Y on tuuline, kui
   agentpos(X, Y, T),  % agent on kohal X, Y ajahetkel T ja
   breeze(T).          % agent tajub tuuletõmmet ajahetkel T

Alakriips on anonüümne muutuja (meid ei huvita, mis ta väärtus on):

 visited(X, Y) :-
   agentpos(X, Y, _). % agendi positsioon mingil suvalisel ajahetkel oli X, Y

Tuleb tähelepanelik olla, mis on tundmatud muutujad ja mis on teadmusbaasist tuletatavad.

 nopit(X, Y) :-              % saab küsida nopit(X, Y).
   visited(L, Y),
   X is L + 1,               % kui X on tundmatu, siis arvutatakse ta visited(L, Y) abil leitud L-ist
   \+ breezy(L, Y).
 
 nopit_katki(X, Y) :-        % nopit_katki(X, Y) annab vea. Suudab ainult kontollida väiteid nagu nopit_katki(1,2).
   visited(L, Y),
   L is X - 1,               % kui X on tundmatu, siis Prolog L-i väärtust kontrollida ei oska :-(
   \+ breezy(L, Y).