decent_bench.cost_functions#

class decent_bench.cost_functions.CostFunction[source]#

Bases: ABC

Used by agents to evaluate the cost and its derivatives at a certain x.

abstract property domain_shape: tuple[int, ...]#

Required shape of x.

abstract property m_smooth: float#

Lipschitz constant of the cost function’s gradient.

The gradient’s Lipschitz constant m_smooth is the smallest value such that \(\| \nabla f(\mathbf{x_1}) - \nabla f(\mathbf{x_2}) \| \leq \text{m_smooth} \cdot \|\mathbf{x_1} - \mathbf{x_2}\|\) for all \(\mathbf{x_1}\) and \(\mathbf{x_2}\).

Returns:

  • non-negative finite number if function is L-smooth

  • np.inf if function is differentiable everywhere but not L-smooth

  • np.nan if function is not differentiable everywhere

abstract property m_cvx: float#

Convexity constant of the cost function.

The convexity constant m_cvx is the largest value such that \(f(\mathbf{x_1}) \geq f(\mathbf{x_2}) + \nabla f(\mathbf{x_2})^T (\mathbf{x_1} - \mathbf{x_2}) + \frac{\text{m_cvx}}{2} \|\mathbf{x_1} - \mathbf{x_2}\|^2\) for all \(\mathbf{x_1}\) and \(\mathbf{x_2}\).

Returns:

  • positive finite number if function is strongly convex

  • 0 if function is convex but not strongly convex

  • np.nan if function is not guaranteed to be convex

abstractmethod evaluate(x: ndarray[tuple[Any, ...], dtype[float64]]) float[source]#

Evaluate function at x.

abstractmethod gradient(x: ndarray[tuple[Any, ...], dtype[float64]]) ndarray[tuple[Any, ...], dtype[float64]][source]#

Gradient at x.

abstractmethod hessian(x: ndarray[tuple[Any, ...], dtype[float64]]) ndarray[tuple[Any, ...], dtype[float64]][source]#

Hessian at x.

abstractmethod proximal(y: ndarray[tuple[Any, ...], dtype[float64]], rho: float) ndarray[tuple[Any, ...], dtype[float64]][source]#

Proximal at y.

The proximal operator is defined as:

\[\operatorname{prox}_{\rho f}(\mathbf{y}) = \arg\min_{\mathbf{x}} \left\{ f(\mathbf{x}) + \frac{1}{2\rho} \| \mathbf{x} - \mathbf{y} \|^2 \right\}\]

where \(\rho > 0\) is the penalty and \(f\) the cost function.

If the cost function’s proximal does not have a closed form solution, it can be solved iteratively using proximal_solver().

abstractmethod __add__(other: CostFunction) CostFunction[source]#

Add another cost function to create a new one.

SumCost can be used as the result of __add__() by returning SumCost([self, other]). However, it’s often more efficient to preserve the cost function type if possible. For example, the addition of two QuadraticCost objects benefits from returning a new QuadraticCost instead of a SumCost as this preserves the closed form proximal solution and only requires one evaluation instead of two when calling evaluate(), gradient(), and hessian().

class decent_bench.cost_functions.QuadraticCost(A: ndarray[tuple[Any, ...], dtype[float64]], b: ndarray[tuple[Any, ...], dtype[float64]], c: float)[source]#

Bases: CostFunction

Quadratic cost function.

\[f(\mathbf{x}) = \frac{1}{2} \mathbf{x}^T \mathbf{Ax} + \mathbf{b}^T \mathbf{x} + c\]
property domain_shape: tuple[int, ...]#

Required shape of x.

property m_smooth: float[source]#

The cost function’s smoothness constant.

\[\max_{i} \left| \lambda_i \right|\]

where \(\lambda_i\) are the eigenvalues of \(\frac{1}{2} (\mathbf{A}+\mathbf{A}^T)\).

For the general definition, see CostFunction.m_smooth.

property m_cvx: float[source]#

The cost function’s convexity constant.

\[\begin{split}\begin{array}{ll} \min_i \lambda_i, & \text{if } \min_i \lambda_i > 0, \\ 0, & \text{if } \min_i \lambda_i = 0, \\ \text{NaN}, & \text{if } \min_i \lambda_i < 0 \end{array}\end{split}\]

