Differences

This shows you the differences between two versions of the page.

Link to this comparison view

pp:23:laboratoare:prolog:intro [2023/05/01 14:18]
bot.pp created
pp:23:laboratoare:prolog:intro [2023/05/10 07:30] (current)
alexandru.bala [Tipuri de date]
Line 19: Line 19:
 ==== Prolog ==== ==== Prolog ====
  
-Prolog a fost unul dintre [[https://​en.wikipedia.org/​wiki/​Logic_programming#​History|primele]] limbaje de programare **logice** și rămâne în continuare cel mai popular astfel de limbaj, folosit în demonstratoarele de teoreme și utilizat inclusiv pentru o parte din implementarea sistemului IBM Watson. Permite separarea datelor de procesul de inferență,​ programele fiind scrise într-un stil **declarativ** și uniform. Impactul principal l-a avut în cercetare, în domeniul inteligenței artificiale,​ dar a rămas un punct de inspirație pentru limbajele de după.+[[https://​en.wikipedia.org/​wiki/​Prolog|Prolog]] ​a fost unul dintre [[https://​en.wikipedia.org/​wiki/​Logic_programming#​History|primele]] limbaje de programare **logice** și rămâne în continuare cel mai popular astfel de limbaj, folosit în demonstratoarele de teoreme și utilizat inclusiv pentru o parte din implementarea sistemului IBM Watson. Permite separarea datelor de procesul de inferență,​ programele fiind scrise într-un stil **declarativ** și uniform. Impactul principal l-a avut în cercetare, în domeniul inteligenței artificiale,​ dar a rămas un punct de inspirație pentru limbajele de după.
  
 Numele limbajului este o abreviere pentru //​programmation en logique//, și este bazat pe calcul cu predicate. Numele limbajului este o abreviere pentru //​programmation en logique//, și este bazat pe calcul cu predicate.
Line 29: Line 29:
 > Toții peștii respiră. (prin branhii) > Toții peștii respiră. (prin branhii)
  
-$$\forall ​X . (peste(X) ​\Rightarrow ​respira(X))$$+//∀ X . (peste(X) ​→ respira(X))//
  
 > Unii pești au o respirație aeriană. (prin plămâni) > Unii pești au o respirație aeriană. (prin plămâni)
  
-$$\exists ​X. (peste(X) ​\land respiraAer(X))$$+//∃ X . (peste(X) ​∧ respira(X))//
  
 Limbajul restricționează această logică doar la folosirea de clauze Horn. O clauză este o disjuncție (o operație //sau//) peste predicate sau și negații de predicate. O **clauză Horn** conține un singur literal pozitiv, ceea ce înseamnă că este o implicație care nu poate avea drept concluzie o disjuncție între mai multe predicate. (Vezi cursul pentru o înțelegere mai bună.) Limbajul restricționează această logică doar la folosirea de clauze Horn. O clauză este o disjuncție (o operație //sau//) peste predicate sau și negații de predicate. O **clauză Horn** conține un singur literal pozitiv, ceea ce înseamnă că este o implicație care nu poate avea drept concluzie o disjuncție între mai multe predicate. (Vezi cursul pentru o înțelegere mai bună.)
  
-$$\begin{align} ​A_1 \land A_2 \land \dots \land A_n &​\Rightarrow ​true &​\Rightarrow ​\end{align}$$+A_1 ∧ A_2 ∧ ... ∧ A_n → A 
 + 
 +true → B
  
 Deci următoarea implicație **nu** poate fi transcrisă direct într-o regulă în Prolog, pentru că are ca implicație o disjuncție dintre două predicate. Deci următoarea implicație **nu** poate fi transcrisă direct într-o regulă în Prolog, pentru că are ca implicație o disjuncție dintre două predicate.
  
-$$\begin{rcases} ​int(a) ​int(b) ​\neq sum(a, b) = 0 \end{rcases} \Rightarrow ​negative(a) ​\lor negative(b) ​$$+int(a) ​∧ int(b) ​∧ ≠ ∧ sum(a, b) = 0 → negative(a) ​∨ negative(b)
  
 ==== SWI-Prolog ==== ==== SWI-Prolog ====
Line 51: 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 91: 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 108: 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 126: 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 132: Line 145:
 X = rhesus, X = rhesus,
 Y = tracia. Y = tracia.
 +
 +?- muritor(X), rege(X, _, _).
 +X = rhesus.
  
 </​code>​ </​code>​
Line 166: 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 200: 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 246: 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 271: 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 279: 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 382: Line 398:
  
 </​code>​ </​code>​
-==== Tiprui ​de date ====+==== Tipuri ​de date ====
  
 Am discutat până acum de: Am discutat până acum de:
Line 396: 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 424: 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 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 450: Line 466:
  
   * [[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/​22/​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/​22/​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 =====
pp/23/laboratoare/prolog/intro.1682939900.txt.gz · Last modified: 2023/05/01 14:18 by bot.pp
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0