Debug output
Debug output can easily be added to any solver run. On the high level interfaces, like gradient_descent
, you can just use the debug=
keyword.
Manopt.DebugAction
— TypeDebugAction
A DebugAction
is a small functor to print/issue debug output. The usual call is given by (p::AbstractManoptProblem, s::AbstractManoptSolverState, k) -> s
, where i
is the current iterate.
By convention i=0
is interpreted as "For Initialization only," only debug info that prints initialization reacts, i<0
triggers updates of variables internally but does not trigger any output.
Fields (assumed by subtypes to exist)
print
method to perform the actual print. Can for example be set to a file export,
or to @info. The default is the print
function on the default Base.stdout
.
Manopt.DebugChange
— TypeDebugChange(M=DefaultManifold(); kwargs...)
debug for the amount of change of the iterate (stored in get_iterate(o)
of the AbstractManoptSolverState
) during the last iteration. See DebugEntryChange
for the general case
Keyword parameters
storage=
StoreStateAction
( [:Gradient] )
storage of the previous actionprefix="Last Change:"
: prefix of the debug output (ignored if you setformat
)io=stdout
: default stream to print the debug to.inverse_retraction_method=
default_inverse_retraction_method
(M, typeof(p))
: an inverse retraction $\operatorname{retr}^{-1}$ to use, see the section on retractions and their inverses
the inverse retraction to be used for approximating distance.
Manopt.DebugCost
— TypeDebugCost <: DebugAction
print the current cost function value, see get_cost
.
Constructors
DebugCost()
Parameters
format="$prefix %f"
: format to print the outputio=stdout
: default stream to print the debug to.long=false
: short form to set the format tof(x):
(default) orcurrent cost:
and the cost
Manopt.DebugDivider
— TypeDebugDivider <: DebugAction
print a small divider (default " | "
).
Constructor
DebugDivider(div,print)
Manopt.DebugEntry
— TypeDebugEntry <: DebugAction
print a certain fields entry during the iterates, where a format
can be specified how to print the entry.
Additional fields
field
: symbol the entry can be accessed with withinAbstractManoptSolverState
Constructor
DebugEntry(f; prefix="$f:", format = "$prefix %s", io=stdout)
Manopt.DebugEntryChange
— TypeDebugEntryChange{T} <: DebugAction
print a certain entries change during iterates
Additional fields
print
: function to print the resultprefix
: prefix to the print outformat
: format to print (uses theprefix
by default and scientific notation)field
: Symbol the field can be accessed with withinAbstractManoptSolverState
distance
: function (p,o,x1,x2) to compute the change/distance between two values of the entrystorage
: aStoreStateAction
to store the previous value of:f
Constructors
DebugEntryChange(f,d)
Keyword arguments
io=stdout
: anIOStream
used for the debugprefix="Change of $f"
: the prefixstorage=StoreStateAction((f,))
: aStoreStateAction
initial_value=NaN
: an initial value for the change ofo.field
.format="$prefix %e"
: format to print the change
Manopt.DebugEvery
— TypeDebugEvery <: DebugAction
evaluate and print debug only every $k$th iteration. Otherwise no print is performed. Whether internal variables are updates is determined by always_update
.
This method does not perform any print itself but relies on it's children's print.
It also sets the subsolvers active parameter, see |DebugWhenActive
}(#ref). Here, the activattion_offset
can be used to specify whether it refers to this iteration, the i
th, when this call is before the iteration, then the offset should be 0, for the next iteration, that is if this is called after an iteration, it has to be set to 1. Since usual debug is happening after the iteration, 1 is the default.
Constructor
DebugEvery(d::DebugAction, every=1, always_update=true, activation_offset=1)
Manopt.DebugFeasibility
— TypeDebugFeasibility <: DebugAction
Display information about the feasibility of the current iterate
Fields
atol
: absolute tolerance for when either equality or inequality constraints are counted as violatedformat
: a vector of symbols and string formatting the outputio
: default stream to print the debug to.
The following symbols are filled with values
:Feasbile
display true or false depending on whether the iterate is feasible:FeasbileEq
display=
or≠
equality constraints are fulfilled or not:FeasbileInEq
display≤
or≰
inequality constraints are fulfilled or not:NumEq
display the number of equality constraints infeasible:NumEqNz
display the number of equality constraints infeasible if exists:NumIneq
display the number of inequality constraints infeasible:NumIneqNz
display the number of inequality constraints infeasible if exists:TotalEq
display the sum of how much the equality constraints are violated:TotalInEq
display the sum of how much the inequality constraints are violated
format to print the output.
Constructor
DebugFeasibility( format=["feasible: ", :Feasible]; io::IO=stdout, atol=1e-13 )
Manopt.DebugGradientChange
— TypeDebugGradientChange()
debug for the amount of change of the gradient (stored in get_gradient(o)
of the AbstractManoptSolverState
o
) during the last iteration. See DebugEntryChange
for the general case
Keyword parameters
storage=
StoreStateAction
( (:Gradient,) )
: storage of the action for previous dataprefix="Last Change:"
: prefix of the debug output (ignored if you setformat
:io=stdout
: default stream to print the debug to.format="$prefix %f"
: format to print the output
Manopt.DebugGroup
— TypeDebugGroup <: DebugAction
group a set of DebugAction
s into one action, where the internal prints are removed by default and the resulting strings are concatenated
Constructor
DebugGroup(g)
construct a group consisting of an Array of DebugAction
s g
, that are evaluated en bloque
; the method does not perform any print itself, but relies on the internal prints. It still concatenates the result and returns the complete string
Manopt.DebugIfEntry
— TypeDebugIfEntry <: DebugAction
Issue a warning, info, or error if a certain field does not pass a the check
.
The message
is printed in this case. If it contains a @printf
argument identifier, that one is filled with the value of the field
. That way you can print the value in this case as well.
Fields
io
: anIO
streamcheck
: a function that takes the value of thefield
as input and returns a booleanfield
: symbol the entry can be accessed with withinAbstractManoptSolverState
msg
: if thecheck
fails, this message is displayedtype
: symbol specifying the type of display, possible values:print
,: warn
,:info
,:error
, where:print
prints toio
.
Constructor
DebugEntry(field, check=(>(0)); type=:warn, message=":$f is nonnegative", io=stdout)
Manopt.DebugIterate
— TypeDebugIterate <: DebugAction
debug for the current iterate (stored in get_iterate(o)
).
Constructor
DebugIterate(; kwargs...)
Keyword arguments
io=stdout
: default stream to print the debug to.format="$prefix %s"
: format how to print the current iteratelong=false
: whether to have a long ("current iterate:"
) or a short ("p:"
) prefix defaultprefix
: (seelong
for default) set a prefix to be printed before the iterate
Manopt.DebugIteration
— TypeDebugIteration <: DebugAction
Constructor
DebugIteration()
Keyword parameters
format="# %-6d"
: format to print the outputio=stdout
: default stream to print the debug to.
debug for the current iteration (prefixed with #
by )
Manopt.DebugMessages
— TypeDebugMessages <: DebugAction
An AbstractManoptSolverState
or one of its sub steps like a Stepsize
might generate warnings throughout their computations. This debug can be used to :print
them display them as :info
or :warnings
or even :error
, depending on the message type.
Constructor
DebugMessages(mode=:Info, warn=:Once; io::IO=stdout)
Initialize the messages debug to a certain mode
. Available modes are
:Error
: issue the messages as an error and hence stop at any issue occurring:Info
: issue the messages as an@info
:Print
: print messages to the steamio
.:Warning
: issue the messages as a warning
The warn
level can be set to :Once
to only display only the first message, to :Always
to report every message, one can set it to :No
, to deactivate this, then this DebugAction
is inactive. All other symbols are handled as if they were :Always:
Manopt.DebugSolverState
— TypeDebugSolverState <: AbstractManoptSolverState
The debug state appends debug to any state, they act as a decorator pattern. Internally a dictionary is kept that stores a DebugAction
for several occasions using a Symbol
as reference.
The original options can still be accessed using the get_state
function.
Fields
options
: the options that are extended by debug informationdebugDictionary
: aDict{Symbol,DebugAction}
to keep track of Debug for different actions
Constructors
DebugSolverState(o,dA)
construct debug decorated options, where dD
can be
- a
DebugAction
, then it is stored within the dictionary at:Iteration
- an
Array
ofDebugAction
s. - a
Dict{Symbol,DebugAction}
. - an Array of Symbols, String and an Int for the
DebugFactory
Manopt.DebugStoppingCriterion
— TypeDebugStoppingCriterion <: DebugAction
print the Reason provided by the stopping criterion. Usually this should be empty, unless the algorithm stops.
Fields
prefix=""
: format to print the outputio=stdout
: default stream to print the debug to.
Constructor
DebugStoppingCriterion(prefix = ""; io::IO=stdout)
Manopt.DebugTime
— TypeDebugTime()
Measure time and print the intervals. Using start=true
you can start the timer on construction, for example to measure the runtime of an algorithm overall (adding)
The measured time is rounded using the given time_accuracy
and printed after canonicalization.
Keyword parameters
io=stdout
: default stream to print the debug to.format="$prefix %s"
: format to print the output, where%s
is the canonicalized time`.mode=:cumulative
: whether to display the total time or reset on every call using:iterative
.prefix="Last Change:"
: prefix of the debug output (ignored if you setformat
:start=false
: indicate whether to start the timer on creation or not. Otherwise it might only be started on first call.time_accuracy=Millisecond(1)
: round the time to this period before printing the canonicalized time
Manopt.DebugWarnIfCostIncreases
— TypeDebugWarnIfCostIncreases <: DebugAction
print a warning if the cost increases.
Note that this provides an additional warning for gradient descent with its default constant step size.
Constructor
DebugWarnIfCostIncreases(warn=:Once; tol=1e-13)
Initialize the warning to warning level (:Once
) and introduce a tolerance for the test of 1e-13
.
The warn
level can be set to :Once
to only warn the first time the cost increases, to :Always
to report an increase every time it happens, and it can be set to :No
to deactivate the warning, then this DebugAction
is inactive. All other symbols are handled as if they were :Always:
Manopt.DebugWarnIfCostNotFinite
— TypeDebugWarnIfCostNotFinite <: DebugAction
A debug to see when a field (value or array within the AbstractManoptSolverState is or contains values that are not finite, for example Inf
or Nan
.
Constructor
DebugWarnIfCostNotFinite(field::Symbol, warn=:Once)
Initialize the warning to warn :Once
.
This can be set to :Once
to only warn the first time the cost is Nan. It can also be set to :No
to deactivate the warning, but this makes this Action also useless. All other symbols are handled as if they were :Always:
Manopt.DebugWarnIfFieldNotFinite
— TypeDebugWarnIfFieldNotFinite <: DebugAction
A debug to see when a field from the options is not finite, for example Inf
or Nan
Constructor
DebugWarnIfFieldNotFinite(field::Symbol, warn=:Once)
Initialize the warning to warn :Once
.
This can be set to :Once
to only warn the first time the cost is Nan. It can also be set to :No
to deactivate the warning, but this makes this Action also useless. All other symbols are handled as if they were :Always:
Example
DebugWaranIfFieldNotFinite(:Gradient)
Creates a [DebugAction
] to track whether the gradient does not get Nan
or Inf
.
Manopt.DebugWarnIfGradientNormTooLarge
— TypeDebugWarnIfGradientNormTooLarge{T} <: DebugAction
A debug to warn when an evaluated gradient at the current iterate is larger than (a factor times) the maximal (recommended) stepsize at the current iterate.
Constructor
DebugWarnIfGradientNormTooLarge(factor::T=1.0, warn=:Once)
Initialize the warning to warn :Once
.
This can be set to :Once
to only warn the first time the cost is Nan. It can also be set to :No
to deactivate the warning, but this makes this Action also useless. All other symbols are handled as if they were :Always:
Example
DebugWaranIfFieldNotFinite(:Gradient)
Creates a [DebugAction
] to track whether the gradient does not get Nan
or Inf
.
Manopt.DebugWhenActive
— TypeDebugWhenActive <: DebugAction
evaluate and print debug only if the active boolean is set. This can be set from outside and is for example triggered by DebugEvery
on debugs on the subsolver.
This method does not perform any print itself but relies on it's children's prints.
For now, the main interaction is with DebugEvery
which might activate or deactivate this debug
Fields
active
: a boolean that can (de-)activated from outside to turn on/off debugalways_update
: whether or not to call the order debugs with iteration<=0
inactive state
Constructor
DebugWhenActive(d::DebugAction, active=true, always_update=true)
Manopt.DebugActionFactory
— MethodDebugActionFactory(s)
create a DebugAction
where
- a
String
yields the corresponding divider - a
DebugAction
is passed through - a [
Symbol
] createsDebugEntry
of that symbol, with the exceptions of:Change
,:Iterate
,:Iteration
, and:Cost
. - a
Tuple{Symbol,String}
creates aDebugEntry
of that symbol where the String specifies the format.
Manopt.DebugActionFactory
— MethodDebugActionFactory(s::Symbol)
Convert certain Symbols in the debug=[ ... ]
vector to DebugAction
s Currently the following ones are done. Note that the Shortcut symbols should all start with a capital letter.
:Cost
creates aDebugCost
:Change
creates aDebugChange
:Gradient
creates aDebugGradient
:GradientChange
creates aDebugGradientChange
:GradientNorm
creates aDebugGradientNorm
:Iterate
creates aDebugIterate
:Iteration
creates aDebugIteration
:IterativeTime
creates aDebugTime
(:Iterative)
:Stepsize
creates aDebugStepsize
:Stop
creates aStoppingCriterion
()
:WarnCost
creates aDebugWarnIfCostNotFinite
:WarnGradient
creates aDebugWarnIfFieldNotFinite
for the::Gradient
.:WarnBundle
creates aDebugWarnIfLagrangeMultiplierIncreases
:Time
creates aDebugTime
:WarningMessages
creates aDebugMessages
(:Warning)
:InfoMessages
creates aDebugMessages
(:Info)
:ErrorMessages
creates aDebugMessages
(:Error)
:Messages
creates aDebugMessages
()
(the same as:InfoMessages
)
any other symbol creates a DebugEntry(s)
to print the entry (o.:s) from the options.
Manopt.DebugActionFactory
— MethodDebugActionFactory(t::Tuple{Symbol,String)
Convert certain Symbols in the debug=[ ... ]
vector to DebugAction
s Currently the following ones are done, where the string in t[2]
is passed as the format
the corresponding debug. Note that the Shortcut symbols t[1]
should all start with a capital letter.
:Change
creates aDebugChange
:Cost
creates aDebugCost
:Gradient
creates aDebugGradient
:GradientChange
creates aDebugGradientChange
:GradientNorm
creates aDebugGradientNorm
:Iterate
creates aDebugIterate
:Iteration
creates aDebugIteration
:Stepsize
creates aDebugStepsize
:Stop
creates aDebugStoppingCriterion
:Time
creates aDebugTime
:IterativeTime
creates aDebugTime
(:Iterative)
any other symbol creates a DebugEntry(s)
to print the entry (o.:s) from the options.
Manopt.DebugFactory
— MethodDebugFactory(a::Vector)
Generate a dictionary of DebugAction
s.
First all Symbol
s String
, DebugAction
s and numbers are collected, excluding :Stop
and :WhenActive
. This collected vector is added to the :Iteration => [...]
pair. :Stop
is added as :StoppingCriterion
to the :Stop => [...]
pair. If necessary, these pairs are created
For each Pair
of a Symbol
and a Vector
, the DebugGroupFactory
is called for the Vector
and the result is added to the debug dictionary's entry with said symbol. This is wrapped into the DebugWhenActive
, when the :WhenActive
symbol is present
Return value
A dictionary for the different enrty points where debug can happen, each containing a DebugAction
to call.
Note that upon the initialisation all dictionaries but the :StartAlgorithm
one are called with an i=0
for reset.
Examples
Providing a simple vector of symbols, numbers and strings like
[:Iterate, " | ", :Cost, :Stop, 10]
Adds a group to :Iteration of three actions (
DebugIteration
,DebugDivider
(" | "), and[
DebugCost](@ref)) as a [
DebugGroup](@ref) inside an [
DebugEvery](@ref) to only be executed every 10th iteration. It also adds the [
DebugStoppingCriterion](@ref) to the
:EndAlgorithm` entry of the dictionary.The same can also be written a bit more precise as
DebugFactory([:Iteration => [:Iterate, " | ", :Cost, 10], :Stop])
We can even make the stoping criterion concrete and pass Actions directly, for example explicitly Making the stop more concrete, we get
DebugFactory([:Iteration => [:Iterate, " | ", DebugCost(), 10], :Stop => [:Stop]])
Manopt.DebugGroupFactory
— MethodDebugGroupFactory(a::Vector)
Generate a DebugGroup
of DebugAction
s. The following rules are used
- Any
Symbol
is passed toDebugActionFactory
- Any
(Symbol, String)
generates similar actions as in 1., but the string is used forformat=
, seeDebugActionFactory
- Any
String
is passed toDebugActionFactory
- Any
DebugAction
is included as is.
If this results in more than one DebugAction
a DebugGroup
of these is build.
If any integers are present, the last of these is used to wrap the group in a DebugEvery
(k)
.
If :WhenActive
is present, the resulting Action is wrapped in DebugWhenActive
, making it deactivatable by its parent solver.
Manopt.reset!
— Methodreset!(d::DebugTime)
reset the internal time of a DebugTime
, that is start from now again.
Manopt.set_parameter!
— Methodset_parameter!(ams::DebugSolverState, ::Val{:Debug}, args...)
Set certain values specified by args...
into the elements of the debugDictionary
Manopt.stop!
— Methodstop!(d::DebugTime)
stop the reset the internal time of a DebugTime
, that is set the time to 0 (undefined)
Technical details
The decorator to print debug during the iterations can be activated by decorating the state of a solver and implementing your own DebugAction
s. For example printing a gradient from the GradientDescentState
is automatically available, as explained in the gradient_descent
solver.
Manopt.initialize_solver!
— Methodinitialize_solver!(amp::AbstractManoptProblem, dss::DebugSolverState)
Extend the initialization of the solver by a hook to run the DebugAction
that was added to the :Start
entry of the debug lists. All others are triggered (with iteration number 0
) to trigger possible resets
Manopt.step_solver!
— Methodstep_solver!(amp::AbstractManoptProblem, dss::DebugSolverState, k)
Extend the i
th step of the solver by a hook to run debug prints, that were added to the :BeforeIteration
and :Iteration
entries of the debug lists.
Manopt.stop_solver!
— Methodstop_solver!(amp::AbstractManoptProblem, dss::DebugSolverState, k)
Extend the stop_solver!
, whether to stop the solver by a hook to run debug, that were added to the :Stop
entry of the debug lists.