where \(\lambda_i\) are the eigenvalues of \(\frac{1}{2} (\mathbf{A}+\mathbf{A}^T)\).

For the general definition, see CostFunction.m_cvx.

evaluate(x: ndarray[tuple[Any, ...], dtype[float64]]) float[source]#

Evaluate function at x.

\[\frac{1}{2} \mathbf{x}^T \mathbf{Ax} + \mathbf{b}^T \mathbf{x} + c\]
gradient(x: ndarray[tuple[Any, ...], dtype[float64]]) ndarray[tuple[Any, ...], dtype[float64]][source]#

Gradient at x.

\[\frac{1}{2} (\mathbf{A}+\mathbf{A}^T)\mathbf{x} + \mathbf{b}\]
hessian(x: ndarray[tuple[Any, ...], dtype[float64]]) ndarray[tuple[Any, ...], dtype[float64]][source]#

Hessian at x.

\[\frac{1}{2} (\mathbf{A}+\mathbf{A}^T)\]
proximal(y: ndarray[tuple[Any, ...], dtype[float64]], rho: float) ndarray[tuple[Any, ...], dtype[float64]][source]#

Proximal at y.

\[(\frac{\rho}{2} (\mathbf{A} + \mathbf{A}^T) + \mathbf{I})^{-1} (\mathbf{y} - \rho \mathbf{b})\]

where \(\rho > 0\) is the penalty.

This is a closed form solution, see CostFunction.proximal() for the general proximal definition.

__add__(other: CostFunction) CostFunction[source]#

Add another cost function.

Raises:

ValueError – if the domain shapes don’t match

class decent_bench.cost_functions.LinearRegressionCost(A: ndarray[tuple[Any, ...], dtype[float64]], b: ndarray[tuple[Any, ...], dtype[float64]])[source]#

Bases: CostFunction

Linear regression cost function.

\[f(\mathbf{x}) = \frac{1}{2} \| \mathbf{Ax} - \mathbf{b} \|^2\]

or in the general quadratic form

\[f(\mathbf{x}) = \frac{1}{2} \mathbf{x}^T\mathbf{A}^T\mathbf{Ax} - (\mathbf{A}^T \mathbf{b})^T \mathbf{x} + \frac{1}{2} \mathbf{b}^T\mathbf{b}\]
property domain_shape: tuple[int, ...]#

Required shape of x.

property m_smooth: float#

The cost function’s smoothness constant.

\[\max_{i} \left| \lambda_i \right|\]

where \(\lambda_i\) are the eigenvalues of \(\mathbf{A}^T \mathbf{A}\).

For the general definition, see CostFunction.m_smooth.

property m_cvx: float#

The cost function’s convexity constant.

\[\begin{split}\begin{array}{ll} \min_i \lambda_i, & \text{if } \min_i \lambda_i > 0, \\ 0, & \text{if } \min_i \lambda_i = 0, \\ \text{NaN}, & \text{if } \min_i \lambda_i < 0 \end{array}\end{split}\]

where \(\lambda_i\) are the eigenvalues of \(\mathbf{A}^T \mathbf{A}\).

For the general definition, see CostFunction.m_cvx.

evaluate(x: ndarray[tuple[Any, ...], dtype[float64]]) float[source]#

Evaluate function at x.

\[\frac{1}{2} \| \mathbf{Ax} - \mathbf{b} \|^2\]
gradient(x: ndarray[tuple[Any, ...], dtype[float64]]) ndarray[tuple[Any, ...], dtype[float64]][source]#

Gradient at x.

\[\mathbf{A}^T\mathbf{Ax} - \mathbf{A}^T \mathbf{b}\]
hessian(x: ndarray[tuple[Any, ...], dtype[float64]]) ndarray[tuple[Any, ...], dtype[float64]][source]#

Hessian at x.

\[\mathbf{A}^T\mathbf{A}\]
proximal(y: ndarray[tuple[Any, ...], dtype[float64]], rho: float) ndarray[tuple[Any, ...], dtype[float64]][source]#

Proximal at y.

\[(\rho \mathbf{A}^T \mathbf{A} + \mathbf{I})^{-1} (\mathbf{y} + \rho \mathbf{A}^T\mathbf{b})\]

where \(\rho > 0\) is the penalty.

