From 0b1f188d9300129c76d08fb8862b414da59fc595 Mon Sep 17 00:00:00 2001
From: Oscar Dowson <odow@users.noreply.github.com>
Date: Fri, 13 Sep 2024 12:06:15 +1200
Subject: [PATCH] [README] add example of how to trace iterations

---
 README.md | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)

diff --git a/README.md b/README.md
index 1b49130..c0146ae 100644
--- a/README.md
+++ b/README.md
@@ -82,6 +82,60 @@ solution status       : XTOL_REACHED
 # function evaluation : 11
 ```
 
+### Trace iterations
+
+A common feature request is for a callback that can used to trace the solution
+over the iterations of the optimizer.
+    
+There is no native support for this in NLopt. Instead, add the callback to your
+objective function.
+
+```julia
+julia> using NLopt
+
+julia> begin
+           trace = Any[]
+           function my_objective_fn(x::Vector, grad::Vector)
+               if length(grad) > 0
+                   grad[1] = 0
+                   grad[2] = 0.5 / sqrt(x[2])
+               end
+               value = sqrt(x[2])
+               push!(trace, copy(x) => value)
+               return value
+           end
+           function my_constraint_fn(x::Vector, grad::Vector, a, b)
+               if length(grad) > 0
+                   grad[1] = 3 * a * (a * x[1] + b)^2
+                   grad[2] = -1
+               end
+               return (a * x[1] + b)^3 - x[2]
+           end
+           opt = NLopt.Opt(:LD_MMA, 2)
+           NLopt.lower_bounds!(opt, [-Inf, 0.0])
+           NLopt.xtol_rel!(opt, 1e-4)
+           NLopt.min_objective!(opt, my_objective_fn)
+           NLopt.inequality_constraint!(opt, (x, g) -> my_constraint_fn(x, g, 2, 0), 1e-8)
+           NLopt.inequality_constraint!(opt, (x, g) -> my_constraint_fn(x, g, -1, 1), 1e-8)
+           min_f, min_x, ret = NLopt.optimize(opt, [1.234, 5.678])
+       end
+(0.5443310477213124, [0.3333333342139688, 0.29629628951338166], :XTOL_REACHED)
+
+julia> trace
+11-element Vector{Any}:
+                            [1.234, 5.678] => 2.382855429941145
+   [0.8787394664016357, 5.551370325142423] => 2.3561346152421816
+   [0.8262160034228196, 5.043903787432386] => 2.245863706334912
+  [0.4739440370386794, 4.0767726724255375] => 2.0191019470114773
+    [0.35389779634506047, 3.0308503583016] => 1.7409337604577608
+ [0.33387310647853335, 1.9717933962872487] => 1.4042056104029954
+  [0.3333337209575201, 1.0450874902862517] => 1.0222952070152005
+ [0.33333357431034494, 0.4695027039311135] => 0.6852026736164369
+  [0.3333332772332185, 0.3057923933552822] => 0.5529849847466767
+ [0.33333339455750244, 0.2963215980646768] => 0.5443542946139737
+ [0.3333333342139688, 0.29629628951338166] => 0.5443310477213124
+```
+
 ## Use with JuMP
 
 NLopt implements the [MathOptInterface interface](https://jump.dev/MathOptInterface.jl/stable/reference/nonlinear/)