Customize Consent Preferences

We use cookies to help you navigate efficiently and perform certain functions. You will find detailed information about all cookies under each consent category below.

The cookies that are categorized as "Necessary" are stored on your browser as they are essential for enabling the basic functionalities of the site. ... 

Always Active

Necessary cookies are required to enable the basic features of this site, such as providing secure log-in or adjusting your consent preferences. These cookies do not store any personally identifiable data.

No cookies to display.

Functional cookies help perform certain functionalities like sharing the content of the website on social media platforms, collecting feedback, and other third-party features.

No cookies to display.

Analytical cookies are used to understand how visitors interact with the website. These cookies help provide information on metrics such as the number of visitors, bounce rate, traffic source, etc.

No cookies to display.

Performance cookies are used to understand and analyze the key performance indexes of the website which helps in delivering a better user experience for the visitors.

No cookies to display.

Advertisement cookies are used to provide visitors with customized advertisements based on the pages you visited previously and to analyze the effectiveness of the ad campaigns.

No cookies to display.

Prolog

Il Prolog è un linguaggio di programmazione logica utilizzato per la rappresentazione della conoscenza. Il nome “Prolog” deriva da “PROgramming in LOGic“.

A differenza di molti altri linguaggi di programmazione, il Prolog si basa su un paradigma dichiarativo e un sistema d’inferenza che sfrutta la logica del primo ordine e l’unificazione per dedurre le risposte alle interrogazioni.

In Prolog, i programmi sono composti da:

  • Fatti (facts): definiscono gli oggetti e le relazioni tra essi
  • Regole (rules): definiscono il modo in cui i diversi oggetti sono in relazione
  • Obiettivi (goals): definiscono ciò che si vuole ottenere

Nota bene: in Prolog, ogni programma è composto da sole clausole di Horn.

Esempi:

Facts:work(emp1, deepmind).work(emp2, deepmind).work(emp3, ibm).work(emp4, ibm).Goal:colleague(X, Y).Rule:colleague(X, Y):-  work(X, Z), work(Y, Z).\text{Facts:}\\ \texttt{work(emp1, deepmind)}.\\ \texttt{work(emp2, deepmind)}.\\ \texttt{work(emp3, ibm)}.\\ \texttt{work(emp4, ibm)}.\\ \\[10pt] \text{Goal:}\\ \texttt{colleague(X, Y)}.\\ \\[10pt] \text{Rule:}\\ \texttt{colleague(X, Y)}\,\text{:-}\,\,\texttt{work(X, Z), work(Y, Z)}.

Nota bene: ogni riga deve finire con il punto.

Per interrogare la knowledge base (ovvero il nostro programma) usiamo l’operatore ?-\text{?-}

?-  colleague(emp1, emp2).oppure?-  colleague(emp1, emp3).\text{?-}\,\,\texttt{colleague(emp1, emp2)}.\\ \text{oppure}\\ \text{?-}\,\,\texttt{colleague(emp1, emp3)}.

dove stiamo controllando se i diversi impiegati sono colleghi di lavoro, avendo prima definito il significato di colleague(X, Y)\texttt{colleague(X, Y)}.

In Prolog si possono inoltre utilizzare le seguenti operazioni

PrologLogicaImplicazioneA :- BBACongiunzioneA,BABDisgiunzioneA;BAB\begin{matrix} &\text{Prolog}&\text{Logica}\\[5pt] \text{Implicazione}&\text{A :- B}&\text{B$\Rightarrow$A}\\[10pt] \text{Congiunzione}&\text{A,B}&\text{A$\wedge$B}\\[10pt] \text{Disgiunzione}&\text{A;B}&\text{A$\vee$B} \end{matrix}

La terminologia

Facendo riferimento al seguente codice Prolog

Chiamiamo le diverse parti del codice nel seguente modo:

  • likes, food: predicati
  • mary, pizza, antonio, john, icecream: costanti
  • Thing: variabile

Ci sono inoltre