This is a closed form solution, see CostFunction.proximal() for the general proximal definition.

__add__(other: CostFunction) CostFunction[source]#

Add another cost function.

class decent_bench.cost_functions.LogisticRegressionCost(A: ndarray[tuple[Any, ...], dtype[float64]], b: ndarray[tuple[Any, ...], dtype[float64]])[source]#

Bases: CostFunction

Logistic regression cost function.

\[f(\mathbf{x}) = -\left[ \mathbf{b}^T \log( \sigma(\mathbf{Ax}) ) + ( \mathbf{1} - \mathbf{b} )^T \log( 1 - \sigma(\mathbf{Ax}) ) \right]\]
property domain_shape: tuple[int, ...]#

Required shape of x.

property m_smooth: float[source]#

The cost function’s smoothness constant.

\[\frac{m}{4} \max_i \|\mathbf{A}_i\|^2\]

where m is the number of rows in \(\mathbf{A}\).

For the general definition, see CostFunction.m_smooth.

property m_cvx: float#

The cost function’s convexity constant, 0.

For the general definition, see CostFunction.m_cvx.

evaluate(x: ndarray[tuple[Any, ...], dtype[float64]]) float[source]#

Evaluate function at x.

\[-\left[ \mathbf{b}^T \log( \sigma(\mathbf{Ax}) ) + ( \mathbf{1} - \mathbf{b} )^T \log( 1 - \sigma(\mathbf{Ax}) ) \right]\]
gradient(x: ndarray[tuple[Any, ...], dtype[float64]]) ndarray[tuple[Any, ...], dtype[float64]][source]#

Gradient at x.

\[\mathbf{A}^T (\sigma(\mathbf{Ax}) - \mathbf{b})\]
hessian(x: ndarray[tuple[Any, ...], dtype[float64]]) ndarray[tuple[Any, ...], dtype[float64]][source]#

Hessian at x.

\[\mathbf{A}^T \mathbf{DA}\]

where \(\mathbf{D}\) is a diagonal matrix such that \(\mathbf{D}_i = \sigma(\mathbf{Ax}_i) (1-\sigma(\mathbf{Ax}_i))\)

proximal(y: ndarray[tuple[Any, ...], dtype[float64]], rho: float) ndarray[tuple[Any, ...], dtype[float64]][source]#

Proximal at y solved using an iterative method.

See CostFunction.proximal() for the general proximal definition.

__add__(other: CostFunction) CostFunction[source]#

Add another cost function.

Raises:

ValueError – if the domain shapes don’t match

class decent_bench.cost_functions.SumCost(cost_functions: list[CostFunction])[source]#

Bases: CostFunction

The sum of multiple cost functions.

property domain_shape: tuple[int, ...]#

Required shape of x.

property m_smooth: float[source]#

The cost function’s smoothness constant.

\[\sum f_{k_\text{m_smooth}}\]

provided all \(f_{k_\text{m_smooth}}\) are finite. If any \(f_{k_\text{m_smooth}} = \text{NaN}\), the result is \(\text{NaN}\).

For the general definition, see CostFunction.m_smooth.

property m_cvx: float[source]#

The cost function’s convexity constant.

\[\sum f_{k_\text{m_cvx}}\]

provided all \(f_{k_\text{m_cvx}}\) are finite. If any \(f_{k_\text{m_cvx}} = \text{NaN}\), the result is \(\text{NaN}\).

For the general definition, see CostFunction.m_cvx.

evaluate(x: ndarray[tuple[Any, ...], dtype[float64]]) float[source]#

Sum the evaluate() of each cost function.

gradient(x: ndarray[tuple[Any, ...], dtype[float64]]) ndarray[tuple[Any, ...], dtype[float64]][source]#

Sum the gradient() of each cost function.

hessian(x: ndarray[tuple[Any, ...], dtype[float64]]) ndarray[tuple[Any, ...], dtype[float64]][source]#

Sum the hessian() of each cost function.

proximal(y: ndarray[tuple[Any, ...], dtype[float64]], rho: float) ndarray[tuple[Any, ...], dtype[float64]][source]#

Proximal at y solved using an iterative method.

See CostFunction.proximal() for the general proximal definition.

__add__(other: CostFunction) SumCost[source]#

Add another cost function.