Найти неподвижную точку многопараметрической функции в Юлии - PullRequest
4 голосов
/ 11 октября 2019

Мне нужно найти фиксированную точку многопараметрической функции в Julia.

Рассмотрим следующий минимальный пример:

function example(p::Array{Float64,1})
    q = -p
    return q
end

В идеале я бы использовал такой пакет, как Roots.jl иВызовите find_zeros(p -> p - example(p)), но я не могу найти аналогичный пакет для функций с несколькими переменными. Я нашел один с именем IntervalRootFinding, но, как ни странно, он требует символов Юникода и редко документирован, поэтому я не могу понять, как его использовать.

Ответы [ 2 ]

5 голосов
/ 12 октября 2019

Есть много вариантов. Выбор наилучшего зависит от характера функции example (вы должны понимать природу вашей функции example и проверять документацию конкретного пакета, поддерживает ли она ее).

Например. вы можете использовать fixedpoint из NLsolve.jl:

julia> using NLsolve

julia> function example!(q, p::Array{Float64,1})
           q .= -p
       end
example! (generic function with 1 method)

julia> fixedpoint(example!, ones(1))
Results of Nonlinear Solver Algorithm
 * Algorithm: Anderson m=1 beta=1 aa_start=1 droptol=0
 * Starting Point: [1.0]
 * Zero: [0.0]
 * Inf-norm of residuals: 0.000000
 * Iterations: 3
 * Convergence: true
   * |x - x'| < 0.0e+00: true
   * |f(x)| < 1.0e-08: true
 * Function Calls (f): 3
 * Jacobian Calls (df/dx): 0

julia> fixedpoint(example!, ones(3))
Results of Nonlinear Solver Algorithm
 * Algorithm: Anderson m=3 beta=1 aa_start=1 droptol=0
 * Starting Point: [1.0, 1.0, 1.0]
 * Zero: [-2.220446049250313e-16, -2.220446049250313e-16, -2.220446049250313e-16]
 * Inf-norm of residuals: 0.000000
 * Iterations: 3
 * Convergence: true
   * |x - x'| < 0.0e+00: false
   * |f(x)| < 1.0e-08: true
 * Function Calls (f): 3
 * Jacobian Calls (df/dx): 0

julia> fixedpoint(example!, ones(5))
Results of Nonlinear Solver Algorithm
 * Algorithm: Anderson m=5 beta=1 aa_start=1 droptol=0
 * Starting Point: [1.0, 1.0, 1.0, 1.0, 1.0]
 * Zero: [0.0, 0.0, 0.0, 0.0, 0.0]
 * Inf-norm of residuals: 0.000000
 * Iterations: 3
 * Convergence: true
   * |x - x'| < 0.0e+00: true
   * |f(x)| < 1.0e-08: true
 * Function Calls (f): 3
 * Jacobian Calls (df/dx): 0

Если вашей функции потребуются инструменты глобальной оптимизации для поиска фиксированной точки, то вы можете, например, использовать BlackBoxOptim.jl с norm(f(x) .-x) в качестве цели:

julia> using LinearAlgebra

julia> using BlackBoxOptim

julia> function example(p::Array{Float64,1})
           q = -p
           return q
       end
example (generic function with 1 method)

julia> f(x) = norm(example(x) .- x)
f (generic function with 1 method)

julia> bboptimize(f; SearchRange = (-5.0, 5.0), NumDimensions = 1)
Starting optimization with optimizer DiffEvoOpt{FitPopulation{Float64},RadiusLimitedSelector,BlackBoxOptim.AdaptiveDiffEvoRandBin{3},RandomBound{ContinuousRectSearchSpace}}
0.00 secs, 0 evals, 0 steps

Optimization stopped after 10001 steps and 0.15 seconds
Termination reason: Max number of steps (10000) reached
Steps per second = 68972.31
Function evals per second = 69717.14
Improvements/step = 0.35090
Total function evaluations = 10109


Best candidate found: [-8.76093e-40]

Fitness: 0.000000000

julia> bboptimize(f; SearchRange = (-5.0, 5.0), NumDimensions = 3);
Starting optimization with optimizer DiffEvoOpt{FitPopulation{Float64},RadiusLimitedSelector,BlackBoxOptim.AdaptiveDiffEvoRandBin{3},RandomBound{ContinuousRectSearchSpace}}
0.00 secs, 0 evals, 0 steps

Optimization stopped after 10001 steps and 0.02 seconds
Termination reason: Max number of steps (10000) reached
Steps per second = 625061.23
Function evals per second = 631498.72
Improvements/step = 0.32330
Total function evaluations = 10104


Best candidate found: [-3.00106e-12, -5.33545e-12, 5.39072e-13]

Fitness: 0.000000000


julia> bboptimize(f; SearchRange = (-5.0, 5.0), NumDimensions = 5);
Starting optimization with optimizer DiffEvoOpt{FitPopulation{Float64},RadiusLimitedSelector,BlackBoxOptim.AdaptiveDiffEvoRandBin{3},RandomBound{ContinuousRectSearchSpace}}
0.00 secs, 0 evals, 0 steps

Optimization stopped after 10001 steps and 0.02 seconds
Termination reason: Max number of steps (10000) reached
Steps per second = 526366.94
Function evals per second = 530945.88
Improvements/step = 0.29900
Total function evaluations = 10088


Best candidate found: [-9.23635e-8, -2.6889e-8, -2.93044e-8, -1.62639e-7, 3.99672e-8]

Fitness: 0.000000391
1 голос
/ 15 октября 2019

Я автор IntervalRootFinding.jl. Я рад сообщить, что в последнее время документация значительно улучшилась, и символы Юникода не нужны. Я предлагаю использовать основную ветку.

Вот как решить ваш пример с пакетом. Обратите внимание, что этот пакет должен быть в состоянии найти всех корней в коробке и гарантировать, что он нашел все из них. У вас есть только 1:

julia> using IntervalArithmetic, IntervalRootFinding

julia> function example(p)
           q = -p
           return q
       end
example (generic function with 2 methods)

julia> X = IntervalBox(-2..2, 2)
[-2, 2] × [-2, 2]

julia> roots(x -> example(x) - x, X, Krawczyk)
1-element Array{Root{IntervalBox{2,Float64}},1}:
 Root([0, 0] × [0, 0], :unique)

Для получения дополнительной информации, я предлагаю посмотреть на https://discourse.julialang.org/t/ann-intervalrootfinding-jl-for-finding-all-roots-of-a-multivariate-function/9515.

...