Prolog


Obsah:


Uvod

Tak pisu neco o prologu..Je to jeden z mych nejoblibenejsich jazyku nejen proto, ze je jednodychy a vykony ale hlavne proto ze je to prvni jazyk, co znam, co ma ksichtiky :- ve zdrojacich. Kouknete se na prologacky zdrojak a plesate. Take to je jazyk co neni ani strukturovany ani objektovy a ma scela novy pristup k veci, ktery se nazyva logic programing. To je moc pekny styl, ktery je lidskemu uvazovani mnohem blizsi a proto clovek, ktery si hraje z prologem je strasne tvorivy a dela ruzne zajimave objevy-kdyz pisete program normale vetsinou presne vite co bude delat ale tady to casto tak jiste neni a prolog vas tim casto prijeme prekvapi.

Toto o tom pisou autori:
Prolog is a simple but powerful programming language developed at the University of Marseilles [Roussel 75], as a practical tool for programming in logic [Kowalski 74] [van Emden 75] [Colmerauer 75]. >From a user's point of view the major attraction of the language is ease of programming. Clear, readable, concise programs can be written quickly with few errors.
(nezni to pekne?)

Rozhodl jsem se pro zmenu nezacit teorii ale jit hned na vec. Napisem takovou malou adventurku, kde by clovek mohl chodit a neco delat. Proste hru minimalne urovne pomsty sileneho ataristy. Na ni bych chtel ukazat vyhody tohoto noveho pristupu. Nepokousejte se zatim nic do prologu busit jenom se zamyslete, co vsechno nam tento postup usetril. (jeji kompletni zdrojaky ,ukazku funkcnosti a popis co jsme vlastne delali pridam na konec.)

Bludiste

Bludiste Kazda textovka obsahuje bludiste. V nem se da nejak pohybovat z mista na misto bud pomoci S J V Z nebo tim, ze napisete kam chcete jit. K tomu potrebujete celkem slozitou datovou strukturu. Je treba aby kazda mistnost mela neco jako:
popis
seznam predmetu
seznam dalsich mistnosti, kam se da jit.
Kdybyste to delali v cecku vypadalo by to asi takto:
struct mistnost {
  char *name
  struct predmet *predmety[MAXPREDMET];
  struct mistnost *dalsi[MAXMISTNOST];
}
No a ted si prestavte to dynamicky alokovani, nacitani z datovyho fajlu, implementaci funkce jdi, ktera musi cely listing dalsi prohledat a porovnat. Navrh struktury datovyho fajlu-jak budete delat ukazatele kdyby fajl vypadal treba jako:
Mistnost:Zachod
Popis:Jsi na zachode...Muzes jit na chodbu nebo oknem ven na zahradu
Predmety:Papir
Cesty:chodba,zahrada
A ted to nacist..vyznat se v nem,kdyz nactete cesty:chodba musite si to napred pamatovat jako string a teprve casem-az bude cela databaze v pameti bude mozne nahradit slova ukazatelama-tudiz musite pridat dalsi kolomky do struktury misnost, ktere budou bezne nepouzity. A cely dohromady by to stalo za nic protoze: V lispu by to slo udelat trochu lepe. Proste byste si udelali strukturu z tema trema polozkama. Cesty i predmety by byly ulozeny jako listy symbolu-takze zadne omezeni na velikost. A vyhledavani by bylo pomoci member. Na pridavani novych cest,predmetu,popisu k mistnosti byste si udelali funkci, ktera by automaticky mistnost zalozila. Ta by byla ulozena v promeny co by se jmenovala stejne jako mistnost takze i ukazatele by byly bez potizi. Fajl z hracim planem by byl v souboru, co by se v includil a co by volal neco jako
(location "papir" "zachod")
(connect "zachod" "zahrada")
(description "zachod" "Jsi na zachode...Muzes jit na chodbu nebo \
oknem ven na zahradu")
A bylo by to relativne jednoduche a eleganti a bez omezeni(snad mimo tluceni se jmen mistnosti z funkcema-musely by se pravdepodobne nazvy delat stylu room-[jmeno]) O to by se uz starala nejaka funkce ktera by se volala nejak: (roomsymbol "blbec")
=> ROOM_BLBEC
To je uz lepsi..Ale jak by to delal prolog?

Proste nijak. Jednoduse byste mu napsali:

|: location(papir,zachod).
|: connect(zachod,zahrada).
|: connect(zachod,chodba).
A protoze cesta chodba->zachod je dvousmerna:
|: connect(chodba,zachod).
A mate to! bludiste je v pameti! Jak rychle jak efektivne a skvrna od tresni je pryc!
A hned se muzete dotazovat..
?- location(papir,X).
X=zachod
?- connect(zachod,X).
X=zahrada
X=chodba
No monkey island to jeste neni ale pametove ulozeni mame a po dvou minutach! Omezeni jsou tu nulovy..format vstupniho fajlu je taky slusny..detekce syntatickych chyb automaticka(interpretrem).

Prikaz jdi

Implementaci prikazu jdi jsme se uz zabyvali..v cecku smyckou co by prosla vsechny moznosti a porovnala pomoci strcmp a zmenila ukazatel aktualni pozice. V lispu pomoci funkce nejak jako:
(let (a (member (roomsymbol mistnost) (mistnost-cesta you)) (
  (if (eq a nil) (print "tam jit nemuzes") (setq you (car a))))
(nejsem si zcela jist jestli je spravne..kdyz ne tak me omluvte)
a v prologu takto:
jdi(X) :-       %funkce na chozeni
  you(L),       %do L ulozi vasi pozici
  connect(L,X),%zjisti jestli vede cesta z L do X-zde muze provadeni selhat
  retract(you(L)),      %Zrusi spojeni ze starou mistnosti
  assert(you(X)).       %Zavede do databaze novou asociaci-you a nova mistnost
jdi(X):-        %V pripade ze cesta nevede-prvni jdi selhalo
  write(' Tam to nejde. '),nl.
Tomu uz asi moc nerozumite..ale verte ze to je zcela jednoducha konstrukce.

Udalosti

Je treba aby se ve hre mohlo take neco dit. To je jeden z neprekonatelnych problemu v cecku-vsechno se vetsinou pise rovnou do kodu a je to pak prasarna. V prologu se to dela asi takto:
smrt :-
  you(L),
  retract(you(L)),
  assert(you(nebe)).


akce :-
  location(papir,zahrada),
  retract(location(papir,zahrada)),
  write(' Vrhla se na tebe diva duchodkyne z holi a utloukla te ze slovy'),nl,
  write(' Takhle znecistovat zivotni prostredi! Kam se ten svet riti! '),
  smrt,        
  akce.        
akce :-        
  nl.
Tato akce zjisti jestli je papir na zahrade,vynada vam a pomoci jednoducheho predikatu smrt vas presune do nebe. Nakonec se rekurzivne zavola to je pro situaci kdyby takovych akci bylo v programu vic.

A ted staci pridat par jednoduchych prikazu a nejkay user interface A monkey island II je na svete! Nebylo to snadny? Tady je videt rozdil mezi strukturovanym a logickym programovanim. Nerikam ze se prolog hodi na vsechno ale na neco je strasne sikovnej=jen se kouknete kolik nam to usetrilo prace! Jak nas to nutilo udelat ten program pekny, citelny snadno rozsiritelny. Jak jsou reseni v prologu elegantni, jednoducha....kolik to usetrilo prace.

A tvrde na vec

(ted je cas nastartovat prolog prikazem pl-distribuci najdete na kazdem mirroru slakwaru v adresari devel/lang/prolog/swi)

Co jsme vlastne psali?

Atomy

Stejne jako lisp ma i prolog atomicky typy.. To jsou cisla:
555
-555
2`1110 je ve dvojkove soustave
6`1323 je v sestkove
konstanty:
To jsou bezna slova zacinajici na male pismeno,symboly jako !@#$%^_ a fura dalsich veci. Promene:
To jsou retezce zacinajici na velke pismeno:Blbec,AA,X,_AAA Atomy v lispu se jmenujou termy

Strukturovane typy

Jako lisp stavi vsechno na consu ma i prolog svuj zakladni strukturovany typ. ten se zapisuje:
predikat(parametry)
tedy treba:
blbec(x,y)
To vytvori jakesi spojeni mezi symboly. Da se pomoci toho moc pekne delat ruzne diagramy(treba bludiste v nasi hre) Nebo asociativni site: barva(medved,cerveny) a potom se muzete ptat jakou barvu ma medved. Da se i retezit:
s(np(john),vp(v(likes),np(mary))
Vytvori takove spojeni:
          s
        /   \
      np     vp
      |    /   \
    john  likes mary
Z nasi hry znate:
location(papir,zachod)
(abyste mohli zadavat clausy ze vstupu musite napsat [user]. - prompt se zmeni na |: a muzete je zadat. po ctrl+d se zase dostanete zpet Je tu ale problem protoze po kazdem zadani [user] se stare vazby zrusi. Proto je lepsi priklady zapisovat do fajlu a potom [fajl] je nahrat do interpretru obsah fajlu z priklady dam na konec)

nebylo volani funkce, ktera by naplnila nejakou strukturu ale jednoduse si prolog zapamatoval neco takoveho:

              papir
                |
           ma location
                |
                v
              zachod
(Takhle se casto zakresluji clausy z dvema parametrama-u tri uz kresleni drhne)

Kdybychom napsali:

umisteni(papir,wc)
rozsirili bychom jeho tabulku na:
              papir
              |   |
        location  umisteni
              |   |
              v   v
          zachod  wc
To prvni slovo je (location,umisteni) je predikat. Zbyle jsou jeho parametry. Trochu to pripomina volani funkce. Muzou byt predikaty bez parametru:
smrt.
nebo z jednim:

barva(zelena).
barva(cervena).

             zelena< -----barva----> cervena
a i vice. To se uz celkem spatne maluje do site. Takovymto jednoduchym zpusebem muzeme vystavet libovolnou asociativni sit. Cely program v prologu je do teto site zabudavan tak, ze muzeme udelat asociace, ktere se nevi predem, ale musi se vyvolat nejaky dalsi kod ktery urci jestli spojeni existuje nebo ne. Vytvareni takovych asociaci popisu pozdeji. Cely prologacky program je tedy soubor pravidel, jak neco ma vypadat a prolog se snazi jim vyhovet.

Bezne pouzivane konstrukce v prologu jsou listy:

    .
   / \
  1   .
     / \
    2   .
       / \
      3   []
Tato konctrukce ma zapis:
.(1,.(2,.(3,[])))
SAmozdrejme ze existuje i pohlednejsi zapis
[1,2,3]
A konstrukce:
     .
    / \
   a   .
      / \
     b   L
jde zapsat
[a,b|L]
Stringy jsou listy integeru z ascikodama.

otazky(direktivy)

pomoci ctrl+d se dostanete zpet do otazkoveho modu(prompt je ?-) a muzete se dotazovat na databazi-odpalit to co jste vytvorili:
?- [clause]
System potom zacne prochazet celou databazi z pokousi se najit dotazovane zpojeni. Muzeme tedy zadat
?- connect(zachod,zahrada).
A system odpovi yes protoze spojeni existuje. Jde tu ale jedna moc zajimava vec:
?- connect(zachod,X).
System zjisti ze X je promena..pokusi se proto v databazi najit nejakou dobrou hodnotu prot promenou. Mame zpojeni mezi zachodem a zahradou napise tedy:
  X = zahrada
a ceka. Pokud zmacknete enter system usoudi ze nasel zpravne a promenou tak nastavi-v dalsi otazce uz bude X vzdycky jenou zahrada. Ale kdyz zmacknete ; system bude hledat dal..a najde jeste jedno spojeni na chodbu a opet se zepta. Kdyz znova zmacknete strednik nic nenajde a napise no.(Pri experimentech je dobre vzdycky mackat stednik protoze jinak se promena na neco nastavi a vy si musite vyprat nejake jine pismeno pro dalsi testovani)

Muzeme pouzivat i predikaty ktere jsme nezadali:

?- member(b,[a,b,c]).
[a,b,c] je list. Member se pta jestli b je jeho prvkem. System tedy odpovi:
yes
Toto je priklad vyvolavani predikatu a dotazovani se na asociaci, ktera se predem nevi-system nema u vsech prvku listu asociaci member ale member je nejaky kus kodu, co to urci. Tedy neco jako funkce, ktera vraci boolean.

Zajimave ale je ze i member muzeme volat z promenou:

?- member(X,[a,b,c]).
Tohle vypada dost nesmyslne-v normalnim jazyce by to proste napsat neslo. Ale v prologu ano. System najde prvni moznost jak by to mohlo souhlasit tedy a. A celkem spravne se zepta:
X = a
A vy muzete odpovedet-enter znamena ano to je spravne
; znamena ne..hledej dal..zepta se tedy na b
Tady je uz jasny jak funguje.
Takovy dotaz se sice zda trochu zbytecny ale verte ze je dost dulezity.

Otazky muzeme retezit za sebe:

?- connect(zachod,X),connect(zahrada,X) a vysledky se budou pekne predavat..

podminky

Ty se delaji pomoci ksichtiku:
:- member(3,[1,2,3]), write(ok).
Napise ok protoze 3 je clenem posloupnosti. Provadeni podminky je podobne jako u otazky z tim rozdilem, ze jeji provadeni se preusi jekamile nejaky dotaz odpovi no. Tedy kdyby volani member vratilo no k volani ok by uz nikdy nedoslo. Zaroven write je priklad jak muze predikat suplovat funkci.

Vytvareni predikatu

Muzeme vytvorit specialni pravidlo-jako member,ktere se predem nevi ale system provede nejaky kod ktery neco zjisti. To se dela napriklad:
(V zadavacim modu)
zamestnany(X) :- zamestnava(X,Y)
(pise se to stejne jako normalni clausa:location(zahrada,zachod) az na to ze misto konstant tam date promene a pak napisete nejake pravidlo) Znamena to neco jako:
X je zamestnany, pokud je nejaky Y ktery ho zamestnava. Takovym zpusobem muzeme popsat i dost slozite situace. A v tom zpociva logicke programovani-popiseme vztahy mezi vecma a potom se proste na neco zeptame a system se nam snazi odpovedet. Takovych podminek pro jeden predikat muzeme napsat vic:
zamestany(X) :- podnikatel(X)
To znamena ze clovek je zamestnany take pokud je podnikatel-podnikatele nikto nezamestnava. Potom kdyz zadame:
?- zamestnany(novak).
System se nejprve podiva jestli je nejake spojeni zamestnava(novak,Y) a pokud ne zjisti jestli je v databazi podnikatel(novak) pokud ani to ne odpovi no.

Takove predikaty jsou pro prolog vsim. Cely program se pomoci nich pise: Tady je vysvetleni na konstrikci:

jdi(X) :-
  you(L),
  connect(L,X),
  retract(you(L)),
  assert(you(X)).
jdi(X) :-
  write(' Tam to nejde. '),nl.
Kdyz se clovek zepta:
?- jdi(zahrada)
Provede kod predikatu-to co nasleduje.Tedy podminku. V teto podmince nejprve pomoci:
  you(L),
Ulozi do L tvoji pozici. To by selhat nemelo. Jedine v tom pripade ze by you zadnou pozici nemel a tak by to byla interni chyba programu.
  connect(L,X)
To je otazka jestli existuje spojeni mezi mistnosti kde se zrovna nachazite a X-kam chcete jit. Pokud toto zpojeni neexistuje prerusi se provadeni a jdi selze. Pokud k tomu preruseni dojde zkusi se dalsi mozny predikat,ktery je nadefinovan a tim je:
jdi(X) :-
  write(' Tam to nejde. '),nl.
A tan spravne vypise chybu. Pokud ale zpojeni existuje pokracuje provadeni radkem:
  retract(you(L)),
To je volani predikatu, ktery je zabudovan primo do prologu a zrusi platnost closy v jeho parametru. Tedy zrusi spojeni mezi vami a starou mistnosti. Dalsi radek:
  assert(you(X)),
Zavede novou closu do databaze tentokrat spojeni mezi vami a novou mistnosti. A posledni radek:
  write(' jses na '),write(X),nl.

Backtracing

Podminky a otazky jsou sice hezka vec. Ale jak jsme si rikali, je nekdy vice reseni. Napriklad napiseme si predikat co odpovi yes prave tehdy kdyz jeho tri parametry jsou za sebou na jedne ceste.
cesta(X,Y,Z) :-
   connect(X,Y),
   connect(Y,Z).
Toto probehne pouze kdyz jsou za sebou. V nasem bludisti to plati pouze pro kombinaci:
?- cesta(chodba,zachod,zahrada).
odpovi yes.
A k cemu by nam byla takova funkce v normalnim jazyce? K nicemu! To ale neplati v prologu! Zadejte treba:
?- cesta(chodba,Y,zahrada).
A co se nestane? system odpovi:
Y = zachod
yes
Stalo se neco zvlastniho....System zauvazoval a nasel spravne reseni. V nasem pripade to je jasne. Predikat se interpretroval jako:
?-  connect(zahrada,Y)
Y = zachod
?-  connect(zachod,chodba)
yes
A nastavilo se tedy Y. Ale co kdybychom udelali dalsi spoje:
|:connect(zahrada,chodba).
|:connect(chodba,zahrada).
Nyni uz situace neni jednoznacna. bludiste vypada:
          /--------zachod< ---> chodba
          |                     ^
      Zahrada< -----------------/
A presto system stale spravne odpovida zachod. To je prave podstata logickeho programovani. My jsme napsali pravidlo a system hleda odpoved tim ze zkousi dosadit vsechny mozne postupy a to dela tak dlouho dokud nenajde odpoved na tu se vas prepta a pokud nevyhovi pokracuje v hledani. Prave teto metode se rika backtracing. To znamena ze klidne muzeme zadat:
?-  cesta(X,Y,zahod).
Tedy ptame se systemu odkud se muzeme dostat pomoci dvou tahu na zachod? A system nam odpovi?
X = zahrada
Y = chodba
a ceka. Pokud zmackeneme enter uz dal nehleda ale pokud dame ; klidne napise:
X = chodba
Y = zahrada
Pokud opet odmitneme odpovi ze uz dalsi reseni nezna. To mi pripomelo davida kaprfilda(nebo jak se pise) a jeho oblibena slova:budu carovat s vami...dejte si prst na obrazovku a vyberte si ctverecek a udelejte tri tahy uhlopricne nebo rovne. A vim ze nejste ve vagone..... Najit takovy postup je celkem slozite ale v prologu by se to psalo jedna basen... Proste by jste si udelali predikaty na posouvani a potom by sjte udelali dotaz kdy predikat najdi_cestu_na_X(X,Y) je nula... Psat neco takoveho v konvencnim jazyce by bylo utrpeni.

Dalsi sikovne vyuziti bactracingu je to,ze muze simulovat smycky. Napriklad kdyz chceme vypsat vsechny cesty z mistnosti muzeme udelat:

cesty :-
  you(L),
  connect(L,X),
  write(X),
  write(' '),
  fail.
cesty :-
  nl.
A system napred bude chtit vyhovet prvnimu predikatu. Ten funguje takto:
  1. uloz pozici hrace do L. To jde vzdycky.
  2. Do X uloz cestu ven. Tech prave muze byt vic. ale do X se da vzdy jen jedna.
  3. Vypis X.
  4. Vypis mezeru pred dlasim slovem
  5. Selzi. Odpoved predikatu fail je vzdy no. Proto chudak system bude zkouset dalsi cestu do X a vypise ji.
Nyni muzeme rozsirit go na:
go :-
  write('cesty:'),
  cesty,
  write('>> '),
  read(X),
  call(X),
  akce,
  go.
Podobne se necha udelat take seznam predmetu v mistnosti a inventar.

Tim jsem snad objasnil zaklady prologu. Je cas ukazat zdrojaky.


Funkcni textovka

%Umistime predmety

location(papir,zachod).

% Bludiste

connect(zachod,zahrada).
connect(zachod,chodba).
connect(chodba,zachod).
connect(zahrada,chodba).
connect(chodba,zahrada).

% Popisy pro jednotlive mistnosti

describe(papir,'proste toaletak').
describe(zachod,'Jdi na zachode..nelibe to tu voni').
describe(zahrada,'Jsi na zahrade..ptaci zpivaji, slunce sviti...').
describe(chodba,'Jsi na chodbe..vede ze zachodu na zahradu').

% Predikaty co delaji smycky prez backtracing

cesty :-        %vypise vsechny cesty s mistnosti
  you(L),       %ulozi do L vasi pozici
  connect(L,X), %zjisti cestu z L a do X ulozi cil-tady se dela backtracing
  write(X),     %vypise cilovou mistnost
  write(' '),   %oddeli slova
  fail.        %selze,aby se system pokusil najit dalsi cestu a take ji vypsal
cesty :-        %tohle se vyvola,kdyz uz neni zadna cesta k vypsani
  nl.        %novy radek-konec vypisu


vydis :-        %vypise predmety v mistnosti
  you(L),       %ulozi do L vasi pozici
  location(X,L),%najde predmet ktery je v mistnosti L-tady se dela backtracing
  write(X),     %vypise nalezeny predmet
  write(' '),   %oddeli slova
  fail.        %selze
vydis :-        %tohle se vyvola kdyz uz neni dalsi predmet v mistnosti
  nl.


inventar :-     %vypise,co uzivatel nese-funguje stejne jako vidis ale
  location(X,you), %misto mistnosti testuje you
  write(X),
  write(' '),
  fail.
inventar :-
  nl.


popis :-        %vypise popis mistnosti
  you(L),       %do L ulozi vasi pozici
  describe(L,X),%vyhleda popis mistnosti
  write(X),nl.  %a vypise

% Jednoduche predikaty na modifikaci herni databaze

jdi(X) :-       %funkce na chozeni
  you(L),       %do L ulozi vasi pozici
  connect(L,X),%zjisti jestli vede cesta z L do X-zde muze provadeni selhat
  retract(you(L)),      %Zrusi spojeni ze starou mistnosti
  assert(you(X)).       %Zavede do databaze novou asociaci-you a nova mistnost
jdi(X):-        %V pripade ze cesta nevede-prvni jdi selhalo
  write(' Tam to nejde. '),nl.


smrt :-        %Tento predikat vas zabije
  you(L),       %Do L ulozi vasi pozici
  retract(you(L)),      %Zrusi spoj ze starou mistnosti
  assert(you(nebe)).    %Presune vas do nebe


akce :-        %Tyto predikaty ridi vsechny udalosti,ktere dejou ve hre
  location(papir,zahrada),      %Pokud jste vyhodili papir na zahradu
  retract(location(papir,zahrada)),%Zrus spojeni-aby se zabranilo zacykleni
  write(' Vrhla se na tebe diva duchodkyne z holi a utloukla te ze slovy'),nl,
  write(' Takhle znecistovat zivotni prostredi! Kam se ten svet riti! '),
  smrt,        %Zabyje vas
  akce.        %Spusti se znova rekurzivne.Touto konstrukci se zarizuje to,
                %aby bylo mozne takovych akci udelat vic. Proste se pisou za
                %sebe. Kdyz tento predikat probehne,automaticky zrusi podminky
                %aby mohl probehnout znova-zrusi papir. Pri dalsim provadenim
                %selze,vyvola se tedy dalsi mozna situace-dalsi akce ve hre
akce :-        %Toto je posledni z akci-nic se nestalo. To je proto,aby
                %volani akce z go neselhalo a nezrusilo tim provadeni cele hry
  nl.


done :-        %Tento predikat zjistuje jestli hra nezkoncila
  you(nebe),
  write(' Sice jste zemrel ale nevadi...vlastne sjte hru vyhral ').

%Hlavni smycka

go :- done.     %Timto je zaruceno aby hra zkoncila v pripade, ze done zjisti
                %ze je konec-provede se tato prvni moznost go a ukonci se
go :-           %Jinak se pokracuje na toto go
  popis,        %Vypise popis mistnosti
  write('cesty:'),%Vypise vesty z mistnosti
  cesty,
  write('vydis:'),%Vypise co vidis
  vydis,
  write('>> '), %Prompt
  read(X),      %Nacte closu z klavesnice
  call(X),      %Provede nactenou closu
  akce,         %Akce-tedy duchodkyne
  go.           %Smycka pomoci rekurze

%Uzivatelske prikazy

zvedni(X) :-    %Zvedne predmet
  you(L),
  location(X,L),%Zjisti jestli predmet X je v mistnosti L-zde muze selhat
  retract(location(X,L)),%Zrusi spojeni predmetu z mistnosti
  assert(location(X,you)),%Zavede zpojeni z vami
  write(' Zvedl jsi '),write(X),nl.%A hlaska
zvedni(X) :-    %Pro pripad selhani
  write(X),write(' tu nikde neni').


poloz(X) :-     %Polozi predmet
  location(X,you),
  you(L),
  retract(location(X,you)),
  assert(location(X,L)),
  write(' Polozil jsi'),write(X),nl.
poloz(X) :-
  write(X),write(' u sebe nemas').

%Predikaty z vykladu..

cesta(X,Y,Z) :-%Typicky priklad backtracingu
   connect(X,Y),
   connect(Y,Z).
you(zachod).

% Priklad matematiky v prologu

mul(R1,I1,R2,I2,R3,I3):-%Nasobeni komplexnich cisel
  R3=R1*R2-I1*I2,
  I3=R1*I2-R2*I1.

A priklad pouziti

1 ?- [pll].
[WARNING: (/root/pll:41)
        Singleton variables: X]
pll compiled, 0.03 sec, 6,300 bytes.

Yes
2 ?- go.
Jdi na zachode..nelibe to tu voni
cesty:zahrada chodba
vydis:papir
>> |: zvedni(papir).
 Zvedl jsi papir

Jdi na zachode..nelibe to tu voni
cesty:zahrada chodba
vydis:
>> |: jdi(chodba).

Jsi na chodbe..vede ze zachodu na zahradu
cesty:zachod zahrada
vydis:
>> |: inventar.
papir

Jsi na chodbe..vede ze zachodu na zahradu
cesty:zachod zahrada
vydis:
>> |: poloz(papir).
 Polozil jsipapir

Jsi na chodbe..vede ze zachodu na zahradu
cesty:zachod zahrada
vydis:papir
>> |: zvedni(papir).
 Zvedl jsi papir

Jsi na chodbe..vede ze zachodu na zahradu
cesty:zachod zahrada
vydis:
>> |: jdi(zahrada).

Jsi na zahrade..ptaci zpivaji, slunce sviti...
cesty:chodba
vydis:
>> |:
>> |: poloz(papir).
 Polozil jsipapir
 Vrhla se na tebe diva duchodkyne z holi a utloukla te ze slovy
 Takhle znecistovat zivotni prostredi! Kam se ten svet riti!
 Sice jste zemrel ale nevadi...vlastne sjte hru vyhral
Yes

priklady funkce bactracingoveho predikatu cesta

3 ?- cesta(X,Y,zachod). X = zachod Y = chodba ; X = zahrada Y = chodba ; No 4 ?- cesta(X,zachod,Y). X = chodba Y = zahrada ; X = chodba Y = chodba ; No 5 ?- cesta(zachod,X,Y). X = zahrada Y = chodba ; X = chodba Y = zachod ; X = chodba Y = zahrada ; No 6 ?- cesta(zachod,X,zachod). X = chodba ; No

Trocha matematiky

7 ?- mul(1,2,3,4,I,R). I = 1 * 3 - 2 * 4 R = 1 * 4 - 3 * 2 ; No Vyrazy se vyhodnocuji az kdyz je treba 8 ?- mul(1,2,I,R,I1,R1). I = G792 R = G796 I1 = 1 * G792 - 2 * G796 R1 = 1 * G796 - G792 * 2 ; No Z backtracingem v matematice je to uz horsi.....

Zaver

Jak jste asi videli prolog je velmi jednoduchy jazyk ze scela novym pohledem na svet. Jde v nem udelat hodne zajimavych a slozitech algoritmu. Pri navrhovani programu setri hodne prace a vsechno jde v nem rychle a tedy i bez chyb. Nase velmi jednoducha textovka mela mnohem min problemu nez kdybychom ji delali v cecku. Jedina dira,ktera v ni je, je v go ktery pousti prikazovou radku prologu. Tam by to chtelo vylepsit nacitani do stringu a nejake to zpracovani pred volanim ale jinak cely program nema chybu. Je snadno rozsiritelny, Pridat nove prikazy, akce, mistnosti nebo treba grafiku a zvuk je hrackou.

Taky jsem zaradil prolog mezi lispovsky jazyky. To je proto ze stejne jako lisp ma udelane promene, trypy(atomicke atd..) ma podobne rozdeleni interpretru-proto read(X) necetlo string ale celou clausu protoze i v prologu se clause da ulozit do premene. Ma dynamicke usporadani pameti a hodne dalsich spolecnych rysu. Proto existuje hodne prologackych interpretru napsanych v lispovi.


Tento soubor je soucasti rozsahle sbirky skolicek na http://www.ucw.cz/~hubicka/skolicky

Take si muzete prohlidnout jeji puvodni textovou podobu

Nebo mi mailnout na hubicka@ucw.cz

Copyright (C) Jan Hubicka 1995