Objectives#
Objective#
Composable objective functions for Cvxium’s convex optimization solvers.
Defines Objective, the abstract base for the scalar function f0(w) that a
Problem minimizes, and ObjectivePoint, the per-point context through which a
solver evaluates the objective’s value, gradient, and structured Hessian at one iterate.
An objective reports its Hessian as a MatrixSystem, which
Problem.build_hessian_system sums with the constraint layers’ contributions, so
structure in ∇^2 f0 (diagonal, low rank, zero) carries through to the Newton step.
The concrete objectives are LinearObjective and QuadraticObjective. Two wrappers
build new objectives from existing ones: NegatedObjective (the negation -g, used by
Problem.maximize) and LiftedObjective (an objective that ignores trailing
auxiliary coordinates, used for epigraph and Phase I formulations).
- class cvxium.problems.objective.ObjectivePoint[source]#
Bases:
ABCPer-point evaluation context returned by
Objective.at.A solver acquires one
ObjectivePointper iterate w (BarrierSolvercaches it until the iterate changes) and routes the value, gradient, and Hessian calls through it. A subclass can therefore compute w-dependent work (forward passes, structured Hessian data) once per iterate and share it across those calls, rather than recomputing it inside each method.The default point returned by
Objective.atis an uncached pass-through that delegates back to theObjectivemethods. An objective with expensive w-dependent work should overrideObjective.atto return a cached point.- abstractmethod evaluate()[source]#
Return the objective value f0(w) at the bound point.
- Returns:
f0 – The objective value.
- Return type:
- abstractmethod gradient()[source]#
Return the gradient ∇f0(w) at the bound point.
- Returns:
grad_f0 – The gradient, of length M.
- Return type:
npt.NDArray[np.float64]
- class cvxium.problems.objective.Objective[source]#
Bases:
ABCAbstract objective of a convex optimization problem.
An
Objectivesupplies the scalar function f0(w) and its derivatives in the form the solvers consume, mirroring theConstraintLayerinterface:evaluatereturns f0(w);gradientreturns ∇f0(w);hessian_contributionreturns ∇^2 f0(w) as aMatrixSystem, whichProblem.build_hessian_systemsums with the constraint layers’ contributions;atreturns anObjectivePointbundling the three at one iterate;btls_keep_in_domainbounds a line-search step by the domain of f0.
Because the Newton system is assembled from structured contributions, an objective with structured curvature (for example, a
QuadraticObjectivewith diagonal Q, or with low rank Q = κ κ^T) keeps that structure through the whole Newton step.- is_linear = False#
Whether f0 is affine in w, so that ∇^2 f0 ≡ 0.
BarrierSolverchecks it, together with each inequality layer’sis_linear, to evaluate the dual analytically (the LP dual, decided by the gradient residual) instead of through the mini-Newton solve. The default False is safe: an affine objective that forgets to override it only takes the slower path, never a wrong one. It is a plain class attribute rather than aClassVarso that wrappers whose linearity depends on what they wrap, such asNegatedObjective, can forward the wrapped value per instance.
- feasibility_threshold = None#
Stop threshold for a feasibility solve, or
Nonefor ordinary minimization.When set, a solver minimizing this objective is answering a feasibility question: it stops as soon as the value falls below
feasibility_threshold(the feasibility certificate), and runs to the optimum only to prove the problem infeasible.Nonedisables the early stop. Attach a threshold to a copy withwith_feasibility_threshold; the objective is otherwise unchanged, so itsis_linearand fast dual path are preserved.
- abstract property dimension#
Return the dimension M of the decision variable this objective acts on.
Every concrete objective fixes its dimension at construction (for example, the length of a coefficient vector c, or the order of a Hessian system).
Problemchecks its declared dimension against each component’s.- Returns:
M – The decision-variable dimension.
- Return type:
- with_feasibility_threshold(threshold)[source]#
Return a copy of this objective that stops a solve at a threshold.
The copy carries
feasibility_thresholdset tothreshold, so a solver treats the minimization as a feasibility question and stops once the value falls below it.Solver._solve_feasibilityattaches a threshold of 0 to the Phase I objective.The copy is shallow: only
feasibility_thresholdis independent, while the underlying data (such as aLinearObjective’sc) is shared with the original. That keeps the copy cheap and preserves its type, itsis_linear, and the fast dual path. Attaching the threshold never mutates the shared data, so the original is unchanged; callers should treat that data as read-only, since in-place changes would show through both.- Parameters:
threshold (float) – Objective value below which a solve stops.
- Returns:
obj – A shallow copy of this objective with
feasibility_threshold = threshold.- Return type:
Self
- abstractmethod evaluate(w)[source]#
Evaluate the objective value f0(w).
- Parameters:
w (npt.NDArray[np.float64]) – Point at which the objective is evaluated, of length M.
- Returns:
f0 – The objective value.
- Return type:
- abstractmethod gradient(w)[source]#
Compute the gradient ∇f0(w).
- Parameters:
w (npt.NDArray[np.float64]) – Point at which the gradient is evaluated, of length M.
- Returns:
grad_f0 – The gradient, of length M.
- Return type:
npt.NDArray[np.float64]
- at(w)[source]#
Return a per-point evaluation context bound to w.
The default returns an uncached pass-through that forwards each call to the corresponding
Objectivemethod. An objective with expensive w-dependent work (forward passes, assembly of Hessian data) should override this to return a cached point, so a solver pays that cost once per iterate rather than once per call toevaluate,gradient, andhessian_contribution.- Parameters:
w (npt.NDArray[np.float64]) – Point to bind, of length M.
- Returns:
point – The evaluation context at w.
- Return type:
- btls_keep_in_domain(w, dw)[source]#
Find the largest step along a direction that stays in the domain of f0.
Returns the largest α such that w + α dw lies in dom f0. This is the domain analogue of
ConstraintLayer.btls_max_step: it bounds a line search by the geometry of dom f0 rather than of the constraint set. The default domain is all of R^M, so the bound is inf, and the line search caps the step atmin(1, β · inf) = 1,
the full Newton step.
An objective with a restricted domain (for example, a logarithm whose argument must stay positive) overrides this with the closed-form distance to the domain boundary, as a
ConstraintLayerdoes for its feasible set.BarrierSolveruses it in the mini-Newton solve that evaluates the dual: that solve minimizes the Lagrangian over unconstrained w, so dom f0 is the only geometry bounding its steps.- Parameters:
w (npt.NDArray[np.float64]) – Current point, in dom f0, of length M.
dw (npt.NDArray[np.float64]) – Step direction, of length M.
- Returns:
alpha – The largest step keeping w + α dw in dom f0; inf by default.
- Return type:
- abstractmethod hessian_contribution(w)[source]#
Return the objective’s structured Hessian as a
MatrixSystem.The owning
Problemsums the returned curvature ∇^2 f0(w) with the constraint layers’ contributions inbuild_hessian_system.- Parameters:
w (npt.NDArray[np.float64]) – Current iterate, of length M, at which the curvature is evaluated.
- Returns:
system – The objective’s curvature ∇^2 f0(w).
- Return type:
- class cvxium.problems.objective.LinearObjective(c)[source]#
Bases:
ObjectiveLinear objective f0(w) = c^T w.
The Hessian is identically zero, so the structured contribution is a
ZeroSystem, andis_linearis True.- Parameters:
c (npt.NDArray[np.float64]) – Coefficient vector of length M, converted to float64.
- is_linear = True#
Whether f0 is affine in w, so that ∇^2 f0 ≡ 0.
BarrierSolverchecks it, together with each inequality layer’sis_linear, to evaluate the dual analytically (the LP dual, decided by the gradient residual) instead of through the mini-Newton solve. The default False is safe: an affine objective that forgets to override it only takes the slower path, never a wrong one. It is a plain class attribute rather than aClassVarso that wrappers whose linearity depends on what they wrap, such asNegatedObjective, can forward the wrapped value per instance.
- property dimension#
Return the dimension M, the length of
c.- Returns:
M – The decision-variable dimension.
- Return type:
- evaluate(w)[source]#
Evaluate the objective value c^T w.
- Parameters:
w (npt.NDArray[np.float64]) – Point at which the objective is evaluated, of length M.
- Returns:
f0 – The value c^T w.
- Return type:
- hessian_contribution(w)[source]#
Return the zero Hessian of a linear objective.
- Parameters:
w (npt.NDArray[np.float64]) – Current iterate, of length M; ignored, since the Hessian is zero everywhere.
- Returns:
system – A
ZeroSystemof order M.- Return type:
- gradient(w)[source]#
Return the gradient c, which does not depend on w.
Returns a fresh copy, so callers may mutate the result without corrupting the stored
c.- Parameters:
w (npt.NDArray[np.float64]) – Point at which the gradient is evaluated, of length M; ignored.
- Returns:
grad_f0 – A copy of
c, of length M.- Return type:
npt.NDArray[np.float64]
- class cvxium.problems.objective.QuadraticObjective(c, hessian_contribution)[source]#
Bases:
ObjectiveQuadratic objective f0(w) = (1/2) w^T Q w + c^T w, with Q symmetric PSD.
The gradient is Q w + c and the Hessian is the constant Q. The caller supplies Q as a
MatrixSystemdescribing its structure:DiagonalSystemfor a diagonal Q,ZeroSystem(M).low_rank_update(kappa)for a low-rank Q = κ κ^T,DenseSystemotherwise. That system is the single source of truth: the value and gradient use itsmultiply, andhessian_contributionreturns it unchanged, so Q is never materialized or factored here and its structure is exploited end to end.- Parameters:
c (npt.NDArray[np.float64]) – Linear coefficient vector of length M, converted to float64.
hessian_contribution (MatrixSystem) – The constant Hessian Q. Its
dimensiondefines M.
- property dimension#
Return the dimension M, the order of the Hessian system.
- Returns:
M – The decision-variable dimension.
- Return type:
- hessian_contribution(w)[source]#
Return the caller-supplied
MatrixSystemfor the constant Hessian Q.- Parameters:
w (npt.NDArray[np.float64]) – Current iterate, of length M; ignored, since Q is constant.
- Returns:
system – The system given at construction (not a copy).
- Return type:
- class cvxium.problems.objective.NegatedObjective(objective)[source]#
Bases:
ObjectiveNegation -g of a wrapped objective g.
Minimizing -g maximizes g. This is the mechanism behind
Problem.maximize: a concave objective g (with negative semidefinite Hessian) is wrapped so that the solver, which only minimizes, sees the convex -g.Value and gradient negate directly. The Hessian goes through
MatrixSystem.negated: when g advertises its curvature asH.negated()for a positive semidefinite H, the second negation collapses back to H itself, so the round trip costs no arithmetic and never asks a factorization to handle a negative-definite matrix.Negation preserves linearity (-c^T w is affine exactly when c^T w is), so the wrapper forwards the wrapped objective’s
is_linear; a negatedLinearObjectivetherefore keeps the analytical LP dual path.- Parameters:
objective (Objective) – The wrapped objective g. For a maximization it should be concave; nothing here checks that, just as Cvxium does not check the convexity of a minimized objective beyond the assembled system’s positive definiteness.
- property objective#
Return the wrapped objective g (this instance represents -g).
- Returns:
objective – The objective given at construction.
- Return type:
- property dimension#
Return the dimension M, the wrapped objective’s.
- Returns:
M – The decision-variable dimension.
- Return type:
- evaluate(w)[source]#
Evaluate the objective value -g(w).
- Parameters:
w (npt.NDArray[np.float64]) – Point at which the objective is evaluated, of length M.
- Returns:
f0 – The negated wrapped value.
- Return type:
- gradient(w)[source]#
Compute the gradient -∇g(w).
- Parameters:
w (npt.NDArray[np.float64]) – Point at which the gradient is evaluated, of length M.
- Returns:
grad_f0 – The negated wrapped gradient, of length M.
- Return type:
npt.NDArray[np.float64]
- hessian_contribution(w)[source]#
Return the curvature -∇^2 g(w), the wrapped Hessian negated.
- Parameters:
w (npt.NDArray[np.float64]) – Current iterate, of length M.
- Returns:
system – The wrapped Hessian system, passed through
MatrixSystem.negated.- Return type:
- at(w)[source]#
Return a per-point context negating the wrapped objective’s point.
Delegates to
g.at(w), so any per-point caching the wrapped objective performs is preserved, then negates each reported quantity.- Parameters:
w (npt.NDArray[np.float64]) – Point to bind, of length M.
- Returns:
point – A
_NegatedObjectivePointwrappingg.at(w).- Return type:
- btls_keep_in_domain(w, dw)[source]#
Return the wrapped objective’s domain bound on the step.
Negation does not change the domain, dom(-g) = dom g, so the bound is g’s.
- Parameters:
w (npt.NDArray[np.float64]) – Current point, in dom g, of length M.
dw (npt.NDArray[np.float64]) – Step direction, of length M.
- Returns:
alpha – The largest step keeping w + α dw in dom g.
- Return type:
- class cvxium.problems.objective.LiftedObjective(objective, extra_dimension)[source]#
Bases:
ObjectiveObjective lifted to a larger space by ignoring trailing coordinates.
The objective counterpart of
LiftedConstraintLayer. The wrapped objective sees only the leadingobjective.dimensioncomponents w of the augmented vector, and is constant in theextra_dimensiontrailing components t. Use it to minimize an existing objective over an epigraph formulation, or in slack-form Phase I, where the auxiliary t carries constraints of its own but no cost.The gradient is zero-padded. A
DiagonalSystemHessian stays diagonal, with zero curvature in the trailing coordinates (a barrier term on t makes the assembled system positive definite); any other structure becomes the first block of aBlockDiagonalSystemwhose second block is aZeroSystem. Lifting preserves linearity, so the wrapper forwards the wrapped objective’sis_linear.- Parameters:
- property objective#
Return the wrapped objective.
- Returns:
objective – The objective given at construction.
- Return type:
- property dimension#
Return the augmented dimension, the wrapped dimension plus the trailing one.
- Returns:
M –
objective.dimension + extra_dimension.- Return type:
- evaluate(w)[source]#
Evaluate the wrapped objective on the leading components of w.
- Parameters:
w (npt.NDArray[np.float64]) – Augmented point, of length
dimension.- Returns:
f0 – The wrapped objective’s value at the leading
objective.dimensioncomponents.- Return type:
- gradient(w)[source]#
Compute the wrapped gradient, zero-padded in the trailing components.
- Parameters:
w (npt.NDArray[np.float64]) – Augmented point, of length
dimension.- Returns:
grad_f0 – The gradient, of length
dimension.- Return type:
npt.NDArray[np.float64]
- hessian_contribution(w)[source]#
Return the wrapped Hessian with zero curvature in the trailing components.
- Parameters:
w (npt.NDArray[np.float64]) – Augmented iterate, of length
dimension.- Returns:
system – A zero-padded
DiagonalSystemwhen the wrapped Hessian is aDiagonalSystem; otherwise aBlockDiagonalSystemof the wrapped Hessian and aZeroSystem.- Return type:
- btls_keep_in_domain(w, dw)[source]#
Return the wrapped domain bound; the trailing components are free.
- Parameters:
w (npt.NDArray[np.float64]) – Augmented point, of length
dimension.dw (npt.NDArray[np.float64]) – Augmented step direction, of length
dimension.
- Returns:
alpha – The wrapped objective’s bound on the leading components.
- Return type: