Skip to content

Root Finding

Root finding means finding the zero of a function, i.e., find \(x^*\) such that \(f(x^*) = 0\).

For this type of problem, we use code packaged into reusable libraries, called "packages". See the Section on Packages.

In this case, we will use Roots.jl.

Before we can use Roots, we need to add it as a dependency to the current environment:

julia> cd("/Users/lutz/Documents/data/web/professional/docs/econ890/julia/")
(@v1.5) pkg> activate .
 Activating new environment at `~/Documents/data/web/professional/docs/econ890/julia/Project.toml`

We have now activated the environment described by Project.toml in this directory.

To get the Pkg commands to work, type ] and the pkg> prompt appears. Backspace backs out of the Pkg mode in the REPL.

To see which packages are already contained in the enviroment:

(julia) pkg> st
Status `~/Documents/data/web/professional/docs/econ890/julia/Project.toml` (empty project)

This makes sense; we have not added any packages yet. But keep in mind that everything we activated before (including all packages in your v1.5 environment are still available). Let's add Roots:

(julia) pkg> add Roots
   Updating registry at `~/.julia/registries/General`
######################################################################## 100.0%
   Updating registry at `~/.julia/registries/registryLH`
   Updating git-repo `https://github.com/hendri54/registryLH`
  Resolving package versions...
Updating `~/Documents/data/web/professional/docs/econ890/julia/Project.toml`
  [f2b01f46] + Roots v1.0.8
Updating `~/Documents/data/web/professional/docs/econ890/julia/Manifest.toml`
  [f2b01f46] + Roots v1.0.8
  [de0858da] + Printf
  [4ec0a83e] + Unicode

(julia) pkg> st
Status `~/Documents/data/web/professional/docs/econ890/julia/Project.toml`
  [f2b01f46] Roots v1.0.8

Now using Roots works.

Roots is a registered package, so it can be installed with pkg> add Roots. The package manager looks up where to find the files for Roots in the General Registry and downloads them.

The code for Roots now resides in a subdirectory of .julia/packages. Each version of Roots gets its own subdirectory. So you can have several versions installed at the same time.

But: Only one version of a package can be loaded at any given time. This can lead to interesting problems...

Note that all of the dependencies of Roots were also installed automatically (in this case, Printf and Unicode).

Now we can use all functions that were exported by Roots.jl. For example:

help?> find_zero
search: find_zero find_zeros find_zero!

  find_zero(fs, x0, M, [N::AbstractBracketing]; kwargs...)

  Interface to one of several methods for find zeros of a univariate function.
[...]

julia> f(x) = exp(x) - x^4;

julia> find_zero(f, (8, 9), Bisection())
8.6131694564414

Closures

We encounter a common problem: find_zero expects a one-argument function f(x). But the function that we use takes 2 arguments: a model and \(c_T\). This type of problem is solved using a closure.

A closure is a function that "captures" some of the variables in the calling namespace. Example:

julia> function foo()
         x = 1;
         g(y) = x + y;
         @show g(2)
         x = 2;
         @show g(2)
       end
foo (generic function with 1 method)

julia> foo()
g(2) = 3
g(2) = 4

Note that g has "captured" the variable x from foo. g behaves as if there were an implicit second argument.

Anonymous functions

When closures are used, they often remain unnamed. Example:

julia> findfirst(x -> x > 2, 1:10)
3
# This is the same as
julia> f(x) = x > 2;

julia> findfirst(f, 1:10)
3

But note:

julia> [x -> x^2  for x in (1,2,3)]
3-element Array{var"#9#11",1}:
 #9 (generic function with 1 method)
 #9 (generic function with 1 method)
 #9 (generic function with 1 method)