У меня есть функция f и массив A со значениями, я хочу вычислить argmin(f) относительно значений в массиве.
Например:
f(x,y)=2x^2-y^2
A=[1 2; 3 4]
Мой интуитивный подход заключался в том, чтобы попытаться
argmin(f,A)
Но я получаю сообщение об ошибке:
ERROR: MethodError: no method matching (::var"#f#6")(::Int64)
Я хотел бы получить индекс строки в A, для которой f минимален.
Я знаю, что могу вычислить argmin с помощью циклов for, но есть ли более элегантный/эффективный способ напрямую использовать argmin?
Я использую Джулию v1.10





argmin(f,A) будет перебирать каждый элемент A, чтобы найти тот, который дает выходные данные функции smalls, он не будет перебирать строки A. Другими словами, он начнет с вызова f(A[1]), а A[1] — это 1, поэтому он вызывает f(1). Но функция f принимает два аргумента, а не один, и поэтому не будет выполнена.
Вы можете перебирать строки A, используя итератор eachrow, например так:
julia> findmin(f(row[1], row[2]) for row in eachrow(A))
(-2, 1)
Первый вывод — это значение, второй — индекс итератора строки. Функция argmax здесь тоже будет работать, но я рекомендую findmin, поскольку argmin обычно возвращает входное значение, которое минимизирует вызов, а не минимальный индекс. На самом деле, поведение argmin/argmax мне очень трудно понять и предсказать, и в сообществе Julia ведутся споры по поводу его поведения.
Кстати, поскольку Джулия Array является основным столбцом, обычно рекомендуется читать данные из них не по строкам, а по столбцам. Если вы можете сами выбрать макет, я бы изменил ориентацию входной матрицы и использовал eachcol вместо eachrow.
Здравствуйте, спасибо за ответ, это было очень полезно! Это отлично работает для моего примера, однако, если у меня есть функция, которая зависит от n переменных, или несколько функций, одна из которых зависит от n, а другая зависит от n-1 переменных. Есть ли способ найти более общий способ/сделать его напрямую зависимым от размера моей Матрицы?
Я хотел бы получить индекс строки в A, для которой f минимально.
Метод argmin(f, X) возвращает значение xmin из коллекции X, для которого f минимально. Чтобы найти индекс xmin в коллекции X, используйте findmin(f, X).
Итак, для вашего примера решение будет
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
Ошибка метода, которую вы получаете, вызвана поведением итерации над Matrix. Функция argmin перебирает коллекцию по умолчанию, поскольку Matrix это перебор ее элементов. С другой стороны, eachrow(A) дает итератор по строкам Matrix.
Сравнивать
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]
Итак, в вашем случае argmin(f, A) перебирает элементы A и вызывает f(element_of_A), но для f нет метода, который принимает один аргумент. Вот почему нужна функция g.
Здравствуйте, спасибо за ваш ответ! Есть ли способ избежать явного определения g(x)? Хотя ваш метод работает для моего примера, я ищу способ сделать это более общим. Например, если у меня есть функция, которая зависит от n переменных. Или у меня есть несколько функций, одна из которых зависит от 6 разных переменных, а другая — от 9, или. Есть ли способ избежать записи g(x)=f(x[1],...,x[n])
@ Мориц, да. Синтаксис g(x) = f(x[1], x[2]) обобщается следующим образом g(x) = f(x...) для f(x1), f(x1, x2), f(x1, x2, x3) и так далее. См. оператор знака . Чтобы опустить определение g, используйте анонимную функцию, например. findmin(row -> f(row...), eachrow(A)).
Есть еще несколько возможностей: вы можете использовать удобную функцию splat, например: findmin(splat(f), eachrow(A)), или генератор, например: findmin(f(row...) for row in eachrow(A)). Обратите внимание, что разброс Arrays снижает производительность, поскольку количество элементов неизвестно во время компиляции.
@StepanZakharov, спасибо, я не знал об операторе splat, это было именно то, что я искал.
@DNF спасибо, это интересно! Не могли бы вы рассказать подробнее о снижении производительности или подсказать мне источник, где я могу об этом прочитать?
@Moritz f(x...) принимает каждый элемент x в качестве входного аргумента f. Какая версия/метод f вызывается, зависит от количества элементов в x. Если компилятор может заранее определить длину x только по типу x, тогда он знает, какой метод f вызывать. В противном случае правильный метод должен быть выбран во время выполнения, что повлечет за собой значительные затраты. Тег типа Array не несет информации о своем собственном размере, эту информацию будет хранить только реальный экземпляр. Если x является кортежем фиксированной длины или StaticArray, вы можете это определить, и правильный вызов будет разрешен во время компиляции.
Какую версию Джулии вы используете?