2

我想检查一个任意事实,如果它在知识库中,则做一些事情,如果不在,但没有( I -> T ; E)语法。

我的知识库中有一些事实:

unexplored(1,1).
unexplored(2,1).
safe(1,1).

给定一个不完整的规则

foo:- safe(A,B),
% do something if unexplored(A,B) is in the knowledge base
% do something else if unexplored(A,B) is not in the knowledge base

不这样做的正确方法是什么?

foo:-
   safe(A,B),
   ( unexplored(A,B) -> something ; something_else ).
4

2 回答 2

2

不是答案,但评论太长了。

根据定义,“流控制”不是声明性的。在运行时更改谓词数据库(定义的规则和事实)也不是声明性的:它将状态引入您的程序。

您应该非常仔细地考虑您的“数据”是否属于数据库,或者您是否可以将其保留为数据结构。但是您的问题没有提供足够的细节来提出任何建议。

但是,您可以看到这个通过迷宫寻找路径的示例。在此解决方案中,数据库包含有关未更改问题的信息。搜索本身使用最简单的数据结构,一个列表。如果你想称之为“流控制”,这是隐含的:它只是 Prolog 寻找证明的副作用。更重要的是,您可以在不考虑确切控制流的情况下争论程序及其作用(但您确实考虑了 Prolog 的解析策略)。

于 2016-03-19T07:08:35.530 回答
1

这个要求的根本问题是它是非单调的

没有这个事实成立的事情可能会在添加这样一个事实后突然成立。

这本质上与单调性的重要且理想的声明性属性背道而驰。

声明式地,通过添加事实,我们期望最多获得增加,而不是减少所持有的事物。

出于这个原因,您的要求与 if-then-else!/0setof/3.

对此进行推理的一种声明方式是完全避免检查知识库的属性。相反,专注于对所持有事物的清晰描述,使用 Prolog 子句对知识进行编码。

在您的情况下,您似乎需要对某些搜索问题的状态进行推理。解决此类任务的一种声明方式是将状态表示为 Prolog 项,并编写涉及状态的纯单调规则。

例如,如果我们探索以前没有探索过的某个位置,假设一个状态S0与状态相关:SPos

state0_state(S0, S) :-
    select(Pos-unexplored, S0, S1),
    S = [Pos-explored|S1].

或更短:

state0_state(S0, [Pos-explored|S1) :-
    select(Pos-unexplored, S0, S1).

我把找出我在这里使用的状态表示作为一个简单的练习。请注意使用S0, S1, ...S来链接不同状态的方便命名约定。

这样,您可以对表示状态的 Prolog 术语的显式关系进行编码。纯净,单调,全方位工作。

于 2016-03-19T07:04:47.507 回答