constraints#
Linear constraints for monotone Bernstein coefficient optimisation.
- class mltpy.constraints.BoundaryConstraint(n_params, lower, upper, total_params=None)[source]#
Bases:
objectFix one or both boundary coefficients of the Bernstein expansion.
Enforces equality constraints:
theta[0] == lower (if lower is not None) theta[n_params-1] == upper (if upper is not None)
- Parameters:
n_params (
int) – Number of Bernstein coefficients.lower (
float|None) – Value to fixtheta[0]to, orNoneto leave it free.upper (
float|None) – Value to fixtheta[n_params-1]to, orNoneto leave it free.total_params (
int|None) – Total length of the parameter vector passed to the optimiser, including any regression coefficients. Whentotal_params > n_paramsthe constraint rows are padded with zero columns for the beta entries so that_Ahas shape(n_active, total_params). Defaults ton_params(no beta).
- as_LinearConstraint()[source]#
Return a
LinearConstraintfor use withtrust-constr.Both
lbandubare set torhs(equality).- Return type:
- class mltpy.constraints.ConstraintMatrices(A_ineq, b_ineq, C_eq, d_eq)[source]#
Bases:
objectConstraint matrices in the canonical form used by
auglag_minimize().Represents the linear constraints as:
A_ineq @ θ ≥ b_ineq (inequality) C_eq @ θ = d_eq (equality)
- Parameters:
A_ineq (
ndarray[tuple[Any,...],dtype[double]]) – Inequality constraint matrix, shape (m_ineq, total_params).b_ineq (
ndarray[tuple[Any,...],dtype[double]]) – Inequality right-hand side, shape (m_ineq,).C_eq (
ndarray[tuple[Any,...],dtype[double]]) – Equality constraint matrix, shape (m_eq, total_params). Zero-row matrix when there are no equality constraints.d_eq (
ndarray[tuple[Any,...],dtype[double]]) – Equality right-hand side, shape (m_eq,). Zero-length array when there are no equality constraints.
- class mltpy.constraints.MonotonicityConstraint(n_params)[source]#
Bases:
objectEncodes the constraint that Bernstein coefficients are non-decreasing.
For a coefficient vector
thetaof lengthn_params, monotonicity of the transformation h(y) = B_k(y) · theta requires:theta[0] <= theta[1] <= ... <= theta[n_params-1]
This is equivalent to the linear inequality:
D @ theta >= 0
where
Dis the(n_params-1, n_params)forward-difference matrix:D = [[-1, 1, 0, 0, ...], [ 0, -1, 1, 0, ...], [ 0, 0, -1, 1, ...], ...]
- Parameters:
n_params (
int) – Number of Bernstein coefficients (= polynomial degree + 1).
- mltpy.constraints.build_constraint_matrices(n_params, lower=None, upper=None, *, total_params=None, nonneg_lower=False, X=None)[source]#
Build constraint matrices for the augmented Lagrangian solver.
Returns a
ConstraintMatricesdataclass whose fields are passed directly toauglag_minimize().Monotonicity (
A_ineq @ θ ≥ 0) is always included. Whenlowerorupperare provided, equality rows pinningθ[0] = lowerand/orθ[n_params-1] = upperare added toC_eq/d_eq— mirroringBoundaryConstraint.- Parameters:
n_params (
int) – Number of Bernstein coefficients (=BernsteinBasis.order + 1).lower (
float|None) – If notNone, pinsθ[0] = lower(equality).upper (
float|None) – If notNone, pinsθ[n_params-1] = upper(equality).total_params (
int|None) – Total parameter-vector length including any regression coefficients. Whentotal_params > n_paramsboth the monotonicity matrix and the boundary rows are padded with zero columns for thebetablock. Defaults ton_params.nonneg_lower (
bool) –If
True, append support-feasibility inequality rows so the transformation stays in the exponential support[0, ∞). Mirrors thenonneg_lowerbranch ofbuild_constraints():No covariates (
X is None): a single row[1, 0, …, 0]enforcingθ_b[0] ≥ 0.With covariates: one row
[1, 0, …, 0 | X_i]per observation, enforcingθ_b[0] + X_i · β ≥ 0.
X (
ndarray[tuple[Any,...],dtype[double]] |None) – Covariate matrix, shape(n, q). Only consulted whennonneg_lower=True;qmust equaltotal_params - n_params.
- Returns:
A_ineqis the padded forward-difference matrix D (shape(n_params-1, total_params)) optionally followed by the support rows;b_ineqis all-zeros.C_eqhas 0, 1, or 2 rows depending on which oflower/upperare provided;d_eqcarries the corresponding right-hand-side values.- Return type:
- Raises:
ValueError – If
Xhas invalid shape, ifXcolumns do not matchtotal_params - n_params, or ifnonneg_lower=TruewithXbuttotal_paramsis omitted.
- mltpy.constraints.build_constraint_matrices_interaction(basis)[source]#
Build constraint matrices for an
InteractionBasis.Constructs the Kronecker inequality
(D ⊗ I_q) @ vec(Θ) ≥ 0that enforces column-wise monotonicity:D @ Θ[:, j] ≥ 0for every columnj = 0, …, q-1.- Parameters:
basis (
InteractionBasis) – TheInteractionBasisto build constraints for.- Returns:
A_ineqhas shape((p-1)*q, p*q).b_ineqis all-zeros.C_eqis a zero-row matrix (no equality constraints).d_eqis a zero-length array.- Return type:
- Raises:
ValueError – If the x-basis type is not supported for closed-form constraints. (This is already checked at
InteractionBasisconstruction time, so this branch is a safety net.)
- mltpy.constraints.build_constraints(n_params, lower=None, upper=None, *, solver='slsqp', total_params=None, nonneg_lower=False, X=None)[source]#
- Overloads:
n_params (int), lower (float | None), upper (float | None), solver (Literal[‘slsqp’]), total_params (int | None), nonneg_lower (bool), X (NDArray[np.float64] | None) → list[dict[str, Any]]
n_params (int), lower (float | None), upper (float | None), solver (Literal[‘trust-constr’]), total_params (int | None), nonneg_lower (bool), X (NDArray[np.float64] | None) → list[LinearConstraint]
- Parameters:
- Return type:
Build all optimisation constraints for a Bernstein model.
Always includes the monotonicity constraint (non-decreasing
theta). Optionally adds boundary equality constraints whenlowerorupperare specified, and support-feasibility inequalities whennonneg_loweris set (see below).optimizer.pycalls this function — it does not instantiate the constraint classes directly.- Parameters:
n_params (
int) – Number of Bernstein coefficients (=BernsteinBasis.order + 1).solver (
Literal['slsqp','trust-constr']) –"slsqp"→ returnslist[dict](forscipy.optimize.minimizewith
method="SLSQP")."trust-constr"→ returnslist[LinearConstraint](formethod="trust-constr").
total_params (
int|None) – Total length of the parameter vector passed to the optimiser, including any regression coefficients (beta). Whentotal_params > n_paramsthe constraint matrix is padded with zero columns so that it maps the fullthetavector. Defaults ton_params(no beta). Ifnonneg_lower=TrueandXis passed, this must be provided as the full parameter lengthn_params + X.shape[1].nonneg_lower (
bool) –If
True, requireh(y|x) >= 0. Used forbase_distribution="exponential", whose support is[0, ∞).No covariates (
X is None): the single inequalitytheta_b[0] >= 0is sufficient, sinceh(y) = B_k(y) · theta_bandmin_y B_k(y) · theta_b = theta_b[0]under monotonicity.With covariates:
h(y|x) = B_k(y) · theta_b + x'β; the minimum overyis attained aty_min(becausetheta_bis non-decreasing andB_k(y_min) = [1, 0, ..., 0]), givingmin_y h(y|x_i) = theta_b[0] + X_i · βper observationi. One inequalitytheta_b[0] + X_i · β >= 0is added per row ofX, making the training fit feasible under the exponential support.
Kept distinct from
lowerbecauseloweris an equality that pinstheta[0].X (
ndarray[tuple[Any,...],dtype[double]] |None) – Optional covariate matrix of shape(n, q). Only consulted whennonneg_lower=True— see above.qmust equaltotal_params - n_params.
- Raises:
ValueError – If
Xhas invalid shape, ifXcolumns do not matchtotal_params - n_params, or ifnonneg_lower=TruewithXbuttotal_paramsis omitted.- Returns:
list[dict] for
solver="slsqp", list[LinearConstraint] forsolver="trust-constr".
- Return type: