使用clpfd ...
:- use_module(library(clpfd)).
...、meta-predicate maplist/2 和 nth0/3 我们定义:
zs_maximum_at(Zs,Max,Pos) :-
maplist(#>=(Max),Zs),
nth0(Pos,Zs,Max).
这是 OP 给出的查询:
?- zs_maximum_at([2,3,4],M,I).
I = 2, M = 4.
好的! ...最一般的查询怎么样?
?- zs_maximum_at(Zs,M,I).
Zs = [M], I = 0, M in inf..sup
; Zs = [ M,_B], I = 0, M #>= _B
; Zs = [_A, M], I = 1, M #>= _A
; Zs = [ M,_B,_C], I = 0, M #>= _B, M #>= _C
; Zs = [_A, M,_C], I = 1, M #>= _A, M #>= _C
; Zs = [_A,_B, M], I = 2, M #>= _A, M #>= _B
; Zs = [ M,_B,_C,_D], I = 0, M #>= _B, M #>= _C, M #>= _D
; Zs = [_A, M,_C,_D], I = 1, M #>= _A, M #>= _C, M #>= _D
...
编辑:算术表达式怎么样?
-
我们可以允许通过添加一个额外的目标(#=)/2来使用算术表达式:
zs_maximum_at(Zs,Expr,Pos) :-
地图列表(#>=(最大),Zs),
nth0(Pos,Zs,Expr),
经验 #= 最大。
现在我们可以运行如下查询,但会失去单调性(参见this clpfd manual)!
?- zs_maximum_at([0+1,1+1,2-0,3-1,1+0],M,I)。
我 = 1, M = 1+1
;我 = 2, M = 2-0
;我 = 3, M = 3-1
;错误的。
-
要禁用算术表达式,我们可以将length/2 与ins/2 结合使用:
zs_maximum_at(Zs,Max,Pos) :-
长度(Zs,_),
Zs ins inf..sup,
地图列表(#>=(最大),Zs),
nth0(Pos,Zs,Max)。
再次运行上面的查询,我们现在得到:
?- zs_maximum_at([0+1,1+1,2-0,3-1,1+0],M,I)。
错误:类型错误:预期为“整数”,发现“0+1”(复合)
请注意,问题(是否允许算术表达式)不仅限于 clpfd。
在使用普通的 Prolog 算术谓词(如 is/2 和朋友)时也会出现此问题。