pyke推理引擎的一些注意事项

pyke是一个与prolog类似的纯python版本的推理引擎。这一类推理引擎比较适合用在一些需要处理大量基于规则来做判断或者决策的应用。规则成为了这类系统里面最重要的东西。有人说,什么东西是软件架构?最重要的东西就是你的软件架构!因此,在遇见这类由规则来主导整个应用的问题的时候,规则管理系统就变成了这个应用的架构。现实世界中很多问题都是这一类应用。因此,一些推理引擎就应运而生了。人们最早可能从80年代开始就有推理引擎的意识了。如果我们能够较好的应用推理引擎,就可以使我们能够脱身于编写繁杂的推理逻辑代码。例如对一系列数据的遍历,if-else判断,等等。有了基于规则而推理的引擎,我们就可以把重心放在想办法将已知条件抽象成事实,将逻辑推理抽象成规则的任务上。这就让我们可以放开推理部分的构建,能够

大幅度缩短开发周期。

我花了一些时间去阅读pyke的文档,从中基本理解了pyke的应用逻辑和语法。并开始尝试了自己使用pyke推理引擎来做一些实际上的小测试。下面陈列一些在这段时间内,我发现的需要特别注意的一些事项:

知识库文件名必须不同名(后缀名不算)

在pyke的框架下,初始化推理引擎的时候会指定一个目录。然后pyke会在那个目录下递归地寻找所有的*.kfb, *.krb和*.kqb文件,并把这些文件中记录的fact,rule和question都编译或者准备好。这些文件统称为pyke的知识库。并且pyke会以这些文件名(不包含后缀)为该知识库的名称。正因为如此,在pyke遍历的过程中如果遇见两个文件名相同的时候就会产生冲突。哪怕是后缀名不同都不行。例如base.kfb和base.krb同时存在是不允许的。

关于知识库实例的归属问题

在pyke的框架下每一个知识库实例都是属于某个知识库之下的。它们具有通用的从属关系。这一点在不同类型的知识库的体现方式有所不一样。

在.kfb中的每个事实实例都是属于与该.kfb文件名对应的那个知识库下的。例如base.kfb中的所有实例都是属于 base 名下的。我们假设 base.kfb 中有一条fact是sonOf(david, jim),那么在整个框架下定位这一条fact时,则需要用base.sonOf来指定。要注意的是,在base.kfb文件中,并没有显示的指明sonOf是属于base知识库的。

在.krb中的规则实例用来表述与知识库的从属关系时又不一样。在正向推理的规则中都要写明每一个知识库实例所属的知识库。例如:

son_of
    foreach
        family.son_of($child, $father, $mother)
    assert
        family.child_parent($child, $father, father, son)
        family.child_parent($child, $mother, mother, son)

在这段规则中,每一条前提和结论都显式的写名了其所属的知识库为family。

但是在逆向推理的规则中,我们在use声明中省去知识库的标识符。并且在when中也可以选择性的缺省知识库的标识符。例如:

parent_and_child
    use child_parent($child, $parent, (), $parent_type, $child_type)
    when
        child_parent($child, $parent, $parent_type, $child_type)

这一个反向推理的规则中,use下的child_parent没有像前面正向推理一样写明知识库。而且在use下是必须省略的。省略掉它,是因为反向推理规则都有一个默认的知识库,那就是这个规则库的基本规则类类名所对应的知识库。我们假设这个规则库文件名是myRule.krb,而它是继承自fatherRule.krb,那么这里所缺省的知识库名就是fatherRule。也就是说,如果把这个示例中的use写全,那么应该就是

use fatherRule.child_parent($child, ...)

但pyke规定了,这种情况下必须缺省知识库。然后在when的声明中,每个规则实例是可以指定知识库名也可以不指定。在指定的情况下,其默认知识库名的方法与use相同。

发表评论

邮箱地址不会被公开。 必填项已用*标注