BrianChung10 / SOP

2 stars 1 forks source link

A function to find multiple roots - not working #3

Closed BrianChung10 closed 2 years ago

BrianChung10 commented 2 years ago

Dear John,

I am still facing some issues with regards to goal 1, which is to produce a function that can find all roots for a given function. (a polynomial, for example)

If you look at rows 100 to 110, it is possible to repeat the process of deflating and applying a newton method manually to find all roots (For example g(x) = (x-2) (x+2) (x+3) gives 2, -2, -3) However when I express it as a 'multroot' function from rows 81 to 95 the function suffers from a stackoverflowerror.

Is there some problem with the way I coded? I would send a stack trace.

BrianChung10 commented 2 years ago

ERROR: StackOverflowError: Stacktrace: [1] (::var"#11#12"{Vector{Function}})(x::Int64) (repeats 10800 times) @ Main ~/SOP/SOP/simple_deflation/deflation.jl:90 [2] newton(f::var"#11#12"{Vector{Function}}, x0::Int64, max_iter::Int64, eps::Float64) @ Main ~/SOP/SOP/simple_deflation/deflation.jl:20 [3] newton(f::Function, x0::Int64) @ Main ~/SOP/SOP/simple_deflation/deflation.jl:18 [4] multroot(f::Function, x0::Int64, n::Int64) @ Main ~/SOP/SOP/simple_deflation/deflation.jl:91 [5] multroot(f::Function, x0::Int64) @ Main ~/SOP/SOP/simple_deflation/deflation.jl:82 [6] eval @ ./boot.jl:373 [inlined] [7] include_string(mapexpr::typeof(REPL.softscope), mod::Module, code::String, filename::String) @ Base ./loading.jl:1196 [8] invokelatest(::Any, ::Any, ::Vararg{Any}; kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}) @ Base ./essentials.jl:716 [9] invokelatest(::Any, ::Any, ::Vararg{Any}) @ Base ./essentials.jl:714 [10] inlineeval(m::Module, code::String, code_line::Int64, code_column::Int64, file::String; softscope::Bool) @ VSCodeServer ~/.vscode/extensions/julialang.language-julia-1.6.17/scripts/packages/VSCodeServer/src/eval.jl:211 [11] (::VSCodeServer.var"#65#69"{Bool, Bool, Module, String, Int64, Int64, String, VSCodeServer.ReplRunCodeRequestParams})() @ VSCodeServer ~/.vscode/extensions/julialang.language-julia-1.6.17/scripts/packages/VSCodeServer/src/eval.jl:155 [12] withpath(f::VSCodeServer.var"#65#69"{Bool, Bool, Module, String, Int64, Int64, String, VSCodeServer.ReplRunCodeRequestParams}, path::String) @ VSCodeServer ~/.vscode/extensions/julialang.language-julia-1.6.17/scripts/packages/VSCodeServer/src/repl.jl:184 [13] (::VSCodeServer.var"#64#68"{Bool, Bool, Bool, Module, String, Int64, Int64, String, VSCodeServer.ReplRunCodeRequestParams})() @ VSCodeServer ~/.vscode/extensions/julialang.language-julia-1.6.17/scripts/packages/VSCodeServer/src/eval.jl:153 [14] hideprompt(f::VSCodeServer.var"#64#68"{Bool, Bool, Bool, Module, String, Int64, Int64, String, VSCodeServer.ReplRunCodeRequestParams}) @ VSCodeServer ~/.vscode/extensions/julialang.language-julia-1.6.17/scripts/packages/VSCodeServer/src/repl.jl:36 [15] (::VSCodeServer.var"#63#67"{Bool, Bool, Bool, Module, String, Int64, Int64, String, VSCodeServer.ReplRunCodeRequestParams})() @ VSCodeServer ~/.vscode/extensions/julialang.language-julia-1.6.17/scripts/packages/VSCodeServer/src/eval.jl:124 [16] with_logstate(f::Function, logstate::Any) @ Base.CoreLogging ./logging.jl:511 [17] with_logger @ ./logging.jl:623 [inlined] [18] (::VSCodeServer.var"#62#66"{VSCodeServer.ReplRunCodeRequestParams})() @ VSCodeServer ~/.vscode/extensions/julialang.language-julia-1.6.17/scripts/packages/VSCodeServer/src/eval.jl:201 [19] #invokelatest#2 @ ./essentials.jl:716 [inlined] [20] invokelatest(::Any) @ Base ./essentials.jl:714 [21] macro expansion @ ~/.vscode/extensions/julialang.language-julia-1.6.17/scripts/packages/VSCodeServer/src/eval.jl:34 [inlined] [22] (::VSCodeServer.var"#60#61")() @ VSCodeServer ./task.jl:423

ioannisPApapadopoulos commented 2 years ago

Which file are you referring to?

BrianChung10 commented 2 years ago

It is simple_deflation/deflation.jl

dlfivefifty commented 2 years ago

StackOverflow almost always is caused by a recursive function that never terminates

ioannisPApapadopoulos commented 2 years ago

Yes, that's what happening but it's a bit peculiar. Stepping through the code, the first loop through the while loop works, but the moment we hit k+=1 a second time, we run into issues. Essentially fs[3] calls fs[2]. Now fs[2] should be calling fs[1], but because k has been incrememented up by 1, it ends up calling itself. How bizarre.

ioannisPApapadopoulos commented 2 years ago

I think the way around this is to not generate new fs that depend on previous function definitions of fs during the while loop, but rather have something like fs = x -> f(x) * M(x, sol).

I.e. modify your definition of function M (lines 11-13) so that it spits out what it should be for all the solutions, e.g.

function M(x, sol, p=2, alpha=1)
    m=1
    for sols in sol
        m=m*(1 / norm(x-sols)^p + alpha)
    end
    return m
end

and

function multroot(f, x0, n = 10)
    xn = newton(f, 0)
    sol = [xn]
    k = 1
    while xn != "Cannot converge."
        k += 1
        m = 1
        fs = x -> f(x) * M(x,sol)
        xnew = newton(fs, x0)
        push!(sol, xnew)
    end
    sol
end

There's still an error due to trying to push the string "Cannot converge." into sol but you can fix that :)

dlfivefifty commented 2 years ago

Because k refers to the outer variable

I think use the struct suggestion

Sent from my iPhone

On 31 May 2022, at 14:13, Ioannis Papadopoulos @.***> wrote:

 Yes, that's what happening but it's a bit peculiar. Stepping through the code, the first loop through the while loop works, but the moment we hit k+=1 a second time, we run into issues. Essentially fs[3] calls fs[2]. Now fs[2] should be calling fs[1], but because k has been incrememented up by 1, it ends up calling itself. How bizarre.

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you commented.

dlfivefifty commented 2 years ago

You can also just use a let block to create a new variable. Eg

let j = k
    f = x -> j
end

Will create a new variable j each time