-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
Description
argmax
has two meanings:
- (since Julia 1.0)
argmax(indexable)
returns the indexi
for whichindexable[i]
is maximum - (added in Add 2-arg versions of findmax/min, argmax/min #35316 and Julia 1.7):
argmax(f, itr)
returns thex∈itr
which achieves the maximum value off(x)
Both of these are useful and well-defined operations. But they should be considered with respect to Julia's overall consistency: it's worth asking how argmax(f, itr)
compares to other such functions that accept a "mapping" function f
as an input. For example, sum(f, itr)
computes sum(f(x) for x in itr)
, maximum(f, itr)
computes maximum(f(x) for x in itr)
, and so on. One simple consequence is that these functions have a very natural property: sum(identity, itr) == sum(itr)
.
So, is argmax(identity, a) == argmax(a)
?
julia> argmax(identity, [10, 30, 20])
30
julia> argmax([10, 30, 20])
2
Nope. How about "is argmax(f, itr)
equivalent to argmax(f(x) for x in itr)
"?
julia> a = [1, 5, NaN, 3]
4-element Vector{Float64}:
1.0
5.0
NaN
3.0
julia> f(x) = isnan(x) ? oftype(x, -Inf) : x # use a sentinel value for NaN
julia> argmax(f, a)
5.0
Again nope: if it did, it would return the index i
such that a[i] == maximum(f, a)
.
Personally, I think this is a footgun. If we ever decide to go to Julia 2.0, I think we should reconsider whether these two methods belong to the same function.
One potential solution is that we could have argmax(itr)
become synonymous with argmax(identity, itr)
and embrace the newer meaning of argmax
. Then, noting that findmax(f, a)
does act in a manner consistent with other mapping functions, we could just eliminate the original meaning of argmax
, as argmax
seems to sometimes be used as a substitute for findmax(A)[2]
. But I'm less fond of having to remember whether the index is the first or second output; hence we could switch to having it return a NamedTuple
(we might be able to do that even now).