How to learn how to solve equations in Julia 1.0?

How to learn how to solve equations in Julia 1.0? Because I am a beginner, I am only interested in relatively simple problems such as basic optimization. I found a book that seemed relevant but it predates Julia 1.0: Julia Programming for Operations Research: A Primer on Computing.

For example, I have the equation:

1/((1+p)^30)*10,000=100

I need to solve p. How to do it in Julia 1.0?

The example was recently discussed on Statalist. In addition to a partial programming solution in Stata, one user suggested to simply type the input online into Wolfram Alpha which works as a simple non-Julia solution. I considered the Julia packages JuMP.jl, Optim.jl and IterativeSolvers.jl but none seem ready for 1.0. My only attempt in Julia was to simply type the input but then I get this error:

julia> 1/((1+p)^30)*10,000=100
ERROR: syntax: "(1 / ((1 + p) ^ 30))" is not a valid function argument name

I looked at the Julia manual for functions but could not find a relevant usage example.

Take a look at NLsolve.jl

But, you need to have some basic knowledge of programming and understand the syntax of Julia before you can take any benefit from using Julia. The Julia Manual is mainly about the language itself. For a concrete application like solving equations, one typically loads a package for that purpose.

2 Likes

Are you sure, it seems JuMP on master may be ready for 1.0/0.7 (and the others too). You may want to wait for it tagged, or not:

From 5 hours ago (as not merged, I’m not sure if this is complete):

As Norman says, you should try to familiarise yourself with basic programming notions to get a feel for how you can translate your problems into code.

The Statalist post you linked sort of explains how you can achieve what you’re trying to do, so porting it to Julia shouldn’t be too hard. You’d have to take a two-step approach:

  1. Translate your mathematical expression into a Julia function. This could be e.g.:
function to_solve(p)
    return abs(1 / ( (1+p)^30 ) * 10_000 - 100)
end

or as a one-liner:

to_solve(p) = abs(1 / ( (1+p)^30 ) * 10_000 - 100)

The basic idea here being that you transform it into a function for which the minimum is zero (namely for the p that sets the left hand side of the original equation to 100.

  1. Then you need to find a solver to plug this function into, which essentially applies an algorithm to search over different values of p to find the one that minimizes the function - your original post has some options for this, with Norman giving you another one. You need to check the solver’s documentation to understand how to call the function that finds your solution.

FWIW I see some deprecation warnings on Optim.jl currently on 0.7 but it seems to work.

2 Likes

How is that possible as it now requires 1.0? I thought you only get the warnings in 0.7 (when applies) and errors in 1.0. Did you maybe not update to the latest version?

EDIT: I see it now, using Julia 0.7 will keep you on older 0.16.0, while 1.0 will enable you to upgrade to latest 0.17.1.

I’m guessing Julia 1.0 is now recommended; and increasingly for other packages too (I thought I should recommend 0.7 to users, over 1.0, but that seems outdated, if it ever was true, for non-package developers).

1 Like

That might well be the case - I haven’t had to solve an optimisation problem in a while so am not following along closely with the relevant packages. I’m on Optim 0.16.0.

For functions of a single variable, the simplest solution is the Roots.jl package:

julia> ]add Roots

julia> using Roots

julia> f(p) = 1 / ((1 + p) ^ 30) * 10000 - 100
f (generic function with 1 method)

julia> find_zero(f, 1.0)
0.16591440117983175

julia> find_zero(f, -3.0)
-2.165914401179832

julia> find_zeros(f, -1000, 1000)
2-element Array{Float64,1}:
 -2.1659144011798315
  0.16591440117983178

You can also use the IntervalRootFinding package, which guarantees (in the best cases) to find all roots and guarantee that they are unique within the respective found intervals:

julia> using IntervalArithmetic, IntervalRootFinding
WARNING: using IntervalRootFinding.Bisection in module Main conflicts with an existing identifier.

julia> roots(f, -∞..∞)
2-element Array{Root{Interval{Float64}},1}:
 Root([0.165914, 0.165915], :unique)
 Root([-2.16592, -2.16591], :unique)
6 Likes

Is that using NL solve?