Iteration-dependent analysis
- class autolyap.IterationDependent[source]
Bases:
objectIteration-dependent Lyapunov analysis utilities.
For the mathematical formulation, notation, and convergence statements, see Iteration-dependent analyses.
This class provides the corresponding computational interface, with
search_lyapunov()as the main entry point.- static get_parameters_distance_to_solution( ) ndarray | Tuple[ndarray, ndarray][source]
Compute Lyapunov parameters for the distance-to-solution metric at iteration \(k\).
For the matrix constructions used in this method, see Performance estimation via SDPs. For the role of \((Q_k,q_k)\), see Iteration-dependent analyses.
Resulting lower bounds
With this choice of \((Q_k,q_k)\),
\[\mathcal{V}(Q_k,q_k,k) = \|y_{i,j}^{k} - y^{\star}\|^{2}.\]Matrix construction
The matrix \(Q_k\) is constructed as
\[Q_k = \left(P_{(i,j)}Y_k^{k,k} - P_{(i,\star)}Y_\star^{k,k}\right)^\top \left(P_{(i,j)}Y_k^{k,k} - P_{(i,\star)}Y_\star^{k,k}\right),\]where:
\(Y_k^{k,k}\) is retrieved via
_get_Ys(), using k_min = k and k_max = k.\(Y_\star^{k,k}\) is retrieved via
_get_Ys(), using k_min = k and k_max = k.\(P_{(i,j)}\) and \(P_{(i,\star)}\) are projection matrices retrieved via
_get_Ps().
The remaining vector is set to zero:
If \(\NumFunc > 0\), then \(q_k = 0\).
Parameters
algo (
Type[Algorithm]): Algorithm instance providing m, m_bar_is,_get_Ys(), and_get_Ps().k (
int): Nonnegative iteration index \(k\).i (
int): Component index, with \(i \in \llbracket 1, m\rrbracket\).j (
int): Evaluation index for component i, with \(j \in \llbracket 1, \NumEval_i\rrbracket\).
Returns
(
Union[numpy.ndarray,Tuple[numpy.ndarray,numpy.ndarray]]): If algo.m_func == 0, returns \(Q_k\) with\[Q_k \in \sym^{n + \NumEval + m}.\]Otherwise, returns \((Q_k, q_k)\) with
\[\begin{split}\begin{aligned} Q_k &\in \sym^{n + \NumEval + m},\\ q_k &\in \mathbb{R}^{\NumEvalFunc + \NumFunc}. \end{aligned}\end{split}\]
Raises
ValueError: If an input is invalid or a required matrix is missing.
- static get_parameters_fixed_point_residual( ) ndarray | Tuple[ndarray, ndarray][source]
Compute Lyapunov parameters for the fixed-point residual at iteration \(k\).
For the matrix constructions used in this method, see Performance estimation via SDPs. For the role of \((Q_k,q_k)\), see Iteration-dependent analyses.
Resulting lower bounds
With this choice of \((Q_k,q_k)\),
\[\mathcal{V}(Q_k,q_k,k) = \|\bx^{k+1} - \bx^{k}\|^{2}.\]Matrix construction
The matrix \(Q_k\) is constructed as
\[Q_k = \left(X_{k+1}^{k,k} - X_k^{k,k}\right)^\top \left(X_{k+1}^{k,k} - X_k^{k,k}\right),\]where:
\(X_k^{k,k}\) is retrieved via
_get_Xs(), using k_min = k and k_max = k.\(X_{k+1}^{k,k}\) is retrieved via
_get_Xs(), using k_min = k and k_max = k.
The remaining vector is set to zero:
If \(\NumFunc > 0\), then \(q_k = 0\).
Parameters
algo (
Type[Algorithm]): Algorithm instance providing dimensions and_get_Xs().k (
int): Nonnegative iteration index \(k\).
Returns
(
Union[numpy.ndarray,Tuple[numpy.ndarray,numpy.ndarray]]): If algo.m_func == 0, returns \(Q_k\) with\[Q_k \in \sym^{n + \NumEval + m}.\]Otherwise, returns \((Q_k, q_k)\) with
\[\begin{split}\begin{aligned} Q_k &\in \sym^{n + \NumEval + m},\\ q_k &\in \mathbb{R}^{\NumEvalFunc + \NumFunc}. \end{aligned}\end{split}\]
Raises
ValueError: If an input is invalid or required \(X\) matrices are missing.
- static get_parameters_function_value_suboptimality( ) Tuple[ndarray, ndarray][source]
Compute Lyapunov parameters for function-value suboptimality at iteration \(k\).
For the matrix constructions used in this method, see Performance estimation via SDPs. For the role of \((Q_k,q_k)\), see Iteration-dependent analyses.
Resulting lower bounds
With this choice of \((Q_k,q_k)\),
\[\mathcal{V}(Q_k,q_k,k) = f_{1}(y_{1,j}^{k}) - f_{1}(y^{\star}).\]Matrix construction
This method applies only when \(m = \NumFunc = 1\).
The vector \(q_k\) is constructed as
\[q_k = \left(F_{(1,j,k)}^{k,k} - F_{(1,\star,\star)}^{k,k}\right)^\top,\]where:
\(F_{(1,j,k)}^{k,k}\) is retrieved via
_get_Fs(), using k_min = k and k_max = k.\(F_{(1,\star,\star)}^{k,k}\) is retrieved via
_get_Fs(), using k_min = k and k_max = k.
The remaining matrix is set to zero:
\(Q_k = 0\).
Parameters
algo (
Type[Algorithm]): Algorithm instance with m = m_func = 1, m_bar_is, and_get_Fs().k (
int): Nonnegative iteration index \(k\).j (
int): Evaluation index for component 1, with \(j \in \llbracket 1, \NumEval_1\rrbracket\).
Returns
(
Tuple[numpy.ndarray,numpy.ndarray]): A tuple \((Q_k, q_k)\) with\[\begin{split}\begin{aligned} Q_k &\in \sym^{n + \NumEval + m},\\ q_k &\in \mathbb{R}^{\NumEvalFunc + \NumFunc}. \end{aligned}\end{split}\]
Raises
ValueError: If an input is invalid, required \(F\) matrices are missing, or \(m \ne 1\) / \(\NumFunc \ne 1\).
- static get_parameters_optimality_measure( ) ndarray | Tuple[ndarray, ndarray][source]
Compute Lyapunov parameters for the optimality measure at iteration \(k\).
For the matrix constructions used in this method, see Performance estimation via SDPs. For the role of \((Q_k,q_k)\), see Iteration-dependent analyses.
Resulting lower bounds
With this choice of \((Q_k,q_k)\),
\[\begin{split}\mathcal{V}(Q_k,q_k,k) = \begin{cases} \|u_{1,1}^{k}\|^{2}, & \text{if } m = 1, \\[0.5em] \left\|\sum_{i=1}^{m} u_{i,1}^{k}\right\|^{2} + \sum_{i=2}^{m} \|y_{1,1}^{k} - y_{i,1}^{k}\|^{2}, & \text{if } m > 1. \end{cases}\end{split}\]Matrix construction
The matrix \(Q_k\) is constructed as
\[\begin{split}Q_k = \begin{cases} \left(P_{(1,1)}U_k^{k,k}\right)^\top \left(P_{(1,1)}U_k^{k,k}\right), & \text{if } m = 1, \\[1em] \left(\sum_{i=1}^{m} P_{(i,1)}U_k^{k,k}\right)^\top \left(\sum_{i=1}^{m} P_{(i,1)}U_k^{k,k}\right) + \sum_{i=2}^{m} \left(\left(P_{(1,1)} - P_{(i,1)}\right)Y_k^{k,k}\right)^\top \left(\left(P_{(1,1)} - P_{(i,1)}\right)Y_k^{k,k}\right), & \text{if } m > 1, \end{cases}\end{split}\]where:
\(U_k^{k,k}\) is retrieved via
_get_Us(), using k_min = k and k_max = k.\(Y_k^{k,k}\) is retrieved via
_get_Ys(), using k_min = k and k_max = k.\(P_{(i,1)}\) are projection matrices retrieved via
_get_Ps().
The remaining vector is set to zero:
If \(\NumFunc > 0\), then \(q_k = 0\).
Parameters
algo (
Type[Algorithm]): Algorithm instance providing m, m_bar, m_bar_is,_get_Us(),_get_Ys(), and_get_Ps().k (
int): Nonnegative iteration index \(k\).
Returns
(
Union[numpy.ndarray,Tuple[numpy.ndarray,numpy.ndarray]]): If algo.m_func == 0, returns \(Q_k\) with\[Q_k \in \sym^{n + \NumEval + m}.\]Otherwise, returns \((Q_k, q_k)\) with
\[\begin{split}\begin{aligned} Q_k &\in \sym^{n + \NumEval + m},\\ q_k &\in \mathbb{R}^{\NumEvalFunc + \NumFunc}. \end{aligned}\end{split}\]
Raises
ValueError: If an input is invalid or required matrices are missing.
- static get_parameters_state_component_cross_iteration_difference( ) ndarray | Tuple[ndarray, ndarray][source]
Compute Lyapunov parameters for a cross-iteration state-component difference metric at iteration \(k\).
For the matrix constructions used in this method, see Performance estimation via SDPs. For the role of \((Q_k,q_k)\), see Iteration-dependent analyses.
Resulting lower bounds
With this choice of \((Q_k,q_k)\),
\[\mathcal{V}(Q_k,q_k,k) = \|x_{\ell}^{k+1} - x_{\ell^{\prime}}^{k}\|^{2}.\]Matrix construction
The matrix \(Q_k\) is constructed as
\[Q_k = \left(e_\ell^\top X_{k+1}^{k,k} - e_{\ell^{\prime}}^\top X_k^{k,k}\right)^\top \left(e_\ell^\top X_{k+1}^{k,k} - e_{\ell^{\prime}}^\top X_k^{k,k}\right),\]where:
\(X_k^{k,k}\) and \(X_{k+1}^{k,k}\) are retrieved via
_get_Xs(), using k_min = k and k_max = k.\(e_\ell, e_{\ell^\prime} \in \mathbb{R}^{n}\) are standard basis vectors.
The remaining vector is set to zero:
If \(\NumFunc > 0\), then \(q_k = 0\).
Parameters
algo (
Type[Algorithm]): Algorithm instance providing dimensions and_get_Xs().k (
int): Nonnegative iteration index \(k\).ell (
int): State coordinate index at iteration \(k+1\), with \(\ell \in \llbracket 1, n\rrbracket\).ell_prime (
int): State coordinate index at iteration \(k\), with \(\ell^\prime \in \llbracket 1, n\rrbracket\).
Returns
(
Union[numpy.ndarray,Tuple[numpy.ndarray,numpy.ndarray]]): If algo.m_func == 0, returns \(Q_k\) with\[Q_k \in \sym^{n + \NumEval + m}.\]Otherwise, returns \((Q_k, q_k)\) with
\[\begin{split}\begin{aligned} Q_k &\in \sym^{n + \NumEval + m},\\ q_k &\in \mathbb{R}^{\NumEvalFunc + \NumFunc}. \end{aligned}\end{split}\]
Raises
ValueError: If an input is invalid or a required matrix is missing.
- static get_parameters_state_component_difference( ) ndarray | Tuple[ndarray, ndarray][source]
Compute Lyapunov parameters for a same-iteration state-component difference metric at iteration \(k\).
For the matrix constructions used in this method, see Performance estimation via SDPs. For the role of \((Q_k,q_k)\), see Iteration-dependent analyses.
Resulting lower bounds
With this choice of \((Q_k,q_k)\),
\[\mathcal{V}(Q_k,q_k,k) = \|x_{\ell}^{k} - x_{\ell^{\prime}}^{k}\|^{2}.\]Matrix construction
The matrix \(Q_k\) is constructed as
\[Q_k = \left(e_\ell^\top X_k^{k,k} - e_{\ell^{\prime}}^\top X_k^{k,k}\right)^\top \left(e_\ell^\top X_k^{k,k} - e_{\ell^{\prime}}^\top X_k^{k,k}\right),\]where:
\(X_k^{k,k}\) is retrieved via
_get_Xs(), using k_min = k and k_max = k.\(e_\ell, e_{\ell^\prime} \in \mathbb{R}^{n}\) are standard basis vectors.
The remaining vector is set to zero:
If \(\NumFunc > 0\), then \(q_k = 0\).
Parameters
algo (
Type[Algorithm]): Algorithm instance providing dimensions and_get_Xs().k (
int): Nonnegative iteration index \(k\).ell (
int): State coordinate index at iteration \(k\), with \(\ell \in \llbracket 1, n\rrbracket\).ell_prime (
int): State coordinate index at iteration \(k\), with \(\ell^\prime \in \llbracket 1, n\rrbracket\).
Returns
(
Union[numpy.ndarray,Tuple[numpy.ndarray,numpy.ndarray]]): If algo.m_func == 0, returns \(Q_k\) with\[Q_k \in \sym^{n + \NumEval + m}.\]Otherwise, returns \((Q_k, q_k)\) with
\[\begin{split}\begin{aligned} Q_k &\in \sym^{n + \NumEval + m},\\ q_k &\in \mathbb{R}^{\NumEvalFunc + \NumFunc}. \end{aligned}\end{split}\]
Raises
ValueError: If an input is invalid or a required matrix is missing.
- static get_parameters_state_component_distance_to_solution( ) ndarray | Tuple[ndarray, ndarray][source]
Compute Lyapunov parameters for a state-component distance-to-solution metric at iteration \(k\).
For the matrix constructions used in this method, see Performance estimation via SDPs. For the role of \((Q_k,q_k)\), see Iteration-dependent analyses.
Resulting lower bounds
With this choice of \((Q_k,q_k)\),
\[\mathcal{V}(Q_k,q_k,k) = \|x_{\ell}^{k} - y^{\star}\|^{2}.\]Matrix construction
The matrix \(Q_k\) is constructed as
\[Q_k = \left(e_\ell^\top X_k^{k,k} - P_{(1,\star)}Y_\star^{k,k}\right)^\top \left(e_\ell^\top X_k^{k,k} - P_{(1,\star)}Y_\star^{k,k}\right),\]where:
\(X_k^{k,k}\) is retrieved via
_get_Xs(), using k_min = k and k_max = k.\(Y_\star^{k,k}\) is retrieved via
_get_Ys(), using k_min = k and k_max = k.\(P_{(1,\star)}\) is retrieved via
_get_Ps().\(e_\ell \in \mathbb{R}^{n}\) is the ell-th standard basis vector.
The remaining vector is set to zero:
If \(\NumFunc > 0\), then \(q_k = 0\).
Parameters
algo (
Type[Algorithm]): Algorithm instance providing dimensions and_get_Xs(),_get_Ys(), and_get_Ps().k (
int): Nonnegative iteration index \(k\).ell (
int): State coordinate index, with \(\ell \in \llbracket 1, n\rrbracket\).
Returns
(
Union[numpy.ndarray,Tuple[numpy.ndarray,numpy.ndarray]]): If algo.m_func == 0, returns \(Q_k\) with\[Q_k \in \sym^{n + \NumEval + m}.\]Otherwise, returns \((Q_k, q_k)\) with
\[\begin{split}\begin{aligned} Q_k &\in \sym^{n + \NumEval + m},\\ q_k &\in \mathbb{R}^{\NumEvalFunc + \NumFunc}. \end{aligned}\end{split}\]
Raises
ValueError: If an input is invalid or a required matrix is missing.
- static search_lyapunov(
- prob: InclusionProblem,
- algo: Algorithm,
- K: int,
- Q_0: ndarray,
- Q_K: ndarray,
- q_0: ndarray | None = None,
- q_K: ndarray | None = None,
- solver_options: SolverOptions | None = None,
- verbosity: int = 1,
Search for an iteration-dependent Lyapunov certificate via an SDP.
Given an inclusion problem, an algorithm, and user-specified targets \((Q_0,q_0,Q_K,q_K,K)\), this method formulates and solves a semidefinite feasibility problem for certificate variables \((\{Q_k,q_k\}_{k=1}^{K-1}, c_K)\).
Connection to theory
For the formal statement of the chained quadratic Lyapunov inequality and the role of \((Q_0,q_0,Q_K,q_K,K)\), see Iteration-dependent analyses.
User-specified targets
The tuple \((Q_0,q_0,Q_K,q_K)\) fixes the endpoint Lyapunov values \(\mathcal{V}(Q_0,q_0,0)\) and \(\mathcal{V}(Q_K,q_K,K)\). These endpoint parameters are fixed inputs to the SDP (not optimization variables).
Built-in constructors for choosing endpoint parameters are:
The SDP then searches for intermediate \((Q_k,q_k)\) for \(k \in \llbracket 1, K-1\rrbracket\) and the minimum feasible \(c_K \ge 0\) so that the chained inequalities hold. When \(\NumFunc = 0\), the vectors \(q_k\) (and inputs q_0, q_K) are omitted.
Parameters
prob (
Type[InclusionProblem]): AnInclusionProbleminstance containing interpolation conditions.algo (
Type[Algorithm]): AnAlgorithminstance providing dimensions and matrix helpers.K (
int): A positive integer corresponding to \(K\) defining the iteration budget.Q_0 (
numpy.ndarray): A symmetric matrix corresponding to \(Q_0 \in \sym^{n + \NumEval + m}\).Q_K (
numpy.ndarray): A symmetric matrix corresponding to \(Q_K \in \sym^{n + \NumEval + m}\).q_0 (
Optional[numpy.ndarray]): A vector corresponding to \(q_0 \in \mathbb{R}^{\NumEvalFunc + \NumFunc}\) for functional components (required if \(\NumFunc > 0\); otherwise None).q_K (
Optional[numpy.ndarray]): A vector corresponding to \(q_K \in \mathbb{R}^{\NumEvalFunc + \NumFunc}\) for functional components (required if \(\NumFunc > 0\); otherwise None).solver_options (
Optional[SolverOptions]): Optional backend and parameter settings. Defaults to SolverOptions(backend=”mosek_fusion”).verbosity (
int): Nonnegative output level. Defaults to 1. Set 0 to disable user-facing diagnostics, 1 for concise summaries, and 2 for per-iteration detail.
Returns
(
Mapping[str,Any]): Result mapping with keys status, solve_status, c_K, and certificate.status (
str): One of “feasible”, “infeasible”, or “not_solved”.solve_status (
Optional[str]): Raw backend solve status (None when unavailable).c_K (
Optional[float]): Optimal objective value when status == “feasible”; otherwise None. This is the horizon-dependent scalar.certificate (
Optional[Mapping[str,Any]]): None unless status == “feasible”.
When status == “feasible”, certificate has:
{ "Q_sequence": List[np.ndarray], # length K+1, Q_sequence[k] = Q_k "q_sequence": List[np.ndarray] | None, # None when m_func == 0 "multipliers": { "operator_lambda": List[record], "function_lambda": List[record], "function_nu": List[record] } }Each multiplier list entry is a record with:
record = { "iteration": int, "component": int, "interpolation_index": int, "pairs": List[{"j": int | "star", "k": int | "star"}], "value": float }Field meanings and ranges:
iteration corresponds to \(k\) and satisfies \(k \in \llbracket 0, K-1 \rrbracket\).
component corresponds to \(i\) and satisfies \(i \in \llbracket 1, m \rrbracket\).
interpolation_index corresponds to \(o\), where \(o\) is the zero-based index from \(\text{enumerate}(\text{prob.get_component_data}(i))\), so \(o \in \llbracket 0, \text{len}(\text{prob.get_component_data}(i)) - 1 \rrbracket\).
pairs is the concrete interpolation-pair list used by that multiplier. Its length is determined by
_InterpolationIndices: 1 for “r1” and 2 for “r1<r2”, “r1!=r2”, “r1!=star”. Typical examples are [{“j”: 2, “k”: 5}] and [{“j”: 1, “k”: 5}, {“j”: “star”, “k”: “star”}].Pair entries satisfy
\[\begin{split}\begin{aligned} j &\in \llbracket 1, \bar m_i \rrbracket \cup \{\star\}, \\ k_{\text{pair}} &\in \{k, k+1\} \cup \{\star\}, \end{aligned}\end{split}\]with \(j=\star \Leftrightarrow k_{\text{pair}}=\star\).
value is the scalar multiplier for that record.
Raises
ValueError: If input dimensions or other conditions are violated.