AI con Python - Programmazione logica

In questo capitolo, ci concentreremo sulla programmazione logica e su come aiuta nell'intelligenza artificiale.

Sappiamo già che la logica è lo studio dei principi del corretto ragionamento o in parole semplici è lo studio di ciò che viene dopo cosa. Ad esempio, se due affermazioni sono vere, possiamo dedurre una terza affermazione da essa.

Concetto

La programmazione logica è la combinazione di due parole, logica e programmazione. La programmazione logica è un paradigma di programmazione in cui i problemi sono espressi come fatti e regole da dichiarazioni di programma ma all'interno di un sistema di logica formale. Proprio come altri paradigmi di programmazione come orientato agli oggetti, funzionale, dichiarativo e procedurale, ecc., È anche un modo particolare di avvicinarsi alla programmazione.

Come risolvere i problemi con la programmazione logica

La programmazione logica utilizza fatti e regole per risolvere il problema. Questo è il motivo per cui sono chiamati gli elementi costitutivi della programmazione logica. È necessario specificare un obiettivo per ogni programma nella programmazione logica. Per capire come risolvere un problema nella programmazione logica, abbiamo bisogno di conoscere gli elementi costitutivi - Fatti e regole -

Fatti

In realtà, ogni programma di logica necessita di fatti su cui lavorare in modo che possa raggiungere l'obiettivo dato. I fatti fondamentalmente sono affermazioni vere sul programma e sui dati. Ad esempio, Delhi è la capitale dell'India.

Regole

In realtà, le regole sono i vincoli che ci consentono di trarre conclusioni sul dominio del problema. Regole fondamentalmente scritte come clausole logiche per esprimere vari fatti. Ad esempio, se stiamo costruendo un gioco, tutte le regole devono essere definite.

Le regole sono molto importanti per risolvere qualsiasi problema nella programmazione logica. Le regole sono fondamentalmente una conclusione logica che può esprimere i fatti. La seguente è la sintassi della regola:

A∶− B1, B2, ..., B n .

Qui, A è la testa e B1, B2, ... Bn è il corpo.

Ad esempio - antenato (X, Y): - padre (X, Y).

antenato (X, Z): - padre (X, Y), antenato (Y, Z).

Questo può essere letto come, per ogni X e Y, se X è il padre di Y e Y è un antenato di Z, X è l'antenato di Z. Per ogni X e Y, X è l'antenato di Z, se X è il padre di Y e Y è un antenato di Z.

Installazione di pacchetti utili

Per avviare la programmazione logica in Python, dobbiamo installare i seguenti due pacchetti:

Kanren

Ci fornisce un modo per semplificare il modo in cui abbiamo creato il codice per la logica aziendale. Ci consente di esprimere la logica in termini di regole e fatti. Il seguente comando ti aiuterà a installare kanren -

pip install kanren

SymPy

SymPy è una libreria Python per la matematica simbolica. Mira a diventare un sistema completo di computer algebra (CAS) mantenendo il codice il più semplice possibile per essere comprensibile e facilmente estendibile. Il seguente comando ti aiuterà a installare SymPy -

pip install sympy

Esempi di programmazione logica

Di seguito sono riportati alcuni esempi che possono essere risolti con la programmazione logica:

Corrispondenza di espressioni matematiche

In realtà possiamo trovare i valori sconosciuti utilizzando la programmazione logica in modo molto efficace. Il seguente codice Python ti aiuterà ad abbinare un'espressione matematica:

Considera prima l'importazione dei seguenti pacchetti:

from kanren import run, var, fact
from kanren.assoccomm import eq_assoccomm as eq
from kanren.assoccomm import commutative, associative

Dobbiamo definire le operazioni matematiche che useremo -

add = 'add'
mul = 'mul'

Sia l'addizione che la moltiplicazione sono processi comunicativi. Quindi, dobbiamo specificarlo e questo può essere fatto come segue:

fact(commutative, mul)
fact(commutative, add)
fact(associative, mul)
fact(associative, add)

È obbligatorio definire le variabili; questo può essere fatto come segue:

a, b = var('a'), var('b')

Dobbiamo far corrispondere l'espressione con il modello originale. Abbiamo il seguente modello originale, che è fondamentalmente (5 + a) * b -

Original_pattern = (mul, (add, 5, a), b)

Abbiamo le seguenti due espressioni da abbinare al modello originale:

exp1 = (mul, 2, (add, 3, 1))
exp2 = (add,5,(mul,8,1))

L'output può essere stampato con il seguente comando:

print(run(0, (a,b), eq(original_pattern, exp1)))
print(run(0, (a,b), eq(original_pattern, exp2)))

Dopo aver eseguito questo codice, otterremo il seguente output:

((3,2))
()

Il primo output rappresenta i valori per a e b. La prima espressione corrispondeva al modello originale e restituiva i valori pera e b ma la seconda espressione non corrispondeva al modello originale, quindi non è stato restituito nulla.

Controllo dei numeri primi

Con l'aiuto della programmazione logica, possiamo trovare i numeri primi da un elenco di numeri e possiamo anche generare numeri primi. Il codice Python fornito di seguito troverà il numero primo da un elenco di numeri e genererà anche i primi 10 numeri primi.

Consideriamo prima l'importazione dei seguenti pacchetti:

from kanren import isvar, run, membero
from kanren.core import success, fail, goaleval, condeseq, eq, var
from sympy.ntheory.generate import prime, isprime
import itertools as it

Ora definiremo una funzione chiamata prime_check che controllerà i numeri primi in base ai numeri dati come dati.

def prime_check(x):
if isvar(x):
   return condeseq([(eq,x,p)] for p in map(prime, it.count(1)))
else:
   return success if isprime(x) else fail

Ora, dobbiamo dichiarare una variabile che verrà utilizzata -

x = var()
print((set(run(0,x,(membero,x,(12,14,15,19,20,21,22,23,29,30,41,44,52,62,65,85)),
(prime_check,x)))))
print((run(10,x,prime_check(x))))

L'output del codice precedente sarà il seguente:

{19, 23, 29, 41}
(2, 3, 5, 7, 11, 13, 17, 19, 23, 29)

Risolvere enigmi

La programmazione logica può essere utilizzata per risolvere molti problemi come 8-puzzle, Zebra puzzle, Sudoku, N-queen, ecc. Qui stiamo prendendo un esempio di una variante di Zebra puzzle che è la seguente:

There are five houses.
The English man lives in the red house.
The Swede has a dog.
The Dane drinks tea.
The green house is immediately to the left of the white house.
They drink coffee in the green house.
The man who smokes Pall Mall has birds.
In the yellow house they smoke Dunhill.
In the middle house they drink milk.
The Norwegian lives in the first house.
The man who smokes Blend lives in the house next to the house with cats.
In a house next to the house where they have a horse, they smoke Dunhill.
The man who smokes Blue Master drinks beer.
The German smokes Prince.
The Norwegian lives next to the blue house.
They drink water in a house next to the house where they smoke Blend.

Lo stiamo risolvendo per la domanda who owns zebra con l'aiuto di Python.

Importiamo i pacchetti necessari -

from kanren import *
from kanren.core import lall
import time

Ora, dobbiamo definire due funzioni: left() e next() per controllare di chi è rimasta la casa o accanto alla casa di chi -

def left(q, p, list):
   return membero((q,p), zip(list, list[1:]))
def next(q, p, list):
   return conde([left(q, p, list)], [left(p, q, list)])

Ora, dichiareremo una casa variabile come segue:

houses = var()

Abbiamo bisogno di definire le regole con l'aiuto del pacchetto lall come segue.

Ci sono 5 case -

rules_zebraproblem = lall(
   (eq, (var(), var(), var(), var(), var()), houses),

   (membero,('Englishman', var(), var(), var(), 'red'), houses),
   (membero,('Swede', var(), var(), 'dog', var()), houses),
   (membero,('Dane', var(), 'tea', var(), var()), houses),
   (left,(var(), var(), var(), var(), 'green'),
   (var(), var(), var(), var(), 'white'), houses),
   (membero,(var(), var(), 'coffee', var(), 'green'), houses),
   (membero,(var(), 'Pall Mall', var(), 'birds', var()), houses),
   (membero,(var(), 'Dunhill', var(), var(), 'yellow'), houses),
   (eq,(var(), var(), (var(), var(), 'milk', var(), var()), var(), var()), houses),
   (eq,(('Norwegian', var(), var(), var(), var()), var(), var(), var(), var()), houses),
   (next,(var(), 'Blend', var(), var(), var()),
   (var(), var(), var(), 'cats', var()), houses),
   (next,(var(), 'Dunhill', var(), var(), var()),
   (var(), var(), var(), 'horse', var()), houses),
   (membero,(var(), 'Blue Master', 'beer', var(), var()), houses),
   (membero,('German', 'Prince', var(), var(), var()), houses),
   (next,('Norwegian', var(), var(), var(), var()),
   (var(), var(), var(), var(), 'blue'), houses),
   (next,(var(), 'Blend', var(), var(), var()),
   (var(), var(), 'water', var(), var()), houses),
   (membero,(var(), var(), var(), 'zebra', var()), houses)
)

Ora, esegui il risolutore con i vincoli precedenti -

solutions = run(0, houses, rules_zebraproblem)

Con l'aiuto del seguente codice, possiamo estrarre l'output dal risolutore:

output_zebra = [house for house in solutions[0] if 'zebra' in house][0][0]

Il codice seguente aiuterà a stampare la soluzione:

print ('\n'+ output_zebra + 'owns zebra.')

L'output del codice precedente sarebbe il seguente:

German owns zebra.