JuliaNLSolvers / NLsolve.jl

Julia solvers for systems of nonlinear equations and mixed complementarity problems
Other
329 stars 66 forks source link

API to access trace #246

Open floswald opened 4 years ago

floswald commented 4 years ago

i'd find it very handy to get both x and F traces from a returned object, like

x=nlsolve(f!, j!, [ 0.1; 1.2],store_trace = true,extended_trace = true)
xtrace(x)
ftrace(x)

basically a shortcut for

julia> vcat([(x.trace[i].metadata["f(x)"])' for i in 1:x.iterations]...)
4×2 Array{Float64,2}:
 1.6568       0.320451
 0.375216     0.0164459
 0.00739956  -0.00032626
 4.3425e-7   -1.25053e-8

thoughts?

pkofod commented 4 years ago

Yes, I thought it was already possible, but I think I only did that for Optim, https://github.com/JuliaNLSolvers/Optim.jl/blob/master/src/api.jl#L8 . Should be possible to more or less copy those here.

floswald commented 3 years ago

it seems that in a recent version the metadata entry is no longer populated. how can I get the x and f traces?

r = nlsolve(f!, j!, [ 0.1; 1.2],store_trace = true)

julia> r.trace
Iter     f(x) inf-norm    Step 2-norm 
------   --------------   --------------
     0     1.656800e+00              NaN
     1     3.752158e-01     2.039103e-01
     2     7.399559e-03     3.379446e-02
     3     4.342501e-07     7.786475e-04
     4     3.552714e-15     4.361577e-08

julia> dump(r)
NLsolve.SolverResults{Float64,Float64,Array{Float64,1},Array{Float64,1}}
  method: String "Trust-region with dogleg and autoscaling"
  initial_x: Array{Float64}((2,)) [0.1, 1.2]
  zero: Array{Float64}((2,)) [-3.7818049096324184e-16, 1.0000000000000002]
  residual_norm: Float64 3.552713678800501e-15
  iterations: Int64 4
  x_converged: Bool false
  xtol: Float64 0.0
  f_converged: Bool true
  ftol: Float64 1.0e-8
  trace: NLsolve.SolverTrace
    states: Array{NLsolve.SolverState}((5,))
      1: NLsolve.SolverState{Float64}
        iteration: Int64 0
        fnorm: Float64 1.6568000000000005
        stepnorm: Float64 NaN
        metadata: Dict{Any,Any}
          slots: Array{UInt8}((16,)) UInt8[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
          keys: Array{Any}((16,))
            1: #undef
            2: #undef
            3: #undef
            4: #undef
            5: #undef
            ...
            12: #undef
            13: #undef
            14: #undef
            15: #undef
            16: #undef
          vals: Array{Any}((16,))
            1: #undef
            2: #undef
            3: #undef
            4: #undef
            5: #undef
            ...
            12: #undef
            13: #undef
            14: #undef
            15: #undef
            16: #undef
          ndel: Int64 0
          count: Int64 0
          age: UInt64 0x0000000000000000
          idxfloor: Int64 1
          maxprobe: Int64 0
      2: NLsolve.SolverState{Float64}
        iteration: Int64 1
        fnorm: Float64 0.3752157650857306
        stepnorm: Float64 0.20391031379570138
        metadata: Dict{Any,Any}
          slots: Array{UInt8}((16,)) UInt8[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
          keys: Array{Any}((16,))
            1: #undef
            2: #undef
            3: #undef
            4: #undef
            5: #undef
            ...
            12: #undef
            13: #undef
            14: #undef
            15: #undef
            16: #undef
          vals: Array{Any}((16,))
            1: #undef
            2: #undef
            3: #undef
            4: #undef
            5: #undef
            ...
            12: #undef
            13: #undef
            14: #undef
            15: #undef
            16: #undef
          ndel: Int64 0
          count: Int64 0
          age: UInt64 0x0000000000000000
          idxfloor: Int64 1
          maxprobe: Int64 0
      3: NLsolve.SolverState{Float64}
        iteration: Int64 2
        fnorm: Float64 0.007399559061358474
        stepnorm: Float64 0.03379445711009191
        metadata: Dict{Any,Any}
          slots: Array{UInt8}((16,)) UInt8[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
          keys: Array{Any}((16,))
            1: #undef
            2: #undef
            3: #undef
            4: #undef
            5: #undef
            ...
            12: #undef
            13: #undef
            14: #undef
            15: #undef
            16: #undef
          vals: Array{Any}((16,))
            1: #undef
            2: #undef
            3: #undef
            4: #undef
            5: #undef
            ...
            12: #undef
            13: #undef
            14: #undef
            15: #undef
            16: #undef
          ndel: Int64 0
          count: Int64 0
          age: UInt64 0x0000000000000000
          idxfloor: Int64 1
          maxprobe: Int64 0
      4: NLsolve.SolverState{Float64}
        iteration: Int64 3
        fnorm: Float64 4.3425005102903924e-7
        stepnorm: Float64 0.0007786475321158225
        metadata: Dict{Any,Any}
          slots: Array{UInt8}((16,)) UInt8[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
          keys: Array{Any}((16,))
            1: #undef
            2: #undef
            3: #undef
            4: #undef
            5: #undef
            ...
            12: #undef
            13: #undef
            14: #undef
            15: #undef
            16: #undef
          vals: Array{Any}((16,))
            1: #undef
            2: #undef
            3: #undef
            4: #undef
            5: #undef
            ...
            12: #undef
            13: #undef
            14: #undef
            15: #undef
            16: #undef
          ndel: Int64 0
          count: Int64 0
          age: UInt64 0x0000000000000000
          idxfloor: Int64 1
          maxprobe: Int64 0
      5: NLsolve.SolverState{Float64}
        iteration: Int64 4
        fnorm: Float64 3.552713678800501e-15
        stepnorm: Float64 4.3615772673215287e-8
        metadata: Dict{Any,Any}
          slots: Array{UInt8}((16,)) UInt8[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
          keys: Array{Any}((16,))
            1: #undef
            2: #undef
            3: #undef
            4: #undef
            5: #undef
            ...
            12: #undef
            13: #undef
            14: #undef
            15: #undef
            16: #undef
          vals: Array{Any}((16,))
            1: #undef
            2: #undef
            3: #undef
            4: #undef
            5: #undef
            ...
            12: #undef
            13: #undef
            14: #undef
            15: #undef
            16: #undef
          ndel: Int64 0
          count: Int64 0
          age: UInt64 0x0000000000000000
          idxfloor: Int64 1
          maxprobe: Int64 0
  f_calls: Int64 5
  g_calls: Int64 5
pkofod commented 3 years ago

Seems like a bug. I'll look.

pkofod commented 3 years ago

I think you always had to use extended_trace for the vectors to be stored.

floswald commented 3 years ago

So store_trace and extended_trace need to be true?

pkofod commented 3 years ago

Yes, that's also what you did in the first comment.

pkofod commented 3 years ago

This is to avoid storing all the arrays unless you're very certain that you want to. It's the same in Optim where the store_trace only enables saving of the objective value (a scalar) and the gradient norm (a scalar). You need extended_trace for x, g, and H to be stored. I've opened #262

floswald commented 3 years ago

Oh no! Of course. Sorry!