julia

Julia - Find argmin of function over values of an array


I have a function f and an array A with values, I want to calculate argmin(f) regarding the values in the array.

For example:

f(x,y)=2x^2-y^2

A=[1 2; 3 4]

My intuitive approach was to try

argmin(f,A)

But I get the error message:

ERROR: MethodError: no method matching (::var"#f#6")(::Int64)

I would like to get the index of the row in A for which f is minimal.

I know I could calculate the argmin with for-loops, but is there a more elegant/efficient way that uses the argmin directly?


Solution

  • I would like to get the index of the row in A for which f is minimal.

    Method argmin(f, X) gives value xmin from collection X for which f is minimal. To find index of xmin in collection X use findmin(f, X).

    So, for your example the solution would be

    julia> f(x, y) = 2*x^2 - y^2
    
    julia> A = [1 2; 3 4]
    
    julia> g(x) = f(x[1], x[2])  # or, more general g(x) = f(x...)
    
    julia> minvalue, minindex = findmin(g, eachrow(A))
    # Avoiding defintion of g:  findmin(row -> f(row...), eachrow(A))
    (-2, 1)
    
    julia> A[minindex, :]
    2-element Vector{Int64}:
     1
     2
    

    The method error you get is caused by iteration behavior over Matrix. Function argmin iterates over a collection in default manner, for Matrix it is iteration over its elements. On other hand, eachrow(A) gives an iterator over Matrix's rows.

    Compare

    julia> for x in A
               println(x)
           end
    1
    3
    2
    4
    
    julia> for x in eachrow(A)
               println(x)
           end
    [1, 2]
    [3, 4]
    

    So, in your case argmin(f, A) iterates over elements of A, and call f(element_of_A), but there is no method for f which takes one argument. That's why g function is needed.