人工智能逻辑编程(python)

在本章中,我们将重点介绍逻辑编程以及它在人工智能中的作用。

我们已经知道逻辑是对正确推理原则的研究,或者简单地说就是研究什么是什么。 例如,如果两个陈述是真的,那么我们可以从中推断出任何第三个陈述。

概念
逻辑编程是两个字,逻辑和编程的组合。 逻辑编程是一种编程模式,其中问题通过程序语句表达为事实和规则,但在形式逻辑系统中。 就像面向对象,函数式,声明式和程序式等其他编程模式一样,它也是编程方法的一种特殊方式。

如何用逻辑编程解决问题

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

事实
实际上,每个逻辑程序都需要事实来处理,以达到既定目标。 事实上基本上是关于计划和数据的真实陈述。 例如,北京是中国的首都。

规则
实际上,规则是允许我们对问题域做出结论的约束条件。 规则基本上写成逻辑条款来表达各种事实。 例如,如果构建游戏,那么必须定义所有规则。

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

1
A∶− B1,B2,...,Bn.

在这里,A是头部,B1,B2,… Bn是主体。

例如 - ancestor(X,Y): - father(X,Y)

ancestor(X,Z): - father(X,Y),ancestor(Y,Z)

对于每一个XY,如果XY的父亲,YZ的祖先,那么XZ的祖先。对于每个XYXZ的祖先,如果XYY的父亲是Z的祖先。

安装必需的包

为了在Python中开始逻辑编程,需要安装以下两个包 -

Kanren
它为我们提供了一种简化业务逻辑编写代码的方式。 它让我们用规则和事实来表达逻辑。 以下命令来安装kanren -

1
pip install kanren

SymPy
SymPy是符号数学的Python库。 它旨在成为一个全功能的计算机代数系统(CAS),同时保持代码尽可能简单,以便易于理解和扩展。 以下命令是用来安装SymPy -

1
pip install sympy

逻辑编程的例子

以下是一些可以通过逻辑编程解决的例子 -

匹配数学表达式

实际上,我们可以通过使用逻辑编程以非常有效的方式找到未知值。 以下Python代码用于匹配数学表达式 -

考虑先导入下列软件包 -

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

需要定义要使用的数学运算 -

1
2
add = 'add'
mul = 'mul'

加法和乘法都是交互进程。 因此,我们需要指定它,这可以按照以下方式完成 -

1
2
3
4
fact(commutative, mul)
fact(commutative, add)
fact(associative, mul)
fact(associative, add)

定义变量是强制性的; 这可以如下完成 -

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

需要将表达式与原始模式相匹配。有以下原始模式,基础是(5 + a)* b-

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

有以下两个表达式来匹配原始模式 -

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

输出可以使用以下命令打印 -

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

运行此代码后,将得到以下输出 -

1
2
((3,2))
()

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

查找素数

在逻辑编程的帮助下,可以从数字列表中出素数,也可以生成素数。 下面给出的Python代码将从数字列表中找到素数,并且还会生成前10个素数。

首先导入以下软件包 -

1
2
3
4
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的函数,它将根据给定的数字检查素数作为数据。

1
2
3
4
5
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

现在,声明一个变量 -

1
2
3
4
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))))

上述代码的输出如下 -

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

解决难题

参考 :http://www.zyiz.net/tutorial/detail-7864.html
 

逻辑编程可用于解决许多问题,如8拼图,斑马拼图,数独,N皇后等。在这里,举例说明斑马拼图的变体如下 -

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
有五间房子。
英国人住在红房子里。
瑞典人有一只狗。
丹麦人喝茶。
绿房子在白房子的左边。
他们在绿房子里喝咖啡。
吸Pall Mall的人有鸟。
吸Dunhill在的人黄色房子里。
在中间的房子里,他们喝牛奶。
挪威人住在第一宫。
那个抽Blend的男人住在猫屋旁边的房子里。
在他们有一匹马的房子旁边的房子里,他们吸Dunhill烟。
抽Blue Master的人喝啤酒。
德国人吸Prince烟。
挪威人住在蓝房子旁边。
他们在房子旁边的房子里喝水,在那里吸Blend烟。

在Python的帮助下解决谁有斑马的问题。
导入必要的软件包 -

1
2
3
from kanren import *
from kanren.core import lall
import time

现在,我们需要定义两个函数 - left()next()来查找哪个房屋左边或接近谁的房子 -

1
2
3
4
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,如下 -

1
houses = var()

需要在lall包的帮助下定义规则如下。

5间房子 -

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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)
)

现在,用前面的约束运行解算器 -

1
solutions = run(0, houses, rules_zebraproblem)

借助以下代码,可以提取解算器的输出 -

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

以下代码将打印解决方案 -

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

上述代码的输出如下 -

1
German owns zebra.
 
posted @ 2021-05-30 18:56  沐雪架构师  阅读(3641)  评论(0编辑  收藏  举报