Skip to content

cvxpy

CVXPy backend for lowering symbolic expressions to disciplined convex programs.

This package implements the CVXPy lowering backend that converts symbolic expression AST nodes into CVXPy expressions and constraints for convex optimization. The lowering uses a visitor pattern where each expression type has a corresponding visitor function registered via @visitor.

The visitor functions are split across submodules that mirror the openscvx.symbolic.expr package structure. Importing this package triggers registration of all visitors.

Example::

from openscvx.symbolic.lowerers.cvxpy import CvxpyLowerer

lowerer = CvxpyLowerer(variable_map={"x": cvx_x, "u": cvx_u})
cvx_expr = lowerer.lower(expr)

CvxpyLowerer

CVXPy backend for lowering symbolic expressions to disciplined convex programs.

This class implements the visitor pattern for converting symbolic expression AST nodes to CVXPy expressions and constraints. Each expression type has a corresponding visitor function decorated with @visitor that handles the lowering logic.

The lowering process is recursive: each visitor lowers its child expressions first, then composes them into a CVXPy operation. CVXPy will validate DCP (Disciplined Convex Programming) compliance when the problem is constructed.

Attributes:

Name Type Description
variable_map dict

Dictionary mapping variable names to CVXPy expressions. Must include "x" for states and "u" for controls. May include parameter names mapped to CVXPy Parameter objects or constants.

Example

Lower an expression to CVXPy::

import cvxpy as cp
lowerer = CvxpyLowerer(variable_map={
    "x": cp.Variable(3),
    "u": cp.Variable(2),
})
expr = ox.Norm(x)**2 + 0.1 * ox.Norm(u)**2
cvx_expr = lowerer.lower(expr)
Note

The lowerer is stateful (stores variable_map) unlike JaxLowerer which is stateless. Variables must be registered before lowering expressions that reference them.

Source code in openscvx/symbolic/lowerers/cvxpy/_lowerer.py
class CvxpyLowerer:
    """CVXPy backend for lowering symbolic expressions to disciplined convex programs.

    This class implements the visitor pattern for converting symbolic expression
    AST nodes to CVXPy expressions and constraints. Each expression type has a
    corresponding visitor function decorated with @visitor that handles the
    lowering logic.

    The lowering process is recursive: each visitor lowers its child expressions
    first, then composes them into a CVXPy operation. CVXPy will validate DCP
    (Disciplined Convex Programming) compliance when the problem is constructed.

    Attributes:
        variable_map (dict): Dictionary mapping variable names to CVXPy expressions.
            Must include "x" for states and "u" for controls. May include parameter
            names mapped to CVXPy Parameter objects or constants.

    Example:
        Lower an expression to CVXPy::

            import cvxpy as cp
            lowerer = CvxpyLowerer(variable_map={
                "x": cp.Variable(3),
                "u": cp.Variable(2),
            })
            expr = ox.Norm(x)**2 + 0.1 * ox.Norm(u)**2
            cvx_expr = lowerer.lower(expr)

    Note:
        The lowerer is stateful (stores variable_map) unlike JaxLowerer which
        is stateless. Variables must be registered before lowering expressions
        that reference them.
    """

    def __init__(self, variable_map: Dict[str, cp.Expression] = None):
        """Initialize the CVXPy lowerer.

        Args:
            variable_map: Dictionary mapping variable names to CVXPy expressions.
                For State/Control objects, keys should be "x" and "u" respectively.
                For Parameter objects, keys should match their names. If None, an
                empty dictionary is created.
        """
        self.variable_map = variable_map or {}

    def register_variable(self, name: str, value: cp.Expression):
        """Register a variable in the variable map.

        Args:
            name: Variable name (e.g., "x", "u", or parameter name)
            value: CVXPy expression to associate with the name
        """
        self.variable_map[name] = value

    def lower(self, expr: Expr) -> cp.Expression:
        """Lower a symbolic expression to a CVXPy expression.

        Main entry point for lowering. Delegates to dispatch() which looks up
        the appropriate visitor method based on the expression type.

        Args:
            expr: Symbolic expression to lower (any Expr subclass)

        Returns:
            CVXPy expression or constraint

        Raises:
            NotImplementedError: If no visitor exists for the expression type
            ValueError: If required variables are missing from variable_map
        """
        return dispatch(self, expr)
__init__(variable_map: Dict[str, cp.Expression] = None)

Initialize the CVXPy lowerer.

Parameters:

Name Type Description Default
variable_map Dict[str, Expression]

Dictionary mapping variable names to CVXPy expressions. For State/Control objects, keys should be "x" and "u" respectively. For Parameter objects, keys should match their names. If None, an empty dictionary is created.

None
Source code in openscvx/symbolic/lowerers/cvxpy/_lowerer.py
def __init__(self, variable_map: Dict[str, cp.Expression] = None):
    """Initialize the CVXPy lowerer.

    Args:
        variable_map: Dictionary mapping variable names to CVXPy expressions.
            For State/Control objects, keys should be "x" and "u" respectively.
            For Parameter objects, keys should match their names. If None, an
            empty dictionary is created.
    """
    self.variable_map = variable_map or {}
lower(expr: Expr) -> cp.Expression

Lower a symbolic expression to a CVXPy expression.

Main entry point for lowering. Delegates to dispatch() which looks up the appropriate visitor method based on the expression type.

Parameters:

Name Type Description Default
expr Expr

Symbolic expression to lower (any Expr subclass)

required

Returns:

Type Description
Expression

CVXPy expression or constraint

Raises:

Type Description
NotImplementedError

If no visitor exists for the expression type

ValueError

If required variables are missing from variable_map

Source code in openscvx/symbolic/lowerers/cvxpy/_lowerer.py
def lower(self, expr: Expr) -> cp.Expression:
    """Lower a symbolic expression to a CVXPy expression.

    Main entry point for lowering. Delegates to dispatch() which looks up
    the appropriate visitor method based on the expression type.

    Args:
        expr: Symbolic expression to lower (any Expr subclass)

    Returns:
        CVXPy expression or constraint

    Raises:
        NotImplementedError: If no visitor exists for the expression type
        ValueError: If required variables are missing from variable_map
    """
    return dispatch(self, expr)
register_variable(name: str, value: cp.Expression)

Register a variable in the variable map.

Parameters:

Name Type Description Default
name str

Variable name (e.g., "x", "u", or parameter name)

required
value Expression

CVXPy expression to associate with the name

required
Source code in openscvx/symbolic/lowerers/cvxpy/_lowerer.py
def register_variable(self, name: str, value: cp.Expression):
    """Register a variable in the variable map.

    Args:
        name: Variable name (e.g., "x", "u", or parameter name)
        value: CVXPy expression to associate with the name
    """
    self.variable_map[name] = value

lower_to_cvxpy(expr: Expr, variable_map: Dict[str, cp.Expression] = None) -> cp.Expression

Lower symbolic expression to CVXPy expression or constraint.

Convenience wrapper that creates a CvxpyLowerer and lowers a single symbolic expression to a CVXPy expression. The result can be used in CVXPy optimization problems.

Parameters:

Name Type Description Default
expr Expr

Symbolic expression to lower (any Expr subclass)

required
variable_map Dict[str, Expression]

Dictionary mapping variable names to CVXPy expressions. Must include "x" for states and "u" for controls. May include parameter names mapped to CVXPy Parameters or constants.

None

Returns:

Type Description
Expression

CVXPy expression for arithmetic expressions (Add, Mul, Norm, etc.)

Expression

or CVXPy constraint for constraint expressions (Equality, Inequality)

Raises:

Type Description
NotImplementedError

If the expression type is not supported

ValueError

If required variables are missing from variable_map

Source code in openscvx/symbolic/lowerers/cvxpy/_lowerer.py
def lower_to_cvxpy(expr: Expr, variable_map: Dict[str, cp.Expression] = None) -> cp.Expression:
    """Lower symbolic expression to CVXPy expression or constraint.

    Convenience wrapper that creates a CvxpyLowerer and lowers a single
    symbolic expression to a CVXPy expression. The result can be used in
    CVXPy optimization problems.

    Args:
        expr: Symbolic expression to lower (any Expr subclass)
        variable_map: Dictionary mapping variable names to CVXPy expressions.
            Must include "x" for states and "u" for controls. May include
            parameter names mapped to CVXPy Parameters or constants.

    Returns:
        CVXPy expression for arithmetic expressions (Add, Mul, Norm, etc.)
        or CVXPy constraint for constraint expressions (Equality, Inequality)

    Raises:
        NotImplementedError: If the expression type is not supported
        ValueError: If required variables are missing from variable_map
    """
    lowerer = CvxpyLowerer(variable_map)
    return lowerer.lower(expr)