prolog - Prolog中处理“剩余目标”的方法是什么?
问题描述
以这个程序为例。它使用延迟的目标
room(green).
room(blue).
room(red).
room(white).
location(jimmy,red).
location(ricky,blue).
location(cindy,green).
% "Is a certain room unoccupied?"
not_occupied(Room) :-
nonvar(Room),
assertion(room(Room)),
\+ location(_Person,Room).
% If no specific "Room" has been given, the negated goal is
% delayed until the "Room" has been instantiated.
not_occupied(Room) :-
var(Room),
!,
when(
ground(Room),
(\+ location(_Person,Room))
).
如果我现在问
?- not_occupied(R).
然后 Prolog 成功并输出一个残差目标
?- not_occupied(R).
when(ground(R),\+location(_7676,R)).
实际上,它并没有真正成功。它乐观地成功(因为为了不停止计算,它必须成功)但实际的逻辑成功取决于剩余目标的实际成功。
如何以编程方式确定子目标是否成功实现了剩余目标?(那我该怎么办?)方法是什么?
附言
拥有第二个 Prolog 真值可能是一个很好的 Prolog 扩展,因为 atrue+
表示“在剩余目标成功的条件下成功”。这实际上似乎是有必要的:
在 SWI-Prolog 中,采用这个固有的模棱两可的目标:
do :- not_occupied(_).
调用它甚至根本不会打印出任何剩余目标:
?- do.
true.
目标成功了吗?不是真的,它仍然处于逻辑边缘,但顶层甚至没有告诉我。另一方面,没有办法向程序提供更多信息来解决剩余目标。但是因为计算运行到终点而默认为“成功”感觉是错误的。
解决方案
首先是一些术语问题。我们从顶层得到的是一个答案。说:
?- length(Xs, 0).
Xs = [].
在这里,答案是描述单个解决方案的答案替换形式。
?- length(Xs, 1).
Xs = [_A].
同样,这是一个答案替换,但这次它描述了无限多的解决方案。
通常答案和解决方案的概念可以互换使用,但是一旦我们使用延迟的目标或约束,我们就需要明确区分。现在的新功能是答案可能包含任意数量的解决方案,甚至根本没有。
?- freeze(X, false).
freeze(X,false). % no solution
?- freeze(X, ( X = 1 ; X = 2 ) ).
freeze(X,(X=1;X=2)). % two solutions
一些实现frozen(Var, Goal)
只提供与Var
. call_residue(Goal_0, Residuum)
在这种情况下,构想了内置。最初,在 SICStus 0.7 中,它是为延迟目标定义的,剩余的定义非常明确。然而,一旦我们将我们的语言扩展到 clpfd,事情就变得不那么清楚了。这是 SICStus 3.12.5:
| ?- X in 1..3, call_residue(X in 2..4, Residuum).
Residuum = [[X]-(X in 2..3),
X in 1..3 ?
残渣现在应该是X in 2..3
还是X in \{1}
?事情可能变得相当复杂(阅读:越野车)。此外,撤消绑定是一项艰巨的任务。或实现首先创建整个目标的副本,然后保留约束。
SICStus 4 被call_residue/2
两个新的内置插件所取代。与与在 中创建的延迟目标或约束相关的变量call_residue_vars(Goal_0, Vars)
统一。请注意,当某些约束变量存在于. 但主要的一点是,这个内置的实现起来相对便宜。它不复制或其任何子项。Vars
Goal_0
Goal_0
Goal_0
Goal_0
另一个copy_term(Term, Copy, G_0s)
可用于通过调用maplist(call, G_0s)
(在 SWI、Scryer 中)或call(G_0)
(在 SICStus 中)来重建附加的约束。在 SWI (clpfd) 和 Scryer (clpz) 的实现中,V in inf..sup
投影省略了形式的一些冗余约束。但投影确实是另一个问题。
推荐阅读
- flutter - 在颤振插件中获取活动参考
- deeplearning4j - DL4j 1.0.0-Beta6 Openblas 不使用多个线程
- c++ - std::set 如何保证恒定时间最小/最大元素访问?
- r - 如何使用 for 循环在 [r] 中加载多个栅格?
- r - 在 htmltools::div 元素中插入带有 !important 的变量的样式标签
- c++ - 为什么我的 SDL 程序在 ig11icd64.dll 中崩溃?
- python - 0 和 1 的 2D numpy 数组 - 单元格为 1 也将周围的 12x12 单元格设置为 1
- javascript - 如何将 JSON 从本地网站发送到 AWS IoT?
- matlab - 在 MacOS 的 Mex 文件中使用 OpenMP
- javascript - 动态生成的表格即使被清除也会不断增加