Distinguiamo i diversi termini semplici:

  • Atoms: pippo, pluto, topolino
  • Numbers: 12, -34, 345.01, 3.1415
  • Variables: iniziano con la lettera maiuscola o con l’underscore, ad esempio X, Y, Who, _variabile

Nota bene: l’utilizzo dell’underscore _ viene usato per indicare tale variabile come don’t-care, quando non è importante il valore che tale variabile assume.

La tecnica del backtracking

Un aspetto del Prolog è la sua capacità di esplorare tutte le possibili soluzioni tramite il meccanismo del backtracking. Se una query ha più soluzioni possibili, il sistema Prolog può restituire tutte le soluzioni rilevanti controllando in maniera iterativa tutte le possibili coppie che potrebbero risolvere la query posta.

Questa tecnica equivale ad effettuare una ricerca depth first nell’insieme delle soluzioni.

Le variabili

Consideriamo il seguente codice

Interrogando la knowledge base

?-  grampa(tommaso, Who)\text{?-}\,\,\texttt{grampa(tommaso, Who)}

Il Prolog riconoscerà il termine Who come una variabile e, tramite la tecnica del backtracking andrà a cercare tutti i possibili valori per Who che sono collegati con tommaso.

Il comando cut (!)

Quando il linguaggio Prolog incontra l’operatore ! (cut), viene effettuata un’esclusione di tutte le possibili alternative per quel punto nel programma. Questo significa che, una volta raggiunto il punto di taglio, il Prolog non proverà più a cercare altre soluzioni per quel particolare frammento di codice.

Esempio: ipotizziamo di avere il seguente codice in Prolog

Il comando

teaches(dr_fred, Course), !, studies(Student, Course).\texttt{teaches(dr\textunderscore fred, Course), !, studies(Student, Course).}

Restituirà i valori

Course = history,Student = alice\text{Course = history,\quad Student = alice}

Infatti l’esecuzione partirà da teaches(dr_fred, history) e si andrà a cercare se ci sono studenti che hanno lo stesso corso di dr_fred, ovvero history. Appena viene trovata alice l’istruzione ! fa terminare la query.

Se invece di avere la knowledge base appena usata si avesse la seguente

Lo stesso comando restituirebbe semplicemente il valore False\text{False}, infatti, al causa del cut, non si sarebbe andati a cercare oltre la prima condizione non soddisfatta nella knowledge base (seguendo l’ordine di scrittura delle righe di codice).

Dopo la prima condizione non soddisfatta il programma infatti non cerca ulteriori match.

Nota bene: il cut in questo caso è stato inserito tra le due condizioni, quindi l’ordine di lettura delle istruzioni sarà il seguente

(1) teaches(dr_fred, Course), (2) !,(3) studies(Student, Course).\texttt{(1) teaches(dr\textunderscore fred, Course), (2) !,(3) studies(Student, Course).}

Poiché la condizione (2)\texttt{(2)} viene controllata prima della (3)\texttt{(3)}, la riga di codice termina dopo la prima condizione non soddisfatta.

Se l’ordine di esecuzione fosse invece stato il seguente

(1) teaches(dr_fred, Course), (2) studies(Student, Course), (3) !.\texttt{(1) teaches(dr\textunderscore fred, Course), (2) studies(Student, Course), (3) !.}

Nelle prime due condizioni si sarebbe utilizzata la tecnica del backtracking per ottenere un match, dopodiché si sarebbe proceduti all’istruzione successiva (!\texttt{!}) che avrebbe fatto terminare la query. Il risultato ottenuto in questo caso sarebbe

Course = english,Student = alice()\tag{$\spades$}\text{Course = english,\quad Student = alice}

Infatti, dapprima vengono state testate tutte le coppie (studente, history)\texttt{(studente, history)}, per poi passare alla condizione successiva dettata da (dr_fred, course)\texttt{(dr\textunderscore fred, course)}, ovvero (dr_fred, english)\texttt{(dr\textunderscore fred, english)}, che viene soddisfatta proprio da ()(\spades).

L’operazione di unificazione

In Prolog, l’operatore = indica l’operazione di unificazione, ovvero il meccanismo che permette di effettuare una sostituzione per uguagliare due espressioni.

