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 — TypeDebugActionA 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)
printmethod 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.DebugCallback — TypeDebugCallback <: DebugActionDebug for a simple callback function, mainly for compatibility to other solvers and if a user already has a callback function or functor available
The expected format of the is that it is a function with signature (problem, state, iteration) -> nothing A simple callbaclk of the signature () -> nothing can be specified by simple=true. In this case the callback is wrapped in a function of the generic form
This is for now an internal struct, since its name might still change before it is made public. The functionality with the factory (callback=f) will still work, but this debug actions name might still change its name in the future.
Constructor
DebugCallback(callback; simple=false)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 <: DebugActionprint 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 <: DebugActionprint a small divider (default " | ").
Constructor
DebugDivider(div,print)Manopt.DebugEntry — TypeDebugEntry <: DebugActionprint 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} <: DebugActionprint a certain entries change during iterates
Additional fields
print: function to print the resultprefix: prefix to the print outformat: format to print (uses theprefixby default and scientific notation)field: Symbol the field can be accessed with withinAbstractManoptSolverStatedistance: function (p,o,x1,x2) to compute the change/distance between two values of the entrystorage: aStoreStateActionto store the previous value of:f
Constructors
DebugEntryChange(f,d)Keyword arguments
io=stdout: anIOStreamused for the debugprefix="Change of $f": the prefixstorage=StoreStateAction((f,)): aStoreStateActioninitial_value=NaN: an initial value for the change ofo.field.format="$prefix %e": format to print the change
Manopt.DebugEvery — TypeDebugEvery <: DebugActionevaluate 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 sub solvers active parameter, see |DebugWhenActive}(#ref). Here, the activattion_offset can be used to specify whether it refers to this iteration, the ith, 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 <: DebugActionDisplay 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
:Feasbiledisplay true or false depending on whether the iterate is feasible:FeasbileEqdisplay=or≠equality constraints are fulfilled or not:FeasbileInEqdisplay≤or≰inequality constraints are fulfilled or not:NumEqdisplay the number of equality constraints infeasible:NumEqNzdisplay the number of equality constraints infeasible if exists:NumIneqdisplay the number of inequality constraints infeasible:NumIneqNzdisplay the number of inequality constraints infeasible if exists:TotalEqdisplay the sum of how much the equality constraints are violated:TotalInEqdisplay 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 <: DebugActiongroup a set of DebugActions 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 DebugActions 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 <: DebugActionIssue 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: anIOstreamcheck: a function that takes the value of thefieldas input and returns a booleanfield: symbol the entry can be accessed with withinAbstractManoptSolverStatemsg: if thecheckfails, this message is displayedtype: symbol specifying the type of display, possible values:print,: warn,:info,:error, where:printprints toio.
Constructor
DebugEntry(field, check=(>(0)); type=:warn, message=":$f is nonnegative", io=stdout)Manopt.DebugIterate — TypeDebugIterate <: DebugActiondebug 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: (seelongfor default) set a prefix to be printed before the iterate
Manopt.DebugIteration — TypeDebugIteration <: DebugActionConstructor
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 <: DebugActionAn 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 <: AbstractManoptSolverStateThe 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
ArrayofDebugActions. - a
Dict{Symbol,DebugAction}. - an Array of Symbols, String and an Int for the
DebugFactory
Manopt.DebugStoppingCriterion — TypeDebugStoppingCriterion <: DebugActionprint 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%sis 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 <: DebugActionprint 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 <: DebugActionA 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 <: DebugActionA 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} <: DebugActionA 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 <: DebugActionevaluate 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<=0inactive state
Constructor
DebugWhenActive(d::DebugAction, active=true, always_update=true)Manopt.DebugActionFactory — MethodDebugActionFactory(s)create a DebugAction where
- a
Stringyields the corresponding divider - a
DebugActionis passed through - a [
Symbol] createsDebugEntryof that symbol, with the exceptions of:Change,:Iterate,:Iteration, and:Cost. - a
Tuple{Symbol,String}creates aDebugEntryof that symbol where the String specifies the format. - a
<:Functioncreates aDebugCallbackwith the function as callback.
Manopt.DebugActionFactory — MethodDebugActionFactory(s::Symbol)Convert certain Symbols in the debug=[ ... ] vector to DebugActions Currently the following ones are done. Note that the Shortcut symbols should all start with a capital letter.
:Costcreates aDebugCost:Changecreates aDebugChange:Gradientcreates aDebugGradient:GradientChangecreates aDebugGradientChange:GradientNormcreates aDebugGradientNorm:Iteratecreates aDebugIterate:Iterationcreates aDebugIteration:IterativeTimecreates aDebugTime(:Iterative):Stepsizecreates aDebugStepsize:Stopcreates aStoppingCriterion():WarnStepsizecreates aDebugWarnIfStepsizeCollapsed:WarnBundlecreates aDebugWarnIfLagrangeMultiplierIncreases:WarnCostcreates aDebugWarnIfCostNotFinite:WarnGradientcreates aDebugWarnIfFieldNotFinitefor the::Gradient.:Timecreates aDebugTime:WarningMessagescreates aDebugMessages(:Warning):InfoMessagescreates aDebugMessages(:Info):ErrorMessagescreates aDebugMessages(:Error):Messagescreates 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 DebugActions 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.
:Changecreates aDebugChange:Costcreates aDebugCost:Gradientcreates aDebugGradient:GradientChangecreates aDebugGradientChange:GradientNormcreates aDebugGradientNorm:Iteratecreates aDebugIterate:Iterationcreates aDebugIteration:Stepsizecreates aDebugStepsize:Stopcreates aDebugStoppingCriterion:Timecreates aDebugTime:IterativeTimecreates 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 DebugActions.
First all Symbols String, DebugActions 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 stopping 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 DebugActions. The following rules are used
- Any
Symbolis passed toDebugActionFactory - Any
(Symbol, String)generates similar actions as in 1., but the string is used forformat=, seeDebugActionFactory - Any
Stringis passed toDebugActionFactory - Any
Functiongenerates aDebugCallback. - Any
DebugActionis 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 DebugActions. 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 ith 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.