Prolog min_成员的反直觉行为/2

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是标准术语顺序中的最小成员时为True。如果列表为空,则失败

?- 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.2
arg/3
(3)或8.2.1
(=)/2
(2)或(1)

8.5.4 1
复制条款/2
(2), , , , 8.10.1
findall/3
(3), 8.10.2
bagof/3
(3), 8.10.3
setof/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.