Per esempio, interrogando il motore del Prolog con le seguenti righe di codice, si ottengono le risposte riportate come risultato:

  • ?- tommaso = tommaso Risultato: true
  • ?- tommaso = X Risultato: X=tommaso
  • gampa(X, Y) = grampa(bianca, Z) (in riferimento al codice sopra) Risultato: X=bianca, Y=Z

La ricorsione

In Prolog, grazie al backtracking, si può facilmente programmare degli algoritmi ricorsivi. Per esempio, per il calcolo del fattoriale è sufficiente scrivere

Che possiamo interrogare nel seguente modo

?- factorial(6, Result)\texttt{?- factorial(6, Result)}

Per trovare il fattoriale di 6, ovvero 720.

Le liste

Una lista è una sequenza finita di elementi, per esempio

Sulle liste possiamo usare gli operatori

  • Lenght, per esempio
    • ?- lenght([a, b, c], 3) Risultato: true
    • ?- lenght([], 0) Risultato: true
    • ?- lenght([’pippo’, [a, b], 3]) Risultato: false
  • Append, per esempio
    • append([a, b], [1, 2, 3], X) Risultato: X=[a, b, 1, 2, 3]
    • append(X, [1, 2, 3], [a, b, 1, 2, 3]) Risultato: X=[a, b] false

Esiste inoltre l’operatore | che può essere utilizzato per decomporre una lista, ad esempio:

  • ?- [Head, Tail] = [antonio, [2, [a, b]], f(X), []].
    • Risultato: Head=antonio, Tail=[2, [a, b]], f(X), []]
  • ?- [One, Two, Remaining] = [antonio, [2, [b, c]], f(X), []].
    • Risultato: One=antonio, Remaining=[f(X), []], Two: [2, [b, c]]

L’operatore fail

Nelle istruzioni in Prolog si può utilizzare anche l’operatore fail, che fa fallire automaticamente tutte le condizioni successive ad essa. Tale operazione, seppur possa sembrare inutile, è in realtà utilizzata in Prolog grazie alla presenza del backtracking. Quando una condizione fallisce il Prolog inizia infatti a controllare le altre possibilità che possono soddisfare la query richiesta.

Un esempio di utilizzo del comando fail è riportato nel seguente codice, per indicare delle caratteristiche dei predicati penguin e ostrich:

Vari comandi Prolog (senza un particolare ordine)

  • ?-var(X). Risultato: true
  • ?-X=5, var(X). Risultato: false
  • ?-X=Y, var(X), var(Y). Risultato: X=Y
  • ?-nonvar(X). Risultato: false
  • ?-X=5, nonvar(X). Risultato: X=5
  • ?-X=Y, nonvar(X), nonvar(Y). Risultato: false
  • ?-integer(5). Risultato: true
  • ?-integer(5.0). Risultato: false
  • ?-X=10, integer(X). Risultato: X=10
  • ?-number(5). Risultato: true
  • ?-number(5.0). Risultato: true
  • ?-number(atom): Risultato: false
  • ?-X=10, number(X). Risultato: X=10
  • ?-X=abc, number(X). Risultato: false
  • ?-atom('hello'). Risultato: true
  • ?-atom(hello). Risultato: true
  • ?-atom('hello world')d Risultato: true
  • ?-atom('123'). Risultato: true
  • ?-atom(123). Risultato: false
  • ?-X=abc, atom(X). Risultato: X=abc
  • ?-X=123, atom(X). Risultato: false
  • ?-atomic(5). Risultato: true
  • ?-atomic(5.0). Risultato: true
  • ?-atomic(hello). Risultato: true
  • ?-X=10, atomic(X). Risultato: X=10
  • ?-X=abc, atomic(X). Risultato: X=abc

Se hai trovato errori o informazioni mancanti scrivi a:
giacomo.dandria@esercizistem.com

Se hai trovato errori o informazioni mancanti scrivi a:
giacomo.dandria@esercizistem.com

Questa pagina è stata utile?
No
Torna in alto