krotov.convergence module

Routines for check_convergence in krotov.optimize.optimize_pulses()

A check_convergence function may be used to determine whether an optimization is converged, and thus can be stopped before the maximum number of iterations (iter_stop) is reached. A function suitable for check_convergence must receive a Result object, and return a value that evaluates as True or False in a Boolean context, indicating whether the optimization has converged or not.

The Result object that the check_convergence function receives as an argument will be up-to-date for the current iteration. That is, it will already contain the current values from optimize_pulses()’s info_hook in Result.info_vals, the current tau_vals, etc. The Result.optimized_controls attribute will contain the current optimized pulses (defined on the intervals of tlist). The check_convergence function should not modify the Result object it receives in any way. The proper place for custom modifications after each iteration in optimize_pulses() is through the info_hook routine.

It is recommended that a check_convergence function returns None (which is False in a Boolean context) if the optimization has not yet converged. If the optimization has converged, check_convergence should return a message string (which is True in a Boolean context). The returned string will be included in the final Result.message.

A typical usage for check_convergence is ending the optimization when the optimization functional falls below a specified limit. Such a check_convergence function can be generated by value_below(). By default, this assumes that the info_hook passed to optimize_pulses() returns the value of the functional, which is then stored in Result.info_vals. Alternatively, value_below() could be told to look at the Result.tau_vals.

Similarly, one might stop the optimization when there is an insufficient improvement between iterations. The delta_below() function generates a check_convergence function for this purpose. Multiple convergence conditions (“stop optimization when \(J_T\) reaches \(10^{-5}\), or if \(\Delta J_T < 10^{-6}\)”) can be defined via Or().

While Krotov’s method is guaranteed to monotonically converge in the continuous limit, this no longer strictly holds when time is discretized (in particular if lambda_a is too small). You can use check_monotonic_error() or check_monotonic_fidelity() as a check_convergence function that stops the optimization when monotonic convergence is lost.

Summary

Data:

Or Chain multiple check_convergence functions together in a logical Or.
check_monotonic_error Check for monotonic convergence with respect to the error
check_monotonic_fidelity Check for monotonic convergence with respect to the fidelity
delta_below Constructor for a routine that checks if \(\Abs{v_1 - v_0} < \varepsilon\)
value_below Constructor for routine that checks if a value is below limit

__all__: Or, check_monotonic_error, check_monotonic_fidelity, delta_below, value_below

Reference

krotov.convergence.Or(*funcs)[source]

Chain multiple check_convergence functions together in a logical Or.

Each parameter must be a function suitable to pass to optimize_pulses() as check_convergence. It must receive a Result object and should return None or a string message.

Returns:A function check_convergence(result) that returns the result of the first “non-passing” function in *funcs. A “non-passing” result is one that evaluates to True in a Boolean context (should be a string message)
Return type:callable
krotov.convergence.value_below(limit, spec=('info_vals', T[-1]), name=None, **kwargs)[source]

Constructor for routine that checks if a value is below limit

Parameters:
  • limit (float or str) – A float value (or str-representation of a float) against which to compare the value extracted from Result
  • spec – A glom() specification of the Result attribute from which to extract the value to compare against limit. Defaults to a spec extracting the last value in Result.info_vals.
  • name (str or None) – A name identifying the checked value, used for the message returned by the check_convergence routine. Defaults to str(spec).
  • **kwargs – Keyword arguments to pass to glom()
Returns:

A function check_convergence(result) that extracts the value specified by spec from the Result object, and checks it against limit. If the value is below the limit, it returns an appropriate message string. Otherwise, it returns None.

Return type:

callable

Note

If you find glom()-specifications intimidating: A simple callable acting on Result is also a valid spec. However, if you use a callable spec, make sure to pass an appropriate name.

The spec in the following example is equivalent to the default spec=('info_vals', glom.T[-1]).

Example

>>> check_convergence = value_below(
...     limit='1e-4',
...     spec=lambda r: r.info_vals[-1],
...     name='J_T'
... )
>>> r = krotov.result.Result()
>>> r.info_vals.append(1e-4)
>>> check_convergence(r)  # returns None
>>> r.info_vals.append(9e-5)
>>> check_convergence(r)
'J_T < 1e-4'
krotov.convergence.delta_below(limit, spec1=('info_vals', T[-1]), spec0=('info_vals', T[-2]), absolute_value=True, name=None, **kwargs)[source]

Constructor for a routine that checks if \(\Abs{v_1 - v_0} < \varepsilon\)

Parameters:
  • limit (float or str) – A float value (or str-representation of a float) for \(\varepsilon\)
  • spec1 – A glom() specification of the Result attribute from which to extract \(v_1\). Defaults to a spec extracting the last value in Result.info_vals.
  • spec0 – A glom() specification of the Result attribute from which to extract \(v_0\). Defaults to a spec extracting the last-but-one value in Result.info_vals.
  • absolute_value (bool) – If False, check for \(v_1 - v_0 < \varepsilon\), instead of the absolute value.
  • name (str or None) – A name identifying the delta, used for the message returned by the check_convergence routine. Defaults to "Δ({spec1},{spec0}".
  • **kwargs – Keyword arguments to pass to glom()

Note

You can use delta_below() to implement a check for strict monotonic convergence, e.g. when info_hook returns the optimization error, by flipping spec0 and spec1, setting limit to zero, and setting absolute_value to False. See check_monotonic_error().

Example

>>> check_convergence = delta_below(limit='1e-4', name='ΔJ_T')
>>> r = krotov.result.Result()
>>> r.info_vals.append(9e-1)
>>> check_convergence(r)  # None
>>> r.info_vals.append(1e-1)
>>> check_convergence(r)  # None
>>> r.info_vals.append(4e-4)
>>> check_convergence(r)  # None
>>> r.info_vals.append(2e-4)
>>> check_convergence(r)  # None
>>> r.info_vals.append(1e-6)
>>> check_convergence(r)  # None
>>> r.info_vals.append(1e-7)
>>> check_convergence(r)
'ΔJ_T < 1e-4'
krotov.convergence.check_monotonic_error(result)[source]

Check for monotonic convergence with respect to the error

Check that the last value in Result.info_vals is smaller than the last-but-one value. If yes, return None. If no, return an appropriate error message.

This assumes that the info_hook passed to optimize_pulses() returns the value of the functional, which is then available in Result.info_vals.

Example

>>> r = krotov.result.Result()
>>> r.info_vals.append(9e-1)
>>> check_monotonic_error(r)  # None
>>> r.info_vals.append(1e-1)
>>> check_monotonic_error(r)  # None
>>> r.info_vals.append(2e-1)
>>> check_monotonic_error(r)
'Loss of monotonic convergence; error decrease < 0'

See also

Use check_monotonic_fidelity() for when info_hook returns a “fidelity”, that is, a measure that should increase in each iteration.

krotov.convergence.check_monotonic_fidelity(result)[source]

Check for monotonic convergence with respect to the fidelity

This is like check_monotonic_error(), but looking for a monotonic increase in the values in Result.info_vals. Thus, it is assumed that the info_hook returns a fidelity, not an error.

Example

>>> r = krotov.result.Result()
>>> r.info_vals.append(0.0)
>>> check_monotonic_fidelity(r)  # None
>>> r.info_vals.append(0.2)
>>> check_monotonic_fidelity(r)  # None
>>> r.info_vals.append(0.15)
>>> check_monotonic_fidelity(r)
'Loss of monotonic convergence; fidelity increase < 0'