How to get the inverse of a function

Hello,

I have the following function which I have been plotting as follows:

function f(x,p)
    v0,S,D,v,K,n,µ = p
    return (((S*x)^n*(µ*x - v - v0)/(v0 - µ*x))^(1/n)-D*x-K)/D
end

plot(x -> f(x,(0.4,4.0,1.0,2.0,0.7,2,1.0)),0.0,1.0)

I would now like to find and plot the inverse of the function. How can I get this? I tried the InverseFunctions package that I found online but it does not seem to be working.

Thanks in advance!

You can solve an equation with for example Roots.jl to obtain the inverse function:

using Roots

invf(y, p) = find_zero(x -> f(x, p) - y, x0)
2 Likes

Thanks a lot! How do I know what to set for x0?

You need good guess for that, which is problem-dependent.

1 Like

In addition, when I do plot(x -> f(x,(0.4,4.0,1.0,2.0,0.7,2,1.0)),0.0,1.0) I get the output below
Screenshot 2022-09-29 at 12.28.56

Now to plot the inverse I’m doing invf(y, p) = find_zero(x -> f(x, p) - y, 1) where I set x0 to 1 just to test whether it works.

However if I now do plot(x -> invf(x,(0.4,4.0,1.0,2.0,0.7,2,1.0)),0.0,1.0) , I get the same axes as above but a totally blank plot.

Any clue why? Thanks!

Does find_zero find a zero with that initial value? You can also try different algorithms for root-finding.

1 Like

Hm I don’t think I know enough math (haven’t gone above high school level) to understand what root finding is nor do I actually get what find_zero does, which I think is why I’m a bit lost! Any chance you could explain a bit, or is there an alternative Julia method that is more compatible with my poor math skills? Apologies for the ignorance!

If it is monotonic, bisection over the whole interval will work. So no guess is needed here.

1 Like

I don’t have any reference off the top of my head. There’s this Root-finding algorithms - Wikipedia but I’m not sure it is at your level. Perhaps youtube or Khan academy can help?

1 Like

If you know that a function is invertible, and you don’t use its inverse later in your code, then you can plot it, taking into account that the graph of the inverse is the reflection (mirror) of the direct one in the line y=x.

2 Likes

See also https://docs.juliahub.com/CalculusWithJulia/AZHbv/0.0.2/precalc/inversefunctions.html

1 Like

Ah yes this is exactly what I want :slight_smile: Do you know how I can flip a plot along the line y=x?

For the mirrored just do plot(y, x) instead of plot(x, y).

So in your case you might want to actually calculate y=f.(x,[(...)]) for some range x=0:dx:1 and use those when plotting.

2 Likes

Awesome, thanks a lot!

Just to give an example with some code to modify, this function will find the inverse over [a,b] for a monotonic function f, if performance is not an issue:

using Roots
function inverse_function(f, a, b, args...; kwargs...)
    fa, fb = f(a), f(b)
    m, M = fa < fb ? (fa, fb) : (fb, fa)
    y -> begin # return a function
        @assert m ≤ y ≤ M
        find_zero(x ->f(x) - y, (a,b), args...; kwargs...)
    end
end

This can be plotted, for example:

f(x) = x - sin(x)
a, b = 0, 5pi
plot(inverse_function(f, a, b), f(a), f(b))

(though for a plot, using plot(f.(xs), xs) is going to be more direct)

If you want an analytic solution, then you can try SymPy along the lines of

using SymPy
@syms x y
solve(y ~ f(x), x)

But this only gets you so far (e.g. f(x) = x- sin(x) won’t work; f(x) = x^3 -3 will have multiple answers to sift through, …)