This shows you the differences between two versions of the page.
|
pp:23:laboratoare:prolog:intro [2023/05/01 18:01] bot.pp |
pp:23:laboratoare:prolog:intro [2023/05/10 07:30] (current) alexandru.bala [Tipuri de date] |
||
|---|---|---|---|
| Line 53: | Line 53: | ||
| ===== Sintaxă și semantică ===== | ===== Sintaxă și semantică ===== | ||
| - | Programele scrise în Prolog descriu relații exprimitate prin clauze. Există două tipuri de clauze: | + | Programele scrise în Prolog descriu relații exprimate prin clauze. Există două tipuri de clauze: |
| * axiome sau fapte (en. //facts//) | * axiome sau fapte (en. //facts//) | ||
| Line 93: | Line 93: | ||
| ==== Termeni ==== | ==== Termeni ==== | ||
| - | În Prolog orice valoare se numește [[https://www.swi-prolog.org/pldoc/man?section=glossary#gloss:term|termen]]. Tipuri simpli de termeni: constante, sau mai bine zis //atomi// simbolici, întregi, numere în virgulă mobilă sau termeni compuși. | + | În Prolog orice valoare se numește [[https://www.swi-prolog.org/pldoc/man?section=glossary#gloss:term|termen]]. Tipuri simpli de termeni: |
| - | Cuvântul [[https://www.swi-prolog.org/pldoc/man?section=glossary#gloss:structure|structură]] este un sinonim pentru termenul [[https://www.swi-prolog.org/pldoc/man?section=glossary#gloss:compound|compus]]. | + | * Constante textuale, sau mai bine zis //atomi//<code> |
| + | nume, ion, popescu | ||
| - | <code> | + | </code> |
| + | * Numere întregi/numere în virgulă mobilă | ||
| + | * Variabile (vom detalia mai departe)<code> | ||
| + | ?- om(X). | ||
| + | X = socrate. | ||
| + | |||
| + | </code> | ||
| + | * Termeni [[https://www.swi-prolog.org/pldoc/man?section=glossary#gloss:compound|compuși]].<code> | ||
| % exemplu structură | % exemplu structură | ||
| client(nume(ion, popescu), carte(aventuri, 2002)). | client(nume(ion, popescu), carte(aventuri, 2002)). | ||
| </code> | </code> | ||
| - | Puteți considera momentan că sintactic singura diferență este că predicatele nu sunt transmise ca argumente, aceasta fiind o [[https://stackoverflow.com/questions/28972038/prolog-structurecomplex-term-vs-predicate-i-dont-really-get-the-difference|discuție]] mai subtilă ce ține de reprezentarea internă a implementării. | ||
| - | Consultați [[https://www.swi-prolog.org/pldoc/man?section=glossary|**glosarul**]] în caz de orice neînțelegere!!! | + | Cuvântul [[https://www.swi-prolog.org/pldoc/man?section=glossary#gloss:structure|structură]] este un sinonim pentru termenul compus. |
| + | |||
| + | Puteți considera momentan că singura diferență, sintactică, este că predicatele nu sunt transmise ca argumente, aceasta fiind o [[https://stackoverflow.com/questions/28972038/prolog-structurecomplex-term-vs-predicate-i-dont-really-get-the-difference|discuție]] mai subtilă ce ține de reprezentarea internă a implementării. | ||
| + | |||
| + | Consultați [[https://www.swi-prolog.org/pldoc/man?section=glossary|**glosarul**]] pentru orice detalii suplimentare. | ||
| ==== Scopuri și variabile ==== | ==== Scopuri și variabile ==== | ||
| Line 110: | Line 121: | ||
| Când rulăm interogări despre termeni și relațiile dintre ei spunem informal că demonstrăm sau obținem informații pornind de la "baza noastră de date" (de la axiome, de la fapte). | Când rulăm interogări despre termeni și relațiile dintre ei spunem informal că demonstrăm sau obținem informații pornind de la "baza noastră de date" (de la axiome, de la fapte). | ||
| - | Calcul se face prin încercarea de a satisface[^1] //scopuri// (en. //goals//). | + | Calcul se face prin încercarea de a satisface [^1] //scopuri// (en. //goals//). |
| **OBSERVAȚIE**: Când am interogat dacă Socrate este muritor, procesul de execuție a returnat ''%%false%%'' deoarece **nu** se putea satisface acest scop. Nu înseamnă că el este nemuritor. Aceasta este //ipoteza lumii închise// -- orice nu poate fi demonstrat ca adevărat va fi considerat fals. | **OBSERVAȚIE**: Când am interogat dacă Socrate este muritor, procesul de execuție a returnat ''%%false%%'' deoarece **nu** se putea satisface acest scop. Nu înseamnă că el este nemuritor. Aceasta este //ipoteza lumii închise// -- orice nu poate fi demonstrat ca adevărat va fi considerat fals. | ||
| Line 128: | Line 139: | ||
| Observați că în a doua interogare am făcut primul nostru calcul util, folosind o variabilă, ''%%X%%''. Argumentul nu mai este o valoare particulară, ci sistemul de execuție încearcă **legarea** ei la diferite constante sau atomi. Prin convenție numele variabilelor (''%%X%%'') începe cu literă mare iar numele atomilor (''%%leulDinNemeea%%'', ''%%rhesus%%'') începe cu literă mică. | Observați că în a doua interogare am făcut primul nostru calcul util, folosind o variabilă, ''%%X%%''. Argumentul nu mai este o valoare particulară, ci sistemul de execuție încearcă **legarea** ei la diferite constante sau atomi. Prin convenție numele variabilelor (''%%X%%'') începe cu literă mare iar numele atomilor (''%%leulDinNemeea%%'', ''%%rhesus%%'') începe cu literă mică. | ||
| - | Așa cum v-ați obișnuit de la Haskell, și Prolog permite folosirea de variablie [[https://www.swi-prolog.org/pldoc/man?section=glossary#gloss:anonymous|anonime]], ''%%_%%''. Multiple folosiri ale lui ''%%_%%'' nu se leagă la același termen. | + | Așa cum v-ați obișnuit de la Haskell, și Prolog permite folosirea de variabile [[https://www.swi-prolog.org/pldoc/man?section=glossary#gloss:anonymous|anonime]], ''%%_%%''. Multiple folosiri ale lui ''%%_%%'' nu se leagă la același termen. |
| <code> | <code> | ||
| Line 134: | Line 145: | ||
| X = rhesus, | X = rhesus, | ||
| Y = tracia. | Y = tracia. | ||
| + | |||
| + | ?- muritor(X), rege(X, _, _). | ||
| + | X = rhesus. | ||
| </code> | </code> | ||
| Line 168: | Line 182: | ||
| * Axiomele sunt reguli fără corp. | * Axiomele sunt reguli fără corp. | ||
| * Am folosit operatorul ''%%,%%'', "și" logic ($\land$), deci a doua regulă a predicatului ''%%muritor(?Cine)%%'' are două premise. | * Am folosit operatorul ''%%,%%'', "și" logic ($\land$), deci a doua regulă a predicatului ''%%muritor(?Cine)%%'' are două premise. | ||
| - | * Am folosit [[https://www.swi-prolog.org/pldoc/doc_for?object=(%5C%2B)/1|operatorul ''%%\+%%'']] pe care îl puteți trata ca pe o negație pentru moment. | + | * Am folosit operatorul ''%%\+%%'' ([[https://www.swi-prolog.org/pldoc/doc_for?object=(%5C%2B)/1|doc]]) pe care îl puteți trata ca pe o negație pentru moment. |
| Rulăm următoarele interogări: | Rulăm următoarele interogări: | ||
| Line 202: | Line 216: | ||
| </code> | </code> | ||
| - | Deci mai întâi încearcă demonstrarea primei reguli pentru predicatul ''%%muritor%%'' și eșuează. Prima premisă din a doua regulă este adevărată (''%%viu(X)%%''). Observăm că **eșecul demonstrației** scopului ''%%zeu(hercule)%%'' determină adevărată a doua premisă (''%%\+ zeu(X)%%''). Cele două premise fiind puse în conjuncție, considerăm că Hercule este muritor. | + | Observăm că mai întâi încearcă demonstrarea primei reguli pentru predicatul ''%%muritor%%'' și eșuează. Prima premisă din a doua regulă este adevărată (''%%viu(X)%%''). Observăm că **eșecul demonstrației** scopului ''%%zeu(hercule)%%'' determină adevărată a doua premisă (''%%\+ zeu(X)%%''). Cele două premise fiind puse în conjuncție, considerăm că Hercule este muritor. |
| === Negația ca eșec în demonstrație === | === Negația ca eșec în demonstrație === | ||
| Line 248: | Line 262: | ||
| // verificarea celei de-a doua condiții se efectuază doar dacă se trece de prima | // verificarea celei de-a doua condiții se efectuază doar dacă se trece de prima | ||
| if (ptr != NULL && ptr->field != ILLEGAL_VALUE) { | if (ptr != NULL && ptr->field != ILLEGAL_VALUE) { | ||
| - | // do something usefull | + | // do something useful |
| } | } | ||
| Line 273: | Line 287: | ||
| === Diferitele tipuri de "egalitate" === | === Diferitele tipuri de "egalitate" === | ||
| - | * [[https://www.swi-prolog.org/pldoc/doc_for?object=(%3D)/2|''%%=%%'']]: operatorul de unificare. Dacă operanzii nu conțin variabile, atunci verifică identitatea operanzilor; altfel, caută o //legare// a variabilelor în așa fel încât operanzii să unifice. | + | * ''%%=%%'' ([[https://www.swi-prolog.org/pldoc/doc_for?object=(%3D)/2|doc]]): operatorul de unificare. Dacă operanzii nu conțin variabile, atunci verifică identitatea operanzilor; altfel, caută o //legare// a variabilelor în așa fel încât operanzii să unifice. |
| - | * [[https://www.swi-prolog.org/pldoc/doc_for?object=(%5C%3D)/2|''%%\=%%'']]: este adevărat doar dacă cei doi operanzi nu pot unifica -- nu se poate găsi o legare a variabilelor în așa fel încât operanzii să unifice. | + | * ''%%\=%%'' ([[https://www.swi-prolog.org/pldoc/doc_for?object=(%5C%3D)/2|doc]]): este adevărat doar dacă cei doi operanzi nu pot unifica -- nu se poate găsi o legare a variabilelor în așa fel încât operanzii să unifice. |
| - | * [[https://www.swi-prolog.org/pldoc/doc_for?object=(%3D%3D)/2|''%%==%%'']] : verifică dacă doi operanzi sunt același lucru, iar eventualele variabile nelegate din operanzi sunt forțate să unifice la același lucru (printr-o unificare anterioară, de exemplu cu ''%%=%%'').<code> | + | * ''%%==%%'' ([[https://www.swi-prolog.org/pldoc/doc_for?object=(%3D%3D)/2|doc]]) : verifică dacă doi operanzi sunt același lucru, iar eventualele variabile nelegate din operanzi sunt forțate să unifice la același lucru (printr-o unificare anterioară, de exemplu cu ''%%=%%'').<code> |
| ?- A=B, X=A, Y=B, X==Y, writeln("Adevarat"). | ?- A=B, X=A, Y=B, X==Y, writeln("Adevarat"). | ||
| Adevarat | Adevarat | ||
| Line 281: | Line 295: | ||
| </code> | </code> | ||
| - | * [[https://www.swi-prolog.org/pldoc/doc_for?object=(%5C%3D%3D)/2|''%%\==%%'']]: echivalent cu ''%%\+ T1 == T2%%'' | + | * ''%%\==%%'' ([[https://www.swi-prolog.org/pldoc/doc_for?object=(%5C%3D%3D)/2|doc]]): echivalent cu ''%%\+ T1 == T2%%'' |
| - | * [[https://www.swi-prolog.org/pldoc/doc_for?object=(is)/2|''%%is%%'']]: evaluează operandul din **dreapta** și | + | * ''%%is%%'' ([[https://www.swi-prolog.org/pldoc/doc_for?object=(is)/2|doc]]): evaluează operandul din **dreapta** și |
| * dacă în stânga este o variabilă nelegată, **leagă** această variabilă la valoarea din dreapta. | * dacă în stânga este o variabilă nelegată, **leagă** această variabilă la valoarea din dreapta. | ||
| * dacă în stânga este un număr, este echivalent cu ''%%=:=%%'' | * dacă în stânga este un număr, este echivalent cu ''%%=:=%%'' | ||
| - | * [[https://www.swi-prolog.org/pldoc/doc_for?object=(%3D%3A%3D)/2|''%%=:=%%'']]: operator aritmetic care returnează adevărat dacă cele două //expresii// se evaluează la același //număr//. Operanzii trebuie să fie complet instanțiați. | + | * ''%%=:=%%'' ([[https://www.swi-prolog.org/pldoc/doc_for?object=(%3D%3A%3D)/2|doc]]): operator aritmetic care returnează adevărat dacă cele două //expresii// se evaluează la același //număr//. Operanzii trebuie să fie complet instanțiați. |
| - | * [[https://www.swi-prolog.org/pldoc/doc_for?object=(%3D%5C%3D)/2|''%%=\=%%'']]: operator aritmetic care returnează adevărat dacă cele două //expresii// **nu** se evaluează la același //număr//. Operanzii trebuie să fie complet instanțiați. | + | * ''%%=\=%%'' ([[https://www.swi-prolog.org/pldoc/doc_for?object=(%3D%5C%3D)/2|doc]]): operator aritmetic care returnează adevărat dacă cele două //expresii// **nu** se evaluează la același //număr//. Operanzii trebuie să fie complet instanțiați. |
| Pentru o mai bună înțelegere, vom trata operatorii ''%%=%%'', ''%%is%%'', ''%%==%%'', ''%%\==%%'', ''%%=:=%%'' și ''%%=\=%%'' din mai multe perspective. | Pentru o mai bună înțelegere, vom trata operatorii ''%%=%%'', ''%%is%%'', ''%%==%%'', ''%%\==%%'', ''%%=:=%%'' și ''%%=\=%%'' din mai multe perspective. | ||
| Line 384: | Line 398: | ||
| </code> | </code> | ||
| - | ==== Tiprui de date ==== | + | ==== Tipuri de date ==== |
| Am discutat până acum de: | Am discutat până acum de: | ||
| Line 398: | Line 412: | ||
| * Lista vidă: ''%%[]%%'' | * Lista vidă: ''%%[]%%'' | ||
| - | * Lista cu elementele a, b, c: ''%%[a,b,c]%%'' | + | * Lista cu elementele a, b, c: ''%%[a, b, c]%%'' |
| - | * Lista nevidă: ''%%[Prim|Rest]%%'' – unde variabila ''%%Prim%%'' se leagă ([[https://www.swi-prolog.org/pldoc/man?section=glossary#gloss:unify|unifică]] mai bine zis) cu primul element al listei, iar variabila ''%%Rest%%'' cu lista fără acest prim element | + | * Lista nevidă: ''%%[Prim | Rest]%%'' – unde variabila ''%%Prim%%'' se leagă ([[https://www.swi-prolog.org/pldoc/man?section=glossary#gloss:unify|unifică]] mai bine zis) cu primul element al listei, iar variabila ''%%Rest%%'' cu lista fără acest prim element |
| - | * Lista care începe cu n elemente ''%%X1, X2, ..., XN%%'' și continuă cu o altă listă ''%%Rest%%'': ''%%[X1,X2,...,XN|Rest]%%'' | + | * Lista care începe cu n elemente ''%%X1, X2, ..., XN%%'' și continuă cu o altă listă ''%%Rest%%'': ''%%[X1, X2, ..., XN | Rest]%%'' |
| === Șiruri === | === Șiruri === | ||
| - | O secvență de caractere înscrisă între ''%%"%%''. | + | O secvență de caractere (un [[https://www.swi-prolog.org/pldoc/man?section=string|string]]) va fi înscrisă între ghilimele (''%%"%%''). |
| <code> | <code> | ||
| - | ?- X= "abc", string(X), writeln(X). | + | ?- X = "abc", string(X), writeln(X). |
| abc | abc | ||
| X = "abc". | X = "abc". | ||
| Line 426: | Line 440: | ||
| <HTML><li></HTML>''%%Arg2%%'' va fi neinstanțiat atunci când se va încerca satisfacerea predicatului. | <HTML><li></HTML>''%%Arg2%%'' va fi neinstanțiat atunci când se va încerca satisfacerea predicatului. | ||
| <HTML><ul></HTML> | <HTML><ul></HTML> | ||
| - | <HTML><li></HTML>Dacă predicatul este satisfăcut, ''%%Arg2%%'' va fa fi instanțiat la finalul evaluării.<HTML></li></HTML> | + | <HTML><li></HTML>Dacă predicatul este satisfăcut, ''%%Arg2%%'' va fi instanțiat la finalul evaluării.<HTML></li></HTML> |
| <HTML><li></HTML>Dacă ''%%Arg2%%'' este deja instanțiat la evaluarea predicatului, evaluarea poate servi la verificarea corectitudinii argumentului în raport cu semnificația predicatului. | <HTML><li></HTML>Dacă ''%%Arg2%%'' este deja instanțiat la evaluarea predicatului, evaluarea poate servi la verificarea corectitudinii argumentului în raport cu semnificația predicatului. | ||
| <HTML><ul></HTML> | <HTML><ul></HTML> | ||
| - | <HTML><li></HTML>Următorul exemplu, din laboratorele următore, îl folosește pe ''%%R%%'' ca o intrare, și pe ''%%N%%'' ca o ieșire.<HTML></li></HTML><HTML></ul></HTML> | + | <HTML><li></HTML>Următorul exemplu, din laboratoarele următoare, îl folosește pe ''%%R%%'' ca intrare, și pe ''%%N%%'' ca o ieșire.<HTML></li></HTML><HTML></ul></HTML> |
| <code> | <code> | ||
| Line 453: | Line 467: | ||
| * [[https://github.com/cs-pub-ro/PP-laboratoare/raw/master/prolog/intro/prolog-cheatsheet-1.pdf|Cheatsheet]] | * [[https://github.com/cs-pub-ro/PP-laboratoare/raw/master/prolog/intro/prolog-cheatsheet-1.pdf|Cheatsheet]] | ||
| * [[https://ocw.cs.pub.ro/courses/_media/pp/23/laboratoare/prolog/intro-schelet.zip|Schelet]] | * [[https://ocw.cs.pub.ro/courses/_media/pp/23/laboratoare/prolog/intro-schelet.zip|Schelet]] | ||
| - | * [[https://ocw.cs.pub.ro/courses/_media/pp/23/laboratoare/prolog/intro-solutie.zip|Soluții]] | + | * [[https://ocw.cs.pub.ro/courses/_media/pp/23/laboratoare/prolog/intro-solutii.zip|Soluții]] |
| ===== Referințe ===== | ===== Referințe ===== | ||