Prolog min_成员的反直觉行为/2
当Min是标准术语顺序中的最小成员时为True。如果列表为空,则失败Prolog min_成员的反直觉行为/2,prolog,min,clpfd,Prolog,Min,Clpfd,当Min是标准术语顺序中的最小成员时为True。如果列表为空,则失败 ?- min_member(3, [1,2,X]). X = 3. 当然,解释是,在标准术语顺序中,变量排在所有其他术语之前,并且使用统一。然而,所报道的解决方案似乎有点错误 这怎么可能是合理的呢?我应该如何解释这个解决方案 编辑: 防止min_member/2成功使用此解决方案的一种方法是更改标准库(SWI Prolog),如下所示: xmin_member(Min, [H|T]) :- xmin_member_(
?- min_member(3, [1,2,X]).
X = 3.
当然,解释是,在标准术语顺序中,变量排在所有其他术语之前,并且使用统一。然而,所报道的解决方案似乎有点错误
这怎么可能是合理的呢?我应该如何解释这个解决方案
编辑:
防止min_member/2
成功使用此解决方案的一种方法是更改标准库(SWI Prolog),如下所示:
xmin_member(Min, [H|T]) :-
xmin_member_(T, H, Min).
xmin_member_([], Min0, Min) :-
( var(Min0), nonvar(Min)
-> fail
; Min = Min0
).
xmin_member_([H|T], Min0, Min) :-
( H @>= Min0
-> xmin_member_(T, Min0, Min)
; xmin_member_(T, H, Min)
).
失败而不是抛出实例化错误(如果我理解正确,@mat在他的回答中建议的)背后的基本原理是,这是一个明确的问题:
当X是自由变量时,3是[1,2,X]
的最小成员吗
答案是(至少对我来说)明确的“不”,而不是“我真的说不出来”
这与排序/2的行为类别相同:
?- sort([A,B,C], [3,1,2]).
A = 3,
B = 1,
C = 2.
同样的技巧也适用于:
?- min_member(3, [1,2,A,B]).
A = 3.
?- var(B), min_member(3, [1,2,A,B]).
B = 3.
这就是
minu member/2
的实现方式:
min_member(Min, [H|T]) :-
min_member_(T, H, Min).
min_member_([], Min, Min).
min_member_([H|T], Min0, Min) :-
( H @>= Min0
-> min_member_(T, Min0, Min)
; min_member_(T, H, Min)
).
因此,似乎
min_-member/2
实际上试图将min
(第一个参数)与列表中的最小元素按照标准术语顺序统一起来。显然min_-member/2
不是一个真正的关系:
?- min_member(X, [X,0]), X = 1.
X = 1.
然而,在通过(非常理想的)连接的交换性简单地交换两个目标之后,我们得到:
?- X = 1, min_member(X, [X,0]).
false.
正如你正确观察到的,这显然是相当糟糕的
约束是此类问题的声明性解决方案。对于整数,有限域约束是此类问题的完全声明性解决方案
在没有约束的情况下,当我们知道的太少而无法给出合理的答案时,最好抛出一个实例化错误。我对您的xmin_成员的实现有一个观察。此查询失败:
?- xmin_member(1, [X, 2, 3]).
false.
我试图将列表可能包含自由变量的情况包括在内。所以,我想到了这个:
ymin_member(Min, Lst):-
member(Min, Lst),
maplist(@=<(Min), Lst).
这是许多(all?)谓词的共同属性,它们依赖于术语的标准顺序,而两个术语之间的顺序在统一后可能会发生变化。基线是下面的连词,不能还原:
?- X @< 2, X = 3.
X = 3.
这些谓词仅在输入为地面时表示干净的关系。但是,要求输入是基础的要求太多了,因为它们可以有意义地与变量一起使用,只要用户知道他/她不应该进一步实例化任何有序术语。在这个意义上,我不同意@mat。我确实同意,约束肯定会使其中一些关系变得合理。造成混淆的实际原因是一般的Prolog代码。对于序言谓词的纯度或杂质,没有一种干净的、普遍接受的分类。在一本手册中,以及在标准中,纯内置和不纯内置是愉快地混合在一起的。由于这个原因,事情往往会变得混乱,谈论什么应该是这样,什么不应该是这样,往往会导致毫无结果的讨论
这怎么可能是合理的呢?我应该如何解释这个解决方案
首先,查看“模式声明”或“模式指示器”:
min\u成员(-min,+列表)
在SWI文档中,这描述了程序员如何使用该谓词。因此,第一个参数应该是未实例化的(并且可能在目标中也是未关联的),第二个参数应该实例化为某种类型的列表。对于所有其他用途,您都可以自己使用。系统假设您能够自己检查。你真的能做到吗?一、 就我而言,我在这方面遇到了不少困难。国际标准化组织(ISO)有一个
此外,对于未指明的情况,实施力求“合理”。特别是,它试图在第一个论点中保持坚定。因此,最小值首先独立于Min
的值进行计算。然后,结果值与Min
统一。这种对滥用的鲁棒性通常是有代价的。在这种情况下,minu member/2
始终必须访问整个列表。不管这是否有用。考虑
?- length(L, 1000000), maplist(=(1),L), min_member(2, L).
显然,2不是L
中的最小值。这可以通过只考虑列表的第一个元素来检测。由于定义的一般性,必须访问整个列表
这种处理输出统一的方法在标准中也有类似的处理。当(否则)声明性描述()显式引用统一时,您可以发现这些情况,如
8.5.4条款副本/2
8.5.4.1说明
copy_term(term_1,term_2)
在term_2
unifies
带有术语T
,该术语是
术语1
或
8.4.3分类/2
8.4.3.1说明
sort(List,Sorted)
为真,如果Sorted
与
列表的排序列表
(7.1.6.5)
以下是只能理解为输出参数的内置参数(括号中)。请注意,还有更多有效的输出参数,但在某些操作后不需要统一过程。想想8.5.2arg/3
(3)或8.2.1(=)/2
(2)或(1)
8.5.4 1复制条款/2
(2),
,
,
,
8.10.1findall/3
(3),
8.10.2bagof/3
(3),
8.10.3setof/3
(3)
关于你的直接问题,这里有一些更基本的问题:
定期订单
从历史上看,“标准”术语order1的定义允许对1982年前后的setof/3
和sort/2
进行定义。(在此之前,与1978年一样,DEC10手册《用户指南》中没有提及。)
从1982年开始,术语order经常(erm,ab-)用于实现其他命令,特别是因为DEC10没有直接提供高阶谓词<代码>呼叫/
?- sort([2,X], [3,2]).
X = 3.
?- length(L, 1000000), maplist(=(1),L), min_member(2, L).
?- min_member(=<, M, Ms).
?- min_member(X, [A, B]), A = 3, B = 2.
X = A, A = 3,
B = 2.
promise_relation(Rel_2, X, Y):-
call(Rel_2, X, Y),
when(ground(X), call(Rel_2, X, Y)),
when(ground(Y), call(Rel_2, X, Y)).
min_member_1(Min, Lst):-
member(Min, Lst),
maplist(promise_relation(@=<, Min), Lst).
?- min_member_1(X, L), L = [_,2,3,4], X = 1.
X = 1,
L = [1, 2, 3, 4] .
?- min_member_1(X, [A,B,C]), B is 3, C is 4, A is 1.
X = A, A = 1,
B = 3,
C = 4 ;
false.
?- min_member_1(X, [A,B,C]), A is 1, B is 3, C is 4.
false.
?- min_member_1(X, [A,B,C]), [A, B, C] = [1, 3, 4].
X = A, A = 1,
B = 3,
C = 4 ;
false.
promise_relation(Rel_2, X, Y):-
when((ground(X), ground(Y)), call(Rel_2, X, Y)).
?- L = [_, _, _, _], min_member_1(X, L), L = [3,4,1,2].
L = [3, 4, 1, 2],
X = 1 ;
false.