I looked at the descriptions for uniroot and optimize and they are somewhat different but the book reference is the same and I am wondering if there are reasons to pick one over the other?
As for reasons to pick one over the other. In (probably) most cases one will be more natural. As @shadow says optimise
is for minimisation (or maximisation) and uniroot
is for finding zero points.
In some cases however you can use either to solve your problem. This will often be because you can take derivatives but there could be another some other way to restructure your problem. The rest of this answer will talk about these cases where you actually have a choice and need to choose between the two cases.
For a simple example we may want to find the minimum of the function:
Func = function(x) {
(2*x-pi)^2 + exp(1)*x - 18
}
One way to do this is to use optimize
as:
OResult = optimize(Func, lower = 0, upper = 5)
OResult
$minimum
[1] 1.231011
$objective
[1] -14.19195
Another way is to transform the function by taking the derivative. As the optimum point is when the derivative is zero we need a root-finding algorithm like uniroot. So the function becomes:
DerivFunction = function(x) {
4*(2*x-pi) + exp(1)
}
Which is optimized by:
UResult = uniroot(DerivFunction , interval = c(0,5))
UResult
$root
[1] 1.231011
$f.root
[1] 4.440892e-16
$iter
[1] 2
$init.it
[1] NA
$estim.prec
[1] 6.103516e-05
If you are choosing between the above too approaches you would probably go with optimize
for simplicity. There are cases in which uniroot
may be faster however.
Using the above example the optimize
function called the function 7 times while the uniroot only called the derivative function 5 times. (This can be found by putting counters in the above functions). This is logical, optimize doesn't know how low the minima is while uniroot does know to aim for a function value of zero. So uniroot will often know what direction to go in x axis whilst optimize will need to look around more.
If we do a benchmark optimize is much faster however.
So in general (if you are looking at speed) use optimize unless it is a very intensive function where function calls are more expensive than what the optimization algorithm is doing (of course in these cases often it will be very difficult to get a form of the problem to use uniroot
on).
library(microbenchmark)
microbenchmark(
optimize(Func, lower = 0, upper = 5),
uniroot(DerivFunction, interval = c(0,5))
)
Unit: microseconds
expr min lq mean median uq max neval
optimize(Func, lower = 0, upper = 5) 18.264 19.785 23.50664 20.7370 23.781 129.365 100
uniroot(DerivFunction, interval = c(0, 5)) 63.161 67.346 74.10322 69.8195 76.858 143.062 100
The optimize function may not find a global optima but merely a local optima. The same in true for uniroot
which may find a local zero but not others that exist. uniroot
is different from optimize
however as while you set optimize to find either a maximum or a minimum, uniroot
will find a point that crosses the y axis. If you uniroot
for a derivative then this point could be a minima or a maxima.
For instance if we have the following function and derivative:
TwoMinFunction = function(x){
((x)^4)/4 + x^3 - 3*x^2 - 8*x + 16
}
TwoZeroDerivFunction = function(x){
(x^3 + 3*x^2 − 6*x − 8)
}
This function is as shown in the following figure:
OResult = optimize(TwoMinFunction, lower = -6, upper = 4)
OResult
$minimum
[1] -4.000001
$objective
[1] 8.007817e-12
UResult = uniroot(TwoZeroDerivFunction , interval = c(-6,4))
UResult
$root
[1] -1
$f.root
[1] 0
$iter
[1] 1
$init.it
[1] NA
$estim.prec
[1] 5
What happened here is that optimize found one of the two minima. The uniroot function on the other hand found a maxima (as uniroot cannot differentiate between minima and maxima).
The two functions have entirely different purposes:
optimize
is used to find the minimum (or maximum) of a function.
uniroot
is used to find the root (zero) of a function.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With