Skip to content

Constraints

openscvx.constraints.ctcs.CTCSConstraint dataclass

Dataclass for continuous-time constraint satisfaction (CTCS) constraints over a trajectory interval.

A CTCSConstraint wraps a residual function func(x, u), applies a pointwise penalty to its outputs, and accumulates the penalized sum only within a specified node interval [nodes[0], nodes[1]).

CTCS constraints are used for continuous-time constraints that need to be satisfied over trajectory intervals rather than at specific nodes. The constraint function should return residuals where positive values indicate constraint violations.

Usage examples:

@ctcs
def g(x_, u_):
    return 2.0 - jnp.linalg.norm(x_[:3])  # ||x[:3]|| <= 2 constraint
@ctcs(penalty="huber", nodes=(0, 10), idx=2)
def g(x_, u_):
    return jnp.sin(x_) + u_  # sin(x) + u <= 0 constraint
@ctcs(penalty="smooth_relu", scaling=0.5)
def g(x_, u_):
    return x_[0]**2 + x_[1]**2 - 1.0  # ||x||^2 <= 1 constraint

Or can directly wrap a function if a more lambda-function interface is desired:

constraint = ctcs(lambda x_, u_: jnp.maximum(0, x[0] - 1.0))

Parameters:

Name Type Description Default
func Callable[[ndarray, ndarray], ndarray]

Function computing constraint residuals g(x, u). - x: 1D array (state at a single node), shape (n_x,) - u: 1D array (control at a single node), shape (n_u,) - Additional parameters: passed as keyword arguments with names matching the parameter name plus an underscore (e.g., g_ for Parameter('g')). Should return positive values for constraint violations (g(x,u) > 0 indicates violation). If you want to use parameters, include them as extra arguments with the underscore naming convention.

required
penalty Callable[[ndarray], ndarray]

Penalty function applied elementwise to g's output. Used to calculate and penalize constraint violation during state augmentation. Common penalties include: - "squared_relu": max(0, x)² (default) - "huber": smooth approximation of absolute value - "smooth_relu": differentiable version of ReLU

required
nodes Optional[Tuple[int, int]]

Half-open interval (start, end) of node indices where this constraint is active. If None, the penalty applies at every node.

None
idx Optional[int]

Optional index used to group CTCS constraints. Used during automatic state augmentation. All CTCS constraints with the same index must be active over the same nodes interval

None
grad_f_x Optional[Callable[[ndarray, ndarray], ndarray]]

User-supplied gradient of func w.r.t. state x, signature (x, u) -> jacobian. If None, computed via jax.jacfwd(func, argnums=0) during state augmentation.

None
grad_f_u Optional[Callable[[ndarray, ndarray], ndarray]]

User-supplied gradient of func w.r.t. input u, signature (x, u) -> jacobian. If None, computed via jax.jacfwd(func, argnums=1) during state augmentation.

None
scaling float

Scaling factor to apply to the penalized sum.

1.0

openscvx.constraints.nodal.NodalConstraint dataclass

Encapsulates a constraint function applied at specific trajectory nodes.

A NodalConstraint wraps a function g(x, u) that computes constraint residuals for given state x and input u. It can optionally apply only at a subset of trajectory nodes, support vectorized evaluation across nodes, and integrate with convex solvers when convex=True.

Expected input types:

Case x, u type/shape
convex=False, vectorized=False 1D arrays, shape (n_x,), (n_u,) (single node)
convex=False, vectorized=True 2D arrays, shape (N, n_x), (N, n_u) (all nodes)
convex=True, vectorized=False list of cvxpy variables, one per node
convex=True, vectorized=True list of cvxpy variables, one per node

Expected output:

Case Output type
convex=False, vectorized=False float (single node)
convex=False, vectorized=True float array (per node)
convex=True, vectorized=False cvxpy expression (single node)
convex=True, vectorized=True list of cvxpy expressions (one per node)

Nonconvex examples:

@nodal
def g(x_, u_):
    return 1 - x_[0] <= 0
@nodal(nodes=[0, 3])
def g(x_, u_):
    return jnp.linalg.norm(x_) - 1.0

Or can directly wrap a function if a more lambda-function interface is desired:

constraint = nodal(lambda x_, u_: 1 - x_[0])

Convex Examples:

@nodal(convex=True)
def g(x_, u_):
    return cp.norm(x_) <= 1.0  # cvxpy expression following DPP rules

Expected input types:

Case x, u type/shape
convex=False, vectorized=False 1D arrays, shape (n_x,), (n_u,) (single node)
convex=False, vectorized=True 2D arrays, shape (N, n_x), (N, n_u) (all nodes)
convex=True, vectorized=False list of cvxpy variables, one per node
convex=True, vectorized=True list of cvxpy variables, one per node

Expected output:

Case Output type
convex=False, vectorized=False float (single node)
convex=False, vectorized=True float array (per node)
convex=True, vectorized=False cvxpy expression (single node)
convex=True, vectorized=True list of cvxpy expressions (one per node)

Nonconvex examples:

@nodal
def g(x_, u_):
    return 1 - x_[0] <= 0
@nodal(nodes=[0, 3])
def g(x_, u_):
    return jnp.linalg.norm(x_) - 1.0 

Or can directly wrap a function if a more lambda-function interface is desired:

constraint = nodal(lambda x_, u_: 1 - x_[0])

Convex Examples:

@nodal(convex=True)
def g(x_, u_):
    return cp.norm(x_) <= 1.0  # cvxpy expression following DPP rules

Parameters:

Name Type Description Default
func Callable

The user-supplied constraint function. The expected input and output types depend on the values of convex and vectorized:

Input/Output types: - convex=False, vectorized=False: x,u are 1D arrays (n_x,), (n_u,), returns float - convex=False, vectorized=True: x,u are 2D arrays (N, n_x), (N, n_u), returns float array - convex=True, vectorized=False: x,u are cvxpy variables, returns cvxpy expression - convex=True, vectorized=True: x,u are cvxpy variables, returns list of cvxpy expressions

Additional parameters: always passed as keyword arguments with names matching the parameter name plus an underscore (e.g., g_ for Parameter('g')). For nonconvex constraints, the function should return constraint residuals (g(x,u) <= 0). For convex constraints, the function should return a cvxpy expression.

required
nodes Optional[List[int]]

Specific node indices where this constraint applies. If None, applies at all nodes.

None
convex bool

If True, the provided cvxpy.expression is directly passed to the cvxpy.problem.

False
vectorized bool

If False, automatically vectorizes func and its jacobians over the node dimension using jax.vmap. If True, assumes func already handles vectorization.

False
grad_g_x Optional[Callable[[ndarray, ndarray], ndarray]]

User-supplied gradient of func wrt x. If None, computed via jax.jacfwd(func, argnums=0).

None
grad_g_u Optional[Callable[[ndarray, ndarray], ndarray]]

User-supplied gradient of func wrt u. If None, computed via jax.jacfwd(func, argnums=1).

None
get_cvxpy_constraints(x, u, *args, **kwargs)

Evaluate the constraint function and always return a flat list of cvxpy constraints.