Optimization of Curves

What is a good option for finding the x value of a tangent point of a curve (such as matching price and value), or finding the minimum or maximum of a curve.

Depends — what kind of curve do you have, and how is it specified?

1 Like

Elsewhere I was shown how to use the intermediate value theorem. I also would want to find local minimums and maximums, critical values and Fermat’s theorem.

I’m not entirely sure what you mean by curves. It would be for continuous functions.

For example, do you have a smooth function of a single variable, and a program that can evaluate this function at any desired point?

If so, you can use ApproxFun.jl for this sort of thing. You can give it a smooth function on an interval and ask for all of the extrema, find where the derivative matches a certain value, etcetera.

2 Likes

Ok thanks, I can look into that, I think most are smooth variables, some periodic or with several minima, I was using Roots, to find the point of a curve with a slope of .01, but it didn’t give the number.

using Roots
∂xf(x)=0.1 * exp(0.1 * x)
g(x) = ∂xf(x)- .01
find_zeros(g, -1, 1)  

it just says float64

find_zeros returns Float64[], an empty array of Float64 to let you know that there are no zeros of the given function over that interval. Perhaps you meant g(x) = ∂xf(x)- .1?

1 Like

Yeah my bad, I figured it out, x=-23… so when I changed the range to -100,100 it worked perfectly. Is there a way to set it so that I can have

using Roots
∂xf(x)=0.1 * exp(0.1 * x)
g(x) = ∂xf(x)- .01
t=find_zeros(g, -100, 100)  
dy=f(t)

I’m assuming f is a function of a single variable, and find_zeros returns an array of values (possibly of length 1, but not guaranteed, as you discovered). In that case, not without sorting out the zero you are looking for or broadcasting f over the returned values. However, if you know there is only one zero, say through monotonicity or some other property, you can use bisection, as in t = find_zero(g, a, b) which will return a number, not a vector. As an aside, a more robust alternative to find_zeros (though maybe even a bit more difficult to work with the output) is IntervalRootFinding's roots function.

1 Like

Here’s how to use IntervalRootFinding.jl for that, trying to address @j_verzani’s valid point about the output being difficult to use. (The timing is on the second run, i.e. post compilation.)

julia> using IntervalArithmetic, IntervalRootFinding

julia> g(x) = 0.1 * exp(0.1 * x) - 0.01
g (generic function with 1 method)

julia> @time rts = roots(g, -Inf..Inf)
  0.110170 seconds (30.03 k allocations: 1.707 MiB)
1-element Array{Root{Interval{Float64}},1}:
 Root([-23.0259, -23.0258], :unique)

julia> rts2 = mid.(interval.(rts))
1-element Array{Float64,1}:
 -23.025850929389335

The first result proves that there is a unique root of this function on the real line (since only one result was returned in the array).
The second returns a good approximation as floats.

EDIT: You can also get more accurate roots by using BigFloats once you’ve found these first approximations:

julia> @time rts3 = roots(g, big.(rts), Newton, 1e-50)
  0.002826 seconds (1.45 k allocations: 84.455 KiB)
1-element Array{Root{Interval{BigFloat}},1}:
 Root([-23.0259, -23.0258]₂₅₆, :unique)

julia> diam.(rts3)   # diameters (widths) of the intervals
1-element Array{BigFloat,1}:
8.29072181289066684037089778828838358827136034985883012962275533136184813103593e-76

julia> rts4 = mid.(interval.(rts3))
1-element Array{BigFloat,1}: -23.02585092994045684017991454684364207601101488628772976033327900967572609677374

In general it is not possible to use an actual infinite interval. In that case you can just use a very wide interval like -1e10..1e10.

You can also use this together with e.g. ForwardDiff for automatic differentiation, if you need to use derivatives of a given function.

3 Likes