📜  带Python的AI –逻辑编程

📅  最后修改于: 2020-12-11 05:34:53             🧑  作者: Mango


在本章中,我们将重点介绍逻辑编程及其在人工智能中的帮助。

我们已经知道,逻辑是对正确推理原理的研究,或者简单来说就是对之后发生的事情的研究。例如,如果两个语句为真,那么我们可以从中推断出任何第三条语句。

概念

逻辑编程是逻辑和编程这两个词的结合。逻辑编程是一种编程范例,其中问题通过程序语句在形式逻辑系统中表示为事实和规则。就像其他面向对象的,函数式的,声明式的和过程式的编程范例一样,它也是一种进行编程的特殊方式。

如何解决逻辑编程问题

逻辑编程使用事实和规则来解决问题。这就是为什么它们被称为逻辑编程的基础。需要为逻辑编程中的每个程序指定一个目标。要了解如何在逻辑编程中解决问题,我们需要了解构件-事实和规则-

事实

实际上,每个逻辑程序都需要处理事实,以便可以实现给定的目标。事实基本上是关于程序和数据的真实陈述。例如,德里是印度的首都。

规则

实际上,规则是使我们能够对问题领域做出结论的约束条件。规则基本上写成逻辑从句来表达各种事实。例如,如果我们要开发任何游戏,那么必须定义所有规则。

规则对于解决逻辑编程中的任何问题非常重要。规则基本上是可以表达事实的逻辑结论。以下是规则的语法-

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是Y,则X是Z的祖先。 Y的父亲,Y是Z的祖先。

安装有用的软件包

为了在Python启动逻辑编程,我们需要安装以下两个软件包-

康仁

它为我们提供了一种简化为业务逻辑编写代码的方式。它使我们可以根据规则和事实来表达逻辑。以下命令将帮助您安装kanren-

pip install kanren

象征

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

第一个输出代表ab的值。第一个表达式匹配原始模式并返回ab的值,但是第二个表达式不匹配原始模式,因此未返回任何内容。

检查素数

借助逻辑编程,我们可以从数字列表中找到素数,还可以生成素数。下面给出的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难题,Zebra难题,Sudoku,N-queen等。这里我们以Zebra难题的变体示例为例-

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.

我们正在借助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.