# Built-ins for discrete ArgMax or ArgMin?

Wondering whether there are discrete versions of ArgMax / ArgMin, that is, something that will find the part of an expression at which some function f of the elements is maximized (or minimized).

Last[Ordering[f/@list]] and First[Ordering[f/@list]] will do, but the following does not work:

ArgMax[Function[i, (f/@list)[[i]]], i]

-
If you use Ordering, Ordering[list, 1] is more efficient than First@Ordering[list] – Szabolcs Feb 11 '13 at 19:40
What if the function is bivariate, e.g., f(x,y), and we want to find argmax or argmin over both x and y? – Alex Mar 24 '15 at 18:27
If you have a new question, please ask it by clicking the Ask Question button. Include a link to this question if it helps provide context. – bbgodfrey Mar 24 '15 at 18:58
This does not provide an answer to the question. To critique or request clarification from an author, leave a comment below their post - you can always comment on your own posts, and once you have sufficient reputation you will be able to comment on any post. – Louis Mar 24 '15 at 19:38

I guess Max and Min are the best fit for discrete lists.

f[x_] := x Sin[x];
list = RandomReal[10, 10^6];
(Position[#, Max[#], 2][[1, 1]]) &@(f /@ list)


One can forcefully use NArgMax or NArgMin for this purpose but they are likely to be extremely inefficient! One such example

list = RandomReal[10, 1000];
ob[i_?IntegerQ] := (f /@ list)[[i]];
ob@NArgMax[{Evaluate@ob[x],1<= x<= Length@list&&Element[x,Integers]},x]//AbsoluteTiming


{5.8344103, 7.91672}

Where as

Max[f /@ list]// AbsoluteTiming


{0., 7.91672}

For timing comparison with solution using Ordering see the following plot. Horizontal axes shows the data length of list and the vertical axes is denoting computation time in seconds. I have tested it in an Intel i7 PC with 64 GB RAM.

As one can see if you compile the functions you get even better speed ups.

cf=Compile[{{x,_Real,1}},
Module[{listval,max},
listval=# Sin[#]&/@x;
max=Max[listval];
(Position[listval,max])[[1,1]]
],
CompilationTarget->"C",
RuntimeAttributes->{Listable},Parallelization->True];

-
This seems to be much faster than the other proposal on large inputs. – Reb.Cabin Feb 11 '13 at 16:15
Yes I will update the answer with timing comparison. – PlatoManiac Feb 11 '13 at 16:16
Ordering[f /@ list, -1] for argmax and Ordering[f /@ list,1] for argmin seems to be faster than both Position-Max combination and Ordering[list,f[#1] < f[#2] &]. – kglr Feb 11 '13 at 17:00

Ordering is good for this if you use a custom ordering function:

f=Sin;
list = RandomReal[{0, Pi}, 100];
First@Ordering[list, 1, f[#1] < f[#2] &]


And similarly for maximum replacing 1 with -1 (or < with >)

-
Manually supplying an ordering function seems to be much slower than just using Ordering[f/@list,1] as kguler recommended in a comment to an answer above. – Wizard Oct 7 '13 at 21:59

Version 10 has a new function FindPeaks that can be used here:

f[x_] := x Sin[x];
list = Range[1, 10, 0.1];
FindPeaks[f /@ list]


This returns the location (in the list) and value of the local maxes. Another new function that's related is MaxDetect, which returns a vector of zeros (at all the non-max locations) and ones (at all the max locations).

MaxDetect[f /@ list]


MaxDetect also works nicely on 2D and 3D data arrays and images, and there is also MinDetect that does what you would expect.

-