Skip to content

Commit 8b166f9

Browse files
authored
Add section on automatic differentiation to the README (#238)
1 parent 1cf747c commit 8b166f9

File tree

1 file changed

+39
-0
lines changed

1 file changed

+39
-0
lines changed

README.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,45 @@ the descriptions below from the specialized NLopt API.
137137
The `constrtol_abs` parameter is an absolute feasibility tolerance applied to
138138
all constraints.
139139

140+
## Automatic differetiation
141+
142+
Some algorithms in NLopt required derivatives, which you must manually provide
143+
in the `if length(grad) > 0` branch of your objective and constraint functions.
144+
145+
To stay simple and lightweighht, NLopt does not provide ways to automatically
146+
compute derivatives. If you do not have analytic expressions for the derivatives,
147+
use package such as [ForwardDiff.jl](https://github.com/JuliaDiff/ForwardDiff.jl)
148+
to compute automatic derivatives.
149+
150+
Here is an example of how to wrap a function `f(x::Vector)` using ForwardDiff so
151+
that it is compatible with NLopt:
152+
```julia
153+
using NLopt
154+
import ForwardDiff
155+
function autodiff(f::Function)
156+
function nlopt_fn(x::Vector, grad::Vector)
157+
if length(grad) > 0
158+
# Use ForwardDiff to compute the gradient. Replace with your
159+
# favorite Julia automatic differentiation package.
160+
ForwardDiff.gradient!(grad, f, x)
161+
end
162+
return f(x)
163+
end
164+
end
165+
# These functions do not implement `grad`:
166+
my_objective_fn(x::Vector) = sqrt(x[2]);
167+
my_constraint_fn(x::Vector, a, b) = (a * x[1] + b)^3 - x[2];
168+
opt = NLopt.Opt(:LD_MMA, 2)
169+
NLopt.lower_bounds!(opt, [-Inf, 0.0])
170+
NLopt.xtol_rel!(opt, 1e-4)
171+
# But we wrap them in autodiff before passing to NLopt:
172+
NLopt.min_objective!(opt, autodiff(my_objective_fn))
173+
NLopt.inequality_constraint!(opt, autodiff(x -> my_constraint_fn(x, 2, 0)), 1e-8)
174+
NLopt.inequality_constraint!(opt, autodiff(x -> my_constraint_fn(x, -1, 1)), 1e-8)
175+
min_f, min_x, ret = NLopt.optimize(opt, [1.234, 5.678])
176+
# (0.5443310477213124, [0.3333333342139688, 0.29629628951338166], :XTOL_REACHED)
177+
```
178+
140179
## Reference
141180

142181
The main purpose of this section is to document the syntax and unique features

0 commit comments

Comments
 (0)