Метод дефляции для поиска нескольких корней

#julia #numerical-methods

#джулия #численные методы

Вопрос:

Я пытаюсь реализовать метод дефляции для нахождения нескольких корней многочлена на Julia. В методе дефляции новые функции генерируются из фактической функции, разделенной на x - x_roots[i] , и корень новой сгенерированной функции должен быть найден. Но g(x) = g(x) / (x - x_root) выдает мне ошибку переполнения стека, поскольку, вероятно, она сгенерировала бесконечное рекурсивное отношение. Как я могу генерировать новую функцию на каждом шаге?

 function deflation(f::Function, order)
    roots=[]
    n=1
    g(x)=f(x)
    x_root=Muller_method(f,-5,0,5,1e-5,50)
    while n<=order
        x_root=Muller_method(a,-5,0,5,1e-5,50)
        g(x)=g(x)/(x-x_root)
        append!(roots,x_root)
        n=n 1
    end
return (roots)
  

Комментарии:

1. Вы должны попробовать опубликовать минимальные (не) рабочие примеры, которые мы можем воспроизвести в наших собственных системах. Например, ваш код (в его нынешнем виде) содержит несколько ошибок, которые совершенно не связаны с вашим вопросом: g никогда не вызывается, a и Muller_method не определены, в deflation определении функции отсутствует end ключевое слово… Наличие воспроизводимого примера помогло бы нам помочь вам!

2. Кстати, инициализировать нетипизированные массивы с помощью [] часто не очень хорошая идея. Если вы знаете, что roots будет содержать только числа с плавающей запятой, было бы намного лучше инициализировать его следующим образом, например: roots = Float64[] .

3. Я не поделился этой частью, потому что думал, что это не так. Прошу прощения за то, что это был мой первый пост. Большое вам спасибо.

Ответ №1:

Что-то подобное вызывает бесконечную рекурсию:

 julia> g(x) = x
g (generic function with 1 method)

julia> g(1)
1

julia> g(x) = g(x) / 2
g (generic function with 1 method)

julia> g(1)
ERROR: StackOverflowError:
Stacktrace:
 [1] g(::Int64) at ./REPL[3]:1 (repeats 79984 times)
  

Это связано с тем, что определения функции (или метода) не работают как присвоение переменной: каждое повторное определение g(x) перезаписывает предыдущее (обратите внимание, что g выше всегда используется только один метод). Когда определение метода ссылается на самого себя, это рекурсия, то есть оно ссылается на свою собственную версию в момент вызова функции.

Что касается вашего метода дефляции, возможно, вы могли бы определить новую функцию, которая закрывает вектор найденных в данный момент корней. Рассмотрим следующий пример, чтобы увидеть, как все будет работать:

 julia> f(x) = (x-1) * (x-2)
f (generic function with 1 method)

julia> roots = Float64[]
Float64[]


# g is defined once, and accounts for all currently found roots
julia> g(x) = f(x) / reduce(*, x-root for root in roots; init=one(x))
g (generic function with 1 method)


# No roots are identified at the beginning
julia> g(1 eps())  
-2.2204460492503126e-16

julia> g(2 eps())
0.0


# But the results produced by g update as roots are identified
julia> push!(roots, 1.)
1-element Array{Float64,1}:
 1.0

julia> g(1 eps())
-0.9999999999999998

julia> g(2 eps())
0.0
  

Комментарии:

1. Большое вам спасибо. Я не знал метода уменьшения. Это мне очень помогло, еще раз спасибо.