AI с Python - логическое программирование

В этой главе мы сосредоточимся на логическом программировании и на том, как оно помогает в искусственном интеллекте.

Мы уже знаем, что логика - это изучение принципов правильного рассуждения или, говоря простыми словами, это изучение того, что следует за чем. Например, если два утверждения верны, мы можем вывести из него любое третье утверждение.

Концепция

Логическое программирование - это сочетание двух слов, логики и программирования. Логическое программирование - это парадигма программирования, в которой проблемы выражаются в виде фактов и правил с помощью программных операторов, но в рамках системы формальной логики. Как и другие парадигмы программирования, такие как объектно-ориентированное, функциональное, декларативное, процедурное и т. Д., Это также особый подход к программированию.

Как решать проблемы с логическим программированием

Логическое программирование использует факты и правила для решения проблемы. Вот почему их называют строительными блоками логического программирования. Для каждой программы в логическом программировании необходимо указать цель. Чтобы понять, как проблема может быть решена в логическом программировании, нам нужно знать о строительных блоках - фактах и ​​правилах -

Факты

Фактически, каждой логической программе нужны факты, с которыми можно работать, чтобы достичь поставленной цели. Факты в основном являются правдивыми утверждениями о программе и данных. Например, Дели - столица Индии.

Правила

Фактически, правила - это ограничения, которые позволяют нам делать выводы о проблемной области. Правила в основном записываются в виде логических пунктов для выражения различных фактов. Например, если мы строим какую-то игру, тогда должны быть определены все правила.

Правила очень важны для решения любой проблемы в логическом программировании. Правила - это, по сути, логический вывод, который может выражать факты. Ниже приводится синтаксис правила -

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

Здесь A - голова, а B1, B2, ... Bn - тело.

Например - предок (X, Y): - отец (X, Y).

предок (X, Z): - отец (X, Y), предок (Y, Z).

Это можно читать так: для любых X и Y, если X является отцом Y, а Y является предком Z, X является предком Z. Для любых X и Y X является предком Z, если X является отец Y и Y является предком Z.

Установка полезных пакетов

Чтобы начать логическое программирование на Python, нам нужно установить следующие два пакета:

Канрен

Это дает нам возможность упростить создание кода для бизнес-логики. Это позволяет нам выразить логику в терминах правил и фактов. Следующая команда поможет вам установить канрен -

pip install kanren

SymPy

SymPy - это библиотека Python для символической математики. Он нацелен на то, чтобы стать полнофункциональной системой компьютерной алгебры (CAS), сохраняя при этом код как можно более простым, чтобы он был понятным и легко расширяемым. Следующая команда поможет вам установить SymPy -

pip install sympy

Примеры логического программирования

Ниже приведены некоторые примеры, которые можно решить с помощью логического программирования.

Соответствие математических выражений

На самом деле мы можем найти неизвестные значения, используя логическое программирование очень эффективным способом. Следующий код Python поможет вам сопоставить математическое выражение -

Сначала рассмотрите возможность импорта следующих пакетов -

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

Нам нужно определить математические операции, которые мы собираемся использовать -

add = 'add'
mul = 'mul'

И сложение, и умножение - коммуникативные процессы. Следовательно, нам нужно указать его, и это можно сделать следующим образом:

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

Определение переменных обязательно; это можно сделать следующим образом -

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

Нам нужно сопоставить выражение с исходным шаблоном. У нас есть следующий исходный шаблон, который в основном (5 + a) * b -

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

У нас есть следующие два выражения, чтобы соответствовать исходному шаблону -

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

Вывод можно распечатать с помощью следующей команды -

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

После запуска этого кода мы получим следующий вывод -

((3,2))
()

Первый вывод представляет значения для a а также b. Первое выражение соответствует исходному шаблону и возвращает значения дляa а также b но второе выражение не соответствует исходному шаблону, поэтому ничего не было возвращено.

Проверка простых чисел

С помощью логического программирования мы можем найти простые числа из списка чисел, а также можем генерировать простые числа. Приведенный ниже код Python найдет простое число из списка чисел, а также сгенерирует первые 10 простых чисел.

Давайте сначала рассмотрим импорт следующих пакетов -

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

Теперь мы определим функцию под названием prime_check, которая будет проверять простые числа на основе заданных чисел как данных.

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

Теперь нам нужно объявить переменную, которая будет использоваться -

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))))

Вывод приведенного выше кода будет следующим:

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

Решение головоломок

Логическое программирование может использоваться для решения многих задач, таких как 8-головоломки, головоломка с зеброй, судоку, N-королева и т. Д. Здесь мы берем пример варианта головоломки с зеброй, который выглядит следующим образом:

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.

Решаем для вопроса who owns zebra с помощью Python.

Импортируем необходимые пакеты -

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

Теперь нам нужно определить две функции - left() а также next() проверить чей дом остался или рядом чей дом -

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)])

Теперь мы объявим переменный дом следующим образом:

houses = var()

Нам нужно определить правила с помощью пакета lall следующим образом.

Всего 5 домов -

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)
)

Теперь запустите решатель с предыдущими ограничениями -

solutions = run(0, houses, rules_zebraproblem)

С помощью следующего кода мы можем извлечь вывод из решателя -

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

Следующий код поможет распечатать решение -

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

Вывод приведенного выше кода будет следующим:

German owns zebra.