Hi,
I wrote a custom algorithm to find the root of my equation (I know, there is much better out there, but my function is not differentiable and it s defined decreasing)
Anyway, this is the algorithm. I would like to return the last value of the ‘x’ which is my root. But I cannot!
It returns nothing.
Harnessing with it, I understood that it returns the first value of the first if statement it walks through, but why!? How can I return the last value. I can define a global variable and get it through that, but it is just wrong!
Thanks for help
## Assuming the function is monotonous decrescent
K = 0.
function _find_minimum!(;y0=10., n = 2., x::Real=20., ν::Real, model::Function)
y = -4*x + 5
# _compute_voltage(;model=ss,ν=ν, Kie=x)
if abs(y0) > 0.001
if sign(y0) ==sign(y)
## the solution is far ahead!
x1 = x + sign(y0)*(2^n-1)
_find_minimum!(y0=y, n=n, ν=ν, x=x1, model=model)
end
if sign(y0) != sign(y)
## you stepped through the solution, go back!
x1 = x - sign(y)*(2^n-1)
_find_minimum!(y0=y, n=n/2., ν=ν, x=x1, model=model)
end
else
## this works
global K = x
return x
end
end
All expressions in Julia have a value. For an if statement, that value is the value of the expression in whatever branch was taken (or nothing if no branch was taken):
julia> a = if 1 == 2
"hello"
else
"world"
end
"world"
julia> a
"world"
Likewise a function automatically returns the value of its last expression if you don’t have an explicit return:
julia> function foo()
if 1 == 2
"hello"
else
"world"
end
end
foo (generic function with 1 method)
julia> a = foo()
"world"
julia> a
"world"
You just need to do return _find_minimum(...) to ensure that the returned value from the last recursive call is propagated all the way out.
For a much simpler example, here’s a simple recursive function to compute a square root:
julia> function find_sqrt(x, guess)
y = x / guess
if y ≈ guess
return guess
else
return find_sqrt(x, 0.5 * (guess + y))
end
end
find_sqrt (generic function with 1 method)
julia> find_sqrt(4, 1)
2.000000000000002
julia> find_sqrt(2, 1)
1.4142135623746899
Also note that I could have removed both return statements without changing the behavior of the function, since the function will implicitly return the value of the if block, and the value of that block will be the value of whatever branch was chosen:
julia> function find_sqrt(x, guess)
y = x / guess
if y ≈ guess
guess
else
find_sqrt(x, 0.5 * (guess + y))
end
end
find_sqrt (generic function with 1 method)
julia> find_sqrt(9, 1)
3.000000001396984
Thanks for the clear explanation, although it is important to signal that the if branches need the else. Indeed, the same algorithm -with the complementary if statement - return nothing
function find_sqrt(x, guess)
y = x / guess
if y ≈ guess
guess
end
if !(y ≈ guess)
find_sqrt(x, 0.5 * (guess + y))
end
end