Professional Documents
Culture Documents
OPERATORI, REZ
SADRŽAJ
oOperatori
oPredefinirani operatori
oVlastiti operatori
oRez
oNadogradnja zadataka
OPERATORI
Ranije smo spomenuli
aritmetičke operatore.
Prolog omogućuje da
korisnik, osim
predefiniranih operatora,
definira i svoje vlastite
operatore.
OPERATORI
Prema broju argumenata Prolog dozvoljava sljedeće vrste
operatora:
◦ unarni -7
◦ binarni 3+1
Prolog daje i mogućnost definiranja tri vrste operatora
prema položaju operanada:
◦ prefiksni -7
◦ infiksni 3+1
◦ postfiksni 8 faktorijela
S obzirom na komutativnost, operatori mogu biti:
◦ komutativni 2+3 = = 3+2
◦ nekomutativni 3-1 =\= 1-3
OPERATORI
Kod definiranja operatora, osim položaja operanada,
definira se i jačina vezivanja, odnosno redoslijed izvođenja
operacija.
Svakom operatoru se određuje nivo između 1 i 1200, pri
čemu se operatori višeg nivoa izvršavaju prije. Na primjer,
direktiva dynamic / 1 je u SWI-Prologu zadana kao
predefinirani operator prioriteta 1150.
PREDEFINIRANI PREDIKAT op / 3
Operatori se u Prologu definiraju
predefiniranim predikatom op / 3. Značenje
argumenata ovog predikata je sljedeće:
1. argument - nivo operatora
2. argument - položaj operanada Objašnjenje drugog argumenta:
3. argument - naziv (oznaka) operatora ◦ slovo f predstavlja operator
◦ slova x i y predstavljaju operande
Prvi argument će biti broj između 1 i 1200 Razlika između x i y je u asocijativnosti
operatora:
Drugi argument može biti jedan od sljedećih ◦ xfx - neasocijativan operator (ne
terma: mogu se dva vezati u jednom izrazu)
fx,fy,xf,yf,xfx,xfy,yfx ◦ xfy - izvođenje operatora slijeva na
desno
Treći argument može biti term ili lista terma ◦ yfx - izvođenje operatora zdesna na
lijevo
koji predstavljaju nazive terma na koje se
odnose prva dva argumenta
OPERATORI
1200 xfx -->, :-
1200 fx :-, ?-
dynamic, discontiguous, initialization, meta_predicate, module_transparent, multifile, public,
1150 fx
thread_local, thread_initialization, volatile
1100 xfy ;, |
1050 xfy ->, *->
1000 xfy ,
990 xfx :=
900 fy \+
700 xfx <, =, =.., =@=, \=@=, =:=, =<, ==, =\=, >, >=, @<, @=<, @>, @>=, \=, \==, as, is, >:<, :<
600 xfy :
500 yfx +, -, /\, \/, xor
500 fx ?
400 yfx *, /, //, div, rdiv, <<, >>, mod, rem
200 xfx **
200 xfy ^
200 fy +, -, \
100 yfx .
1 fx $
OPERATORI
Iskoristit ćemo operatore da bismo omogućili ljepše sučelje
za avanturu u što prirodnijem jeziku.
Sve dosad opisane predikate u bazi ćemo pretvoriti u
operatore i time omogućiti izdavanje komandi igraču bez
zagrada i zareza.
OPERATORI
Za odgovarajuće predikate definiramo unarne operatore na
sljedeći način:
:- op(30,fx,mjesto).
:- op(30,fx,pogledaj). % mijenjamo gledaj/1 u pogledaj/1
:- op(30,fx,idiU).
:- op(30,fx,uzmi).
:- op(30,fx,ispusti).
:- op(30,fx,jedi).
:- op(30,fx,upali).
:- op(30,fx,ugasi).
OPERATORI
Primjeri upita:
?- pogledaj krevet.
false.
OPERATORI
Imamo i jedan neasocijativni Primjer upita:
binarni operator za predikat
jeU / 2: ?- jabuka jeU soba1.
false.
:- op(30,xfx,jeU). ?- jabuka jeU soba2.
true.
REZ
Do sada smo radili s Prologom i vidjeli kako funkcionira
backtracking. Ponekad je dobro isključiti backtracking.
Za tu svrhu koristimo rez (cut) koji je u Prologu predstavljen s !
write(X)
nl
fail
PRIMJER BEZ REZA
pr1(X) a(X)
write(X)
nl
fail
PRIMJER BEZ REZA
true a(1)
pr1(X) a(X)
X=1
write(X)
nl
fail
PRIMJER BEZ REZA
true
pr1(X) a(X)
X=1
write(X)
nl
fail
PRIMJER BEZ REZA
true
pr1(X) a(X)
X=1 X=1
write(X)
nl
fail
PRIMJER BEZ REZA
true
pr1(X) a(X)
X=1
write(X) 1
X=1
nl Ispis:
1
fail
PRIMJER BEZ REZA
true
pr1(X) a(X)
X=1
write(X)
nl nl Ispis:
1
X=1
fail
PRIMJER BEZ REZA
true
pr1(X) a(X)
X=1
write(X)
nl Ispis:
1
false
fail
PRIMJER BEZ REZA
true
pr1(X) a(X)
X=1
write(X)
false
nl Ispis:
1
fail
PRIMJER BEZ REZA
true
pr1(X) a(X)
false X=1
write(X)
nl Ispis:
1
fail
PRIMJER BEZ REZA
pr1(X) a(X)
write(X)
nl Ispis:
1
fail
PRIMJER BEZ REZA
true a(2)
pr1(X) a(X)
X=2
write(X)
nl Ispis:
1
fail
PRIMJER BEZ REZA
true
pr1(X) a(X)
X=2
write(X)
nl Ispis:
1
fail
PRIMJER BEZ REZA
true
pr1(X) a(X)
X=2 X=2
write(X)
nl Ispis:
1
fail
PRIMJER BEZ REZA
true
pr1(X) a(X)
X=2
write(X) 2
X=2
nl Ispis:
1
2
fail
PRIMJER BEZ REZA
true
pr1(X) a(X)
X=2
write(X)
nl nl Ispis:
1
X=2 2
fail
PRIMJER BEZ REZA
true
pr1(X) a(X)
X=2
write(X)
nl Ispis:
1
false 2
fail
PRIMJER BEZ REZA
true
pr1(X) a(X)
X=2
write(X)
false
nl Ispis:
1
2
fail
PRIMJER BEZ REZA
true
pr1(X) a(X)
false X=2
write(X)
nl Ispis:
1
2
fail
PRIMJER BEZ REZA
pr1(X) a(X)
write(X)
nl Ispis:
1
2
fail
PRIMJER BEZ REZA
true a(3)
pr1(X) a(X)
X=3
write(X)
nl Ispis:
1
2
fail
PRIMJER BEZ REZA
true
pr1(X) a(X)
X=3
write(X)
nl Ispis:
1
2
fail
PRIMJER BEZ REZA
true
pr1(X) a(X)
X=3 X=3
write(X)
nl Ispis:
1
2
fail
PRIMJER BEZ REZA
true
pr1(X) a(X)
X=3
write(X) 3
X=3
nl Ispis:
1
2
fail 3
PRIMJER BEZ REZA
true
pr1(X) a(X)
X=3
write(X)
nl nl Ispis:
1
X=3 2
fail 3
PRIMJER BEZ REZA
true
pr1(X) a(X)
X=3
write(X)
nl Ispis:
1
false 2
fail 3
PRIMJER BEZ REZA
true
pr1(X) a(X)
X=3
write(X)
false
nl Ispis:
1
2
fail 3
PRIMJER BEZ REZA
true
pr1(X) a(X)
false X=3
write(X)
nl Ispis:
1
2
fail 3
PRIMJER BEZ REZA
pr1(X) a(X)
write(X)
nl Ispis:
1
2
fail 3
PRIMJER BEZ REZA
false false
pr1(X) a(X)
write(X)
nl Ispis:
1
2
fail 3
PRIMJER BEZ REZA
false
pr1(X) a(X)
write(X)
nl Ispis:
1
2
fail 3
PRIMJER BEZ REZA
pr1('zadnja klauzula')
pr1(X)
write(X)
nl Ispis:
1
2
fail 3
PRIMJER BEZ REZA
pr1(X)
X= 'zadnja klauzula'
write(X)
nl Ispis:
1
2
fail 3
PRIMJER BEZ REZA
pr1(X)
write(X)
nl nl Ispis:
1
X= 'zadnja klauzula' 2
fail 3
zadnja klauzula
PRIMJER BEZ REZA
pr1(X)
write(X)
nl Ispis:
1
false 2
fail 3
zadnja klauzula
PRIMJER BEZ REZA
pr1(X)
write(X)
false
nl Ispis:
1
2
fail 3
zadnja klauzula
PRIMJER BEZ REZA
pr1(X)
false
write(X)
nl Ispis:
1
2
fail 3
zadnja klauzula
PRIMJER BEZ REZA
false
pr1(X)
write(X)
nl Ispis:
1
2
fail 3
zadnja klauzula
false.
PRIMJER – REZ1
Sljedeći primjer je: Postavimo sljedeći upit:
write(X)
nl
fail
PRIMJER – REZ1
pr2(X) a(X)
write(X) !
nl
fail
PRIMJER – REZ1
a(1)
pr2(X) a(X)
X=1
write(X) !
nl
fail
PRIMJER – REZ1
pr2(X)
true
write(X) !
X=1
nl
fail
PRIMJER – REZ1
pr2(X)
true
write(X) !
X=1
nl
fail
PRIMJER – REZ1
pr2(X)
X=1 true
write(X) !
X=1
nl
fail
PRIMJER – REZ1
pr2(X)
true
write(X) 1 !
X=1 X=1
nl
Ispis:
1
fail
PRIMJER – REZ1
pr2(X)
true
write(X) !
X=1
nl nl
Ispis:
X=1 1
fail
PRIMJER – REZ1
pr2(X)
true
write(X) !
X=1
nl
Ispis:
false 1
fail
PRIMJER – REZ1
pr2(X)
true
write(X) !
false X=1
nl
Ispis:
1
fail
PRIMJER – REZ1
pr2(X)
false true
write(X) !
X=1
nl
Ispis:
1
fail
PRIMJER – REZ1
pr2(X)
write(X) !
nl
Ispis:
1
fail
PRIMJER – REZ1
pr2(X)
false
write(X) !
nl
Ispis:
1
fail
PRIMJER – REZ1
false
pr2(X)
write(X)
nl
Ispis:
1
fail false.
PRIMJER – REZ2
Sljedeći primjer je: Postavimo sljedeći upit:
write(X-Y)
nl
fail
PRIMJER – REZ2
pr3(X,Y) a(X)
write(X-Y) !
nl a(Y)
fail
PRIMJER – REZ2
a(1)
pr3(X,Y) a(X)
X=1
write(X-Y) !
nl a(Y)
fail
PRIMJER – REZ2
pr3(X,Y)
write(X-Y) !
X=1
nl a(Y)
fail
PRIMJER – REZ2
pr3(X,Y)
write(X-Y) !
a(1)
nl a(Y)
X=1
Y=1
fail
PRIMJER – REZ2
pr3(X,Y)
write(X-Y) !
true
nl a(Y)
X=1
Y=1
fail
PRIMJER – REZ2
pr3(X,Y)
true
write(X-Y) !
nl a(Y)
X=1
Y=1
fail
PRIMJER – REZ2
pr3(X,Y)
X=1
true
Y=1
write(X-Y) !
nl a(Y)
X=1
Y=1
fail
PRIMJER – REZ2
pr3(X,Y)
true
write(X-Y) 1-1 !
X=1
Y=1
nl a(Y)
X=1 Ispis:
Y=1 1-1
fail
PRIMJER – REZ2
pr3(X,Y)
true
write(X-Y) !
nl nl a(Y)
X=1
X=1 Ispis:
Y=1
Y=1 1-1
fail
PRIMJER – REZ2
pr3(X,Y)
true
write(X-Y) !
nl a(Y)
false X=1 Ispis:
Y=1 1-1
fail
PRIMJER – REZ2
pr3(X,Y)
true
write(X-Y) !
false
nl a(Y)
X=1 Ispis:
Y=1 1-1
fail
PRIMJER – REZ2
pr3(X,Y)
false true
write(X-Y) !
nl a(Y)
X=1 Ispis:
Y=1 1-1
fail
PRIMJER – REZ2
pr3(X,Y)
write(X-Y) !
nl a(Y)
Ispis:
fail 1-1
PRIMJER – REZ2
pr3(X,Y)
write(X-Y) !
nl a(Y)
Ispis:
fail 1-1
PRIMJER – REZ2
pr3(X,Y)
write(X-Y) !
a(2)
nl a(Y)
Y=2 Ispis:
fail 1-1
PRIMJER – REZ2
pr3(X,Y)
write(X-Y) !
true
nl a(Y)
Y=2 Ispis:
fail 1-1
PRIMJER – REZ2
pr3(X,Y)
true
write(X-Y) !
nl a(Y)
Y=2 Ispis:
fail 1-1
PRIMJER – REZ2
pr3(X,Y)
X=1
true
Y=2
write(X-Y) !
nl a(Y)
Y=2 Ispis:
fail 1-1
PRIMJER – REZ2
pr3(X,Y)
true
write(X-Y) 1-2 !
X=1
Y=2
nl a(Y)
Y=2 Ispis:
fail 1-1
1-2
PRIMJER – REZ2
pr3(X,Y)
true
write(X-Y) !
nl nl a(Y)
X=1
Y=2 Ispis:
Y=2
fail 1-1
1-2
PRIMJER – REZ2
pr3(X,Y)
true
write(X-Y) !
nl a(Y)
false Y=2 Ispis:
fail 1-1
1-2
PRIMJER – REZ2
pr3(X,Y)
true
write(X-Y) !
false
nl a(Y)
Y=2 Ispis:
fail 1-1
1-2
PRIMJER – REZ2
pr3(X,Y)
false true
write(X-Y) !
nl a(Y)
Y=2 Ispis:
fail 1-1
1-2
PRIMJER – REZ2
pr3(X,Y)
write(X-Y) !
nl a(Y)
Ispis:
fail 1-1
1-2
PRIMJER – REZ2
pr3(X,Y)
write(X-Y) !
nl a(Y)
Ispis:
fail 1-1
1-2
PRIMJER – REZ2
pr3(X,Y)
write(X-Y) !
a(3)
nl a(Y)
Y=3 Ispis:
fail 1-1
1-2
PRIMJER – REZ2
pr3(X,Y)
write(X-Y) !
true
nl a(Y)
Y=3 Ispis:
fail 1-1
1-2
PRIMJER – REZ2
pr3(X,Y)
true
write(X-Y) !
nl a(Y)
Y=3 Ispis:
fail 1-1
1-2
PRIMJER – REZ2
pr3(X,Y)
X=1
true
Y=3
write(X-Y) !
nl a(Y)
Y=3 Ispis:
fail 1-1
1-2
PRIMJER – REZ2
pr3(X,Y)
true
write(X-Y) 1-3 !
X=1
Y=3
nl a(Y)
Y=3 Ispis:
fail 1-1
1-2
1-3
PRIMJER – REZ2
pr3(X,Y)
true
write(X-Y) !
nl nl a(Y)
X=1
Y=3 Ispis:
Y=3
fail 1-1
1-2
1-3
PRIMJER – REZ2
pr3(X,Y)
true
write(X-Y) !
nl a(Y)
false Y=3 Ispis:
fail 1-1
1-2
1-3
PRIMJER – REZ2
pr3(X,Y)
true
write(X-Y) !
false
nl a(Y)
Y=3 Ispis:
fail 1-1
1-2
1-3
PRIMJER – REZ2
pr3(X,Y)
false true
write(X-Y) !
nl a(Y)
Y=3 Ispis:
fail 1-1
1-2
1-3
PRIMJER – REZ2
pr3(X,Y)
write(X-Y) !
nl a(Y)
Ispis:
fail 1-1
1-2
1-3
PRIMJER – REZ2
pr3(X,Y)
write(X-Y) !
nl a(Y)
Ispis:
fail 1-1
1-2
1-3
PRIMJER – REZ2
pr3(X,Y)
write(X-Y) !
false false
nl a(Y)
Ispis:
fail 1-1
1-2
1-3
PRIMJER – REZ2
pr3(X,Y)
false
write(X-Y) !
nl a(Y)
Ispis:
fail 1-1
1-2
1-3
PRIMJER – REZ2
false
pr3(X,Y)
write(X-Y)
nl
Ispis:
fail 1-1
1-2
1-3
false.
PREDIKAT problem / 1
U našu avanturu ćemo dodati neke probleme koji će
igračima “zagorčavati život”.
Probleme ćemo opisati predikatom problem / 1
Predikat mora imati sljedeća svojstva:
◦ ako je problem uspješno riješen, mora uspjeti
◦ ako problem nije riješen, mora javiti poruku i ne smije
uspjeti
◦ ako problem nije definiran, mora uspjeti
PREDIKAT problem / 1
Prvi problem će biti u tome što igraču zabranjujemo ulaz u
podrum sve dok nema fenjer i dok on nije upaljen
Definirat ćemo predikat:
problem(idiU(podrum)) :-
ima(fenjer),
upaljeno(fenjer),!.
problem(idiU(podrum)) :-
write('U podrumu je mrak!'),nl,!,fail.
PREDIKAT problem / 1
Drugi problem će biti u tome što igraču zabranjujemo izlaz
u šumu sve dok nema ključ
Definirat ćemo predikat:
problem(idiU(šuma)) :-
ima(ključ),!.
problem(idiU(šuma)) :-
write('Vrata su zaključana!'),nl,!,fail.
problem(_). % Piše se samo nakon zadnjeg problema!
PREDIKAT problem / 1
Još trebamo predefinirati predikat idiU / 1 kao:
idiU(Mjesto) :- problem(idiU(Mjesto)),
mozeIci(Mjesto),
pokret(Mjesto),
gledaj.
REZ - NAPOMENA
Treba upozoriti da u slučaju uvođenja reza u program
gubimo jednu značajku logičkog programiranja - nebitnost
redoslijeda klauzula.
Naime, ako se pojavi rez, on će spriječiti daljnje
pretraživanje baze za klauzulama koje zadovoljavaju cilj, jer
će odrezati osnovni cilj i ostaviti samo cilj iza reza.
Rez se može i izbjeći korištenjem predefiniranog predikata
not / 1, čime se dobiva logička čistoća koda i nezavisnost
poretka klauzula.
Definirajmo naš predikat problem / 1 bez upotrebe reza. Za
svaku klauzulu ćemo definirati sve uvjete.
PREDIKAT problem / 1 bez reza
problem(idiU(podrum)) :-
ima(fenjer),
upaljeno(fenjer).
problem(idiU(podrum)) :-
not(ima(fenjer)),
write('Nemaš fenjer, a u podrumu je
mrak!'),nl,fail.
problem(idiU(podrum)) :-
ima(fenjer), not(upaljeno(fenjer)),
write('Upali fenjer, u podrumu je
mrak!'),nl,fail.
PREDIKAT problem / 1 bez reza
problem(idiU(šuma)) :-
ima(ključ).
problem(idiU(šuma)) :-
not(ima(ključ)),
write('Nemaš ključ, a vrata su zaključana!'),
nl,fail.
problem(X) :- not(X = idiU(podrum)), not(X = idiU(šuma)).
PREDIKAT pritisni / 0
Definiramo uvjete za otkrivanje vrata u sobu 3:
pritisni :- polozaj(podrum),
jeU(izbočina,podrum),
not(vrata(hodnik1,soba3)),
assertz(vrata(hodnik1,soba3)),
write('Izbočina se miče! Tajna vrata su otvorena!').
pritisni :- polozaj(podrum),
jeU(izbočina,podrum),
vrata(hodnik1,soba3),
write(‘Ne mogu!'), nl, fail.
PREDIKAT pritisni / 0
pritisni :- not(polozaj(podrum)),
write('Nisi u podrumu!'), nl, fail.
pritisni :- polozaj(podrum),
not(jeU(izbočina,podrum)),
write('Što da pritisnem?'), nl, fail.
PREDIKAT uzeti / 1 - predefiniranje
Predefinirat ćemo predikat uzeti /1 tako da se, ako
uzimamo blago, u sobi3 pojavi ključ koji se nalazio ispod
blaga:
uzeti(Stvar) :- Stvar \= 'blago',
retract(lokacija(Stvar, _)),
asserta(ima(Stvar)),
write('Uzeo sam!'), nl.
uzeti(Stvar) :- Stvar = 'blago',
retract(lokacija(Stvar, _)),
asserta(ima(Stvar)),
assertz(lokacija(ključ,soba3)),
assertz(opisStvari(ključ, opis(srebrni, 100))),
write('Uzeo sam! A tu je i ključ!'), nl.
Govorili smo o…