人工智能逻辑编程(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.
 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM