# How to Use InverseFunctions.jl that can Calculate the Inverse of a Function?

**URL:** https://discourse.julialang.org/t/how-to-use-inversefunctions-jl-that-can-calculate-the-inverse-of-a-function/91931
**Category:** General Usage
**Tags:** package
**Created:** [December 21, 2022, 7:16am UTC](https://discourse.julialang.org/t/how-to-use-inversefunctions-jl-that-can-calculate-the-inverse-of-a-function/91931 "2022-12-21T07:16:24Z")
**Posts on this page:** 16
**Page:** 1

<div class="post-metadata">

### Author: ![Freya\_the\_Goddess](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/freya_the_goddess/32/36835_2.png) [@Freya\_the\_Goddess](https://discourse.julialang.org/u/Freya_the_Goddess)
#### Post date: [December 21, 2022, 7:16am UTC](https://discourse.julialang.org/t/how-to-use-inversefunctions-jl-that-can-calculate-the-inverse-of-a-function/91931/1 "2022-12-21T07:16:24Z")

</div>

Hi all,

I read the package here:  
[https://juliamath.github.io/InverseFunctions.jl/stable/](https://juliamath.github.io/InverseFunctions.jl/stable/)

I want to calculate simple inverse of a function: y^{2} = 4x

I use this:

```julia
using InverseFunctions

foo(x) = sqrt(4x)

inverse(foo)

```

**NoInverse{typeof(foo)}(foo)**

Why it does not return the inverse of a function which is \frac{y^{2}}{4}  
Another question, I want to know another alternative to get the inverse of a function besides that package.

---

<div class="post-metadata">

### Author: ![uniment](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/uniment/32/24532_2.png) [@uniment](https://discourse.julialang.org/u/uniment)
#### Post date: [December 21, 2022, 7:28am UTC](https://discourse.julialang.org/t/how-to-use-inversefunctions-jl-that-can-calculate-the-inverse-of-a-function/91931/2 "2022-12-21T07:28:35Z")

</div>

This package wants you to express the function as a composition of functions:

```julia
julia> using InverseFunctions

julia> foo = sqrt ∘ Base.Fix1(*, 4)
sqrt ∘ Base.Fix1{typeof(*), Int64}(*, 4)

julia> inverse(foo)
Base.Fix1{typeof(\), Int64}(\, 4) ∘ InverseFunctions.square

julia> inverse(foo).(1:8)
8-element Vector{Float64}:
  0.25
  1.0
  2.25
  4.0
  6.25
  9.0
 12.25
 16.0

```

It does raise interesting questions about function composition fallbacks, something that’s recently been on my mind ([see here](https://discourse.julialang.org/t/summary-of-piping-chaining-proposal/91442/8)). It could be interesting if Julia allowed our own fallbacks for this kind of purpose. Calculating inverse functions sure is handy, e.g., when using the Kolmogorov-Nagumo Average.

Edit: On further thought, we wouldn’t need any custom fallback to satisfy this desire beyond what was suggested in that link (i.e., a composition fallback for partially-applied functions).

---

<div class="post-metadata">

### Author: ![uniment](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/uniment/32/24532_2.png) [@uniment](https://discourse.julialang.org/u/uniment)
#### Post date: [December 21, 2022, 8:17am UTC](https://discourse.julialang.org/t/how-to-use-inversefunctions-jl-that-can-calculate-the-inverse-of-a-function/91931/3 "2022-12-21T08:17:53Z")

</div>

Building on concepts from PR#24990 and function composition…

```julia
julia> using ChainingDemo # my demo code for underscore partial application

julia> InverseFunctions.inverse(f::ComposedPartialFunction) = inverse(f.f)

julia> InverseFunctions.inverse(f::Fix{F,()}) where F = inverse(f.f)

julia> InverseFunctions.inverse(f::Fix1_2) = inverse(Base.Fix1(f.f, f.fixvals[1]))

julia> f(x) = √(4x)
f (generic function with 1 method)

julia> @underscores@show g=inverse(f(identity(_)));
g = inverse(f(Fix{(), 1}(identity))) = identity ∘ Base.Fix1{typeof(\), Int64}(\, 4) ∘ InverseFunctions.square

julia> g(8)
16.0

```

![RaccoonYesGIF](https://global.discourse-cdn.com/julialang/original/3X/5/a/5a3531c2086628b4225b78e831b3bccf1b115015.gif)

---

<div class="post-metadata">

### Author: ![Freya\_the\_Goddess](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/freya_the_goddess/32/36835_2.png) [@Freya\_the\_Goddess](https://discourse.julialang.org/u/Freya_the_Goddess)
#### Post date: [December 21, 2022, 8:44am UTC](https://discourse.julialang.org/t/how-to-use-inversefunctions-jl-that-can-calculate-the-inverse-of-a-function/91931/4 "2022-12-21T08:44:00Z")

</div>

Can I have the function `g` in terms of `y` ?

ChainingDemo is not available to be downloaded now.

---

<div class="post-metadata">

### Author: ![uniment](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/uniment/32/24532_2.png) [@uniment](https://discourse.julialang.org/u/uniment)
#### Post date: [December 21, 2022, 8:55am UTC](https://discourse.julialang.org/t/how-to-use-inversefunctions-jl-that-can-calculate-the-inverse-of-a-function/91931/5 "2022-12-21T08:55:37Z")

</div>

Yes, `g` is a function of `y`.

`ChainingDemo` is just some demo code I made to demonstrate my ideas for a language proposal (available in the link above), demonstrating an implementation of [PR#24990](https://github.com/JuliaLang/julia/pull/24990) to make `_` underscores create partial functions. In that demo code I overloaded a “whitelist” of basic functions so that calling them on partial functions would invoke function composition.

Unfortunately, these ideas aren’t very robust when not implemented as a proper language feature (a function composition fallback is preferable to overloading, due to type ~~inference~~ dispatch ambiguities that arise from overloading).

So until PR#24990 can be approved, we will just have to live with typing out `foo = sqrt ∘ Base.Fix1(*, 4)` instead.

---

<div class="post-metadata">

### Author: ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)
#### Post date: [December 21, 2022, 1:33pm UTC](https://discourse.julialang.org/t/how-to-use-inversefunctions-jl-that-can-calculate-the-inverse-of-a-function/91931/6 "2022-12-21T13:33:24Z")

</div>

Accessors.jl helps defining a function as a composition:

```julia
julia> using Accessors, InverseFunctions

julia> foo = @optic sqrt(4*_)
sqrt ∘ Base.Fix1{typeof(*), Int64}(*, 4)

julia> inverse(foo)
Base.Fix1{typeof(\), Int64}(\, 4) ∘ InverseFunctions.square

```

Accessors are composable and have much more superpowers, but the above is also a common nice usecase. Accessors.jl is a very stable, lightweight and widely used package.

---

<div class="post-metadata">

### Author: ![uniment](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/uniment/32/24532_2.png) [@uniment](https://discourse.julialang.org/u/uniment)
#### Post date: [December 21, 2022, 2:28pm UTC](https://discourse.julialang.org/t/how-to-use-inversefunctions-jl-that-can-calculate-the-inverse-of-a-function/91931/7 "2022-12-21T14:28:02Z")

</div>

Ah yes, this is a nice option too.

---

<div class="post-metadata">

### Author: ![Freya\_the\_Goddess](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/freya_the_goddess/32/36835_2.png) [@Freya\_the\_Goddess](https://discourse.julialang.org/u/Freya_the_Goddess)
#### Post date: [December 22, 2022, 8:12am UTC](https://discourse.julialang.org/t/how-to-use-inversefunctions-jl-that-can-calculate-the-inverse-of-a-function/91931/8 "2022-12-22T08:12:51Z")

</div>

I still don’t get this:

why defining a function as a composition to get the inverse of a function?

---

<div class="post-metadata">

### Author: ![uniment](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/uniment/32/24532_2.png) [@uniment](https://discourse.julialang.org/u/uniment)
#### Post date: [December 22, 2022, 9:01am UTC](https://discourse.julialang.org/t/how-to-use-inversefunctions-jl-that-can-calculate-the-inverse-of-a-function/91931/9 "2022-12-22T09:01:20Z")

</div>

Function composition is just a convenient way to represent a sequence of function calls, because it stores the functions in a data structure and it’s supported by the language.

Consider the function h(x)=\sqrt{4x}. We can represent it as h(x)=f(g(x)) where f(x)=\sqrt x and g(x)=4x.

Mathematics provides a _function composition operator_ \circ, which allows you to write h as a composition of f and g, namely, h=f\circ g. The rules are, h(x) = f(g(x)) \Leftrightarrow h(x)= (f\circ g)(x). The neat thing about this is that h can be represented strictly in terms of other functions, and not in terms of x, and so if you know the properties of those functions you can reason about the properties of h.

Julia, being a language heavily inspired by mathematics, provides a function composition operator `∘` (`\circ<tab>`). The rules work the same as in mathematics, and when I write `h=f∘g`, the result is an object that can be called like any other function, `h(x) == (f∘g)(x)`, but the object `h` has information about what functions it’s made of. If you’re trying to take the inverse of `h`, this is super useful because you can simply interrogate the `h` object to find what functions it’s made of, take the inverse of those (which you know from a lookup table), and compose a new function with those inverses in reversed order.

To see how it works in detail, go to [line 1024 here](https://github.com/JuliaLang/julia/blob/master/base/operators.jl). Basically, `h::ComposedFunction` has `h.inner` and `h.outer` fields that contain the functions it’s made of.

---

<div class="post-metadata">

### Author: ![fatteneder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fatteneder/32/33991_2.png) [@fatteneder](https://discourse.julialang.org/u/fatteneder)
#### Post date: [December 22, 2022, 9:03am UTC](https://discourse.julialang.org/t/how-to-use-inversefunctions-jl-that-can-calculate-the-inverse-of-a-function/91931/10 "2022-12-22T09:03:23Z")

</div>

Assuming f,g are invertible, it holds (f \circ g)^{-1} = g^{-1} \circ f^{-1} with f^{-1} the inverse of f.

---

<div class="post-metadata">

### Author: ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)
#### Post date: [December 22, 2022, 9:28am UTC](https://discourse.julialang.org/t/how-to-use-inversefunctions-jl-that-can-calculate-the-inverse-of-a-function/91931/11 "2022-12-22T09:28:31Z")

</div>

> [@Freya\_the\_Goddess](#):
>
> why defining a function as a composition to get the inverse of a function?

There are different possible ways to automatically calculate function inverses:

- Analytical, as implemented by `InverseFunctions`. Basically, this package is a database of known invertible functions with their inverses, and a mechanism of computing inverses for function compositions: `inverse(f ∘ g) = inverse(g) ∘ inverse(f)`.
- Numerical: computing `f_inv(x) = y` involves solving `f(y) = x`. This is not how `InverseFunctions` work.

So, the analytical approach works when the function is in the “database” itself, or is a composition of known functions. When you define `f(x) = sqrt(4x)` and try `inverse(f)`, the `f` function is opaque to the `inverse` function: it doesn’t know what operations are inside. So, `f` should be an explicit Julia function composition.

---

<div class="post-metadata">

### Author: ![Freya\_the\_Goddess](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/freya_the_goddess/32/36835_2.png) [@Freya\_the\_Goddess](https://discourse.julialang.org/u/Freya_the_Goddess)
#### Post date: [December 23, 2022, 5:16am UTC](https://discourse.julialang.org/t/how-to-use-inversefunctions-jl-that-can-calculate-the-inverse-of-a-function/91931/12 "2022-12-23T05:16:55Z")

</div>

I have been trying to find the inverse of f through the composition method, thanks to your explanation I can understand a bit more.

But I think I still can’t find the inverse of h.

![Capture d’écran_2022-12-23_12-16-02](https://global.discourse-cdn.com/julialang/original/3X/2/d/2da975d1df966b9a7ac4334fc89ba735e3aae613.png)

---

<div class="post-metadata">

### Author: ![Freya\_the\_Goddess](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/freya_the_goddess/32/36835_2.png) [@Freya\_the\_Goddess](https://discourse.julialang.org/u/Freya_the_Goddess)
#### Post date: [December 23, 2022, 5:18am UTC](https://discourse.julialang.org/t/how-to-use-inversefunctions-jl-that-can-calculate-the-inverse-of-a-function/91931/13 "2022-12-23T05:18:05Z")

</div>

I define the function f(x) and g(x)

then type

```julia
inverse(f∘g)

```

gets:  
**NoInverse{ComposedFunction{typeof(f), typeof(g)}}(f ∘ g)**

---

<div class="post-metadata">

### Author: ![Freya\_the\_Goddess](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/freya_the_goddess/32/36835_2.png) [@Freya\_the\_Goddess](https://discourse.julialang.org/u/Freya_the_Goddess)
#### Post date: [December 23, 2022, 5:39am UTC](https://discourse.julialang.org/t/how-to-use-inversefunctions-jl-that-can-calculate-the-inverse-of-a-function/91931/14 "2022-12-23T05:39:23Z")

</div>

Your explanation makes me understand why need to use composition, my problem now is how to use InverseFunctions.jl correctly…

---

<div class="post-metadata">

### Author: ![uniment](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/uniment/32/24532_2.png) [@uniment](https://discourse.julialang.org/u/uniment)
#### Post date: [December 23, 2022, 8:21am UTC](https://discourse.julialang.org/t/how-to-use-inversefunctions-jl-that-can-calculate-the-inverse-of-a-function/91931/15 "2022-12-23T08:21:25Z")

</div>

This is what you must understand about using this package:

The only way that it “knows” how to invert a function, is through a lookup table.

For example, it has been programmed that the inverse of the function x\mapsto\sqrt x is y\mapsto y^2. _But how does it know that a function is_ x\mapsto \sqrt x _to begin with?_ **By reference. The only way it “knows” that the inverse of** `sqrt` **is a squaring function, is because it has been programmed that the inverse of the function we reference with the identifier** `sqrt` **is a squaring function.** And for the most part, this is how humans invert functions too.

This is best explained with an example:

```julia
julia> inverse(sqrt) # magic!
square (generic function with 2 methods)

julia> f(x) = sqrt(x) # same thing, right?
f (generic function with 1 method)

julia> inverse(f) # oh no! it has no idea!
NoInverse{typeof(f)}(f)

```

The moment we wrap `sqrt` in a new function, the package doesn’t know what the inverse is anymore. By inspection I can say that f(x)=\sqrt x for all x, but I can say this because I wrote it and I can see it; the `inverse` function has no clue what’s inside.

The same thing would happen if I blindfold you and give you a function f without telling what its definition is, and ask you to tell me the inverse; you wouldn’t be able to invert the function, even if it was really simple, because you don’t know what’s inside.

For contrast, let’s see what happens if we just create a new reference to the same function:

```julia
julia> w = sqrt # notice: this is just an assignment
sqrt (generic function with 19 methods)

julia> inverse(w) # it works!
square (generic function with 2 methods)

```

When I set `w = sqrt`, `w` is a new reference pointing to the same location in memory as `sqrt`, so `inverse` is able to identify that it’s the same thing.

As we’ve previously mentioned, when we create a more complicated function, we run into the same problem: `inverse` can’t tell what’s inside, unless we define the function as a composition of other functions.

This works because when I compose two functions using the `∘` operator, I create an object which has references to both functions. For example:

```julia
julia> exp ∘ sqrt
exp ∘ sqrt

julia> (exp ∘ sqrt).inner
sqrt (generic function with 19 methods)

julia> (exp ∘ sqrt).outer
exp (generic function with 14 methods)

```

This gives InverseFunctions.jl visibility into what functions have been composed to make the greater function, and as long as it has inverses defined for the `inner` and `outer` functions, it can invert the composition:

```julia
julia> inverse((exp ∘ sqrt).inner)
square (generic function with 2 methods)

julia> inverse((exp ∘ sqrt).outer)
log (generic function with 26 methods)

julia> inverse(exp ∘ sqrt)
InverseFunctions.square ∘ log

```

Notice that this works:

```julia
julia> s = exp
exp (generic function with 14 methods)

julia> t = sqrt
sqrt (generic function with 19 methods)

julia> inverse(s ∘ t)
InverseFunctions.square ∘ log

```

but this does not:

```julia
julia> u(x) = exp(x)
u (generic function with 1 method)

julia> v(x) = sqrt(x)
v (generic function with 1 method)

julia> inverse(u ∘ v)
NoInverse{ComposedFunction{typeof(u), typeof(v)}}(u ∘ v)

```

we can force it to work though by manually adding entries to the lookup table (by overloading the `inverse` function):

```julia
julia> InverseFunctions.inverse(::typeof(u)) = log

julia> InverseFunctions.inverse(::typeof(v)) = InverseFunctions.square

julia> inverse(u ∘ v)
InverseFunctions.square ∘ log

```

this isn’t useful in this case, because `u` and `v` are so simple they could have just been made to be references, but it could become useful later if you define more complicated functions.

* * *

So in your case, we want to invert a function x\mapsto \sqrt{4x}. We can write it as a composition of functions, (x\mapsto\sqrt x)\circ(x\mapsto 4x), but if we want to leverage InverseFunctions.jl’s power we need identifiers for these functions that it recognizes.

For the first function, we have the `sqrt` identifier.

And for the second? The function being called is multiplication, which is a binary operator. In order for multiplication to be invertible, we need to declare a single-argument function in terms of it: we need to fix one of its arguments. And that’s where `Base.Fix1(*, 4)` comes in: it’s a way to partially-apply the multiplication operator—resulting in a single-argument function—and because it’s built-in to the language, InverseFunctions.jl has been programmed to recognize it. (namely, for any two-argument function f, we can represent the function x\mapsto f(c, x) with `Base.Fix1(f, c)` and x\mapsto f(x, c) we can represent with `Base.Fix2(f, c)`).

And so we write:

```julia
julia> inverse(sqrt ∘ Base.Fix1(*, 4))
Base.Fix1{typeof(\), Int64}(\, 4) ∘ InverseFunctions.square

```

Now, something you have to be careful with, is that if you have previously declared `h` as a function (using _named function syntax_), you will get this error:

```julia
julia> h = inverse(sqrt ∘ Base.Fix1(*, 4))
ERROR: invalid redefinition of constant h

```

so we will need to either a) restart Julia so that we can give `h` a new meaning, or b) pick a different identifier such as `inv`:

```julia
julia> inv = inverse(sqrt ∘ Base.Fix1(*, 4))
Base.Fix1{typeof(\), Int64}(\, 4) ∘ InverseFunctions.square

julia> [inv(y) for y = 1:8]
8-element Vector{Float64}:
  0.25
  1.0
  2.25
  4.0
  6.25
  9.0
 12.25
 16.0

```

Now, if you think that learning about internals like `Base.Fix1` for this purpose is unsavory, I agree. Getting PR#24990 approved, along with a generalized partial function applicator and a function composition fallback [as laid out in points 1, 2, and 3 at the bottom of this post](https://discourse.julialang.org/t/summary-of-piping-chaining-proposal/91442/8) would solve this. But for now, if you just want something that works today and you don’t mind it being constrained to a macro call, `@optic` works quite well:

```julia
julia> using Accessors

julia> inv = inverse(@optic sqrt(4_))
Base.Fix1{typeof(\), Int64}(\, 4) ∘ InverseFunctions.square

```

* * *

> [@Freya\_the\_Goddess](#):
>
> Another question, I want to know another alternative to get the inverse of a function besides that package.

It’s also possible to use a numerical solver, for example:

```julia
julia> using Roots

julia> f(x) = √(4x)
f (generic function with 1 method)

julia> [fzero(x->f(x)-y, 0) for y=1:8]
8-element Vector{Float64}:
  0.25
  1.0000000000000002
  2.25
  4.0
  6.25
  9.0
 12.25
 16.0

```

Before jumping to the conclusion that numerical solvers are magic and solve all our problems, you need to be aware that some people spend their entire lives making them work and they _still_ don’t solve all our problems. They work sometimes though, and it’s nice when they do.

---

<div class="post-metadata">

### Author: ![Freya\_the\_Goddess](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/freya_the_goddess/32/36835_2.png) [@Freya\_the\_Goddess](https://discourse.julialang.org/u/Freya_the_Goddess)
#### Post date: [December 27, 2022, 2:46pm UTC](https://discourse.julialang.org/t/how-to-use-inversefunctions-jl-that-can-calculate-the-inverse-of-a-function/91931/16 "2022-12-27T14:46:38Z")

</div>

Thanks for all this explanations, I am still reading and try to comprehend all of them
