Using clpfd ...
:- use_module(library(clpfd)).
..., meta-predicate maplist/2
, and nth0/3
we define:
zs_maximum_at(Zs,Max,Pos) :-
maplist(#>=(Max),Zs),
nth0(Pos,Zs,Max).
Here's the query the OP gave:
?- zs_maximum_at([2,3,4],M,I).
I = 2, M = 4.
OK! ... how about the most general query?
?- 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
...
Edit: What about arithmetic expressions?
We can allow the use of arithmetic expressions by adding an additional goal (#=)/2
:
zs_maximum_at(Zs,Expr,Pos) :-
maplist(#>=(Max),Zs),
nth0(Pos,Zs,Expr),
Expr #= Max.
Now we can run queries like the following one—but lose monotonicity (cf. this clpfd manual)!
?- zs_maximum_at([0+1,1+1,2-0,3-1,1+0],M,I).
I = 1, M = 1+1
; I = 2, M = 2-0
; I = 3, M = 3-1
; false.
To disable arithmetic expressions we can use length/2
in combination with ins/2
:
zs_maximum_at(Zs,Max,Pos) :-
length(Zs,_),
Zs ins inf..sup,
maplist(#>=(Max),Zs),
nth0(Pos,Zs,Max).
Running above query again, we now get:
?- zs_maximum_at([0+1,1+1,2-0,3-1,1+0],M,I).
ERROR: Type error: `integer' expected, found `0+1' (a compound)
Note that the issue (of allowing arithmetic expressions or not) is not limited to clpfd.
It is also present when using plain-old Prolog arithmetic predicates like is/2
and friends.