我想检查一个任意事实,如果它在知识库中,则执行某些操作,如果不是,则执行其他操作,但不使用( 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 ).
答案 0 :(得分:2)
不是答案,但评论时间太长。
"流量控制"根据定义,不是声明性的。在运行时更改谓词数据库(定义的规则和事实)也不是声明性的:它会向您的程序引入状态。
你应该非常仔细地考虑你的数据"属于数据库,或者如果您可以保留数据结构。但是你的问题并没有提供足够的细节来提出任何建议。
但您可以看到this example of finding paths through a maze。在此解决方案中,数据库包含有关不会更改的问题的信息。搜索本身使用最简单的数据结构,即列表。 "流量控制"如果你想调用它,这是隐含的:它只是Prolog寻找证据的副作用。更重要的是,你可以在不考虑确切的控制流程的情况下争论该程序及其功能(但你确实考虑了Prolog的解决策略)。
答案 1 :(得分:1)
此要求的根本问题在于非单调:
在添加这样的事实后,持有而这个事实的事情可能会突然失败。
这本质上与单调性的重要和理想的陈述性特征背道而驰。
声明地说,通过添加事实,我们希望最多获得增加,而不是减少持有的东西。
出于这个原因,您的要求本质上与非单调结构相关联,例如if-then-else,!/0
和setof/3
。
推理这种方法的理由是完全避免检查知识库的属性。相反,要专注于对持有的事物的清晰描述,使用Prolog子句对知识进行编码。
在您的情况下,您似乎需要推断某些搜索问题的状态。解决此类任务的一种声明方式是将州表示为Prolog术语,并编写涉及国家的纯粹单调规则。
例如,如果我们探索之前未探索过的某个位置S0
,请说明州S
与州Pos
相关:
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术语的显式关系。纯粹,单调,并在各个方向工作。