symbolic
Symbolic expression system for trajectory optimization.
See openscvx.symbolic.expr for detailed documentation and examples.
ConstraintSet
dataclass
¶
Container for categorized symbolic constraints.
This dataclass holds all symbolic constraint types in a structured way, providing type safety and a clear API for accessing constraint categories. This is a pre-lowering container - after lowering, constraints live in LoweredJaxConstraints and LoweredCvxpyConstraints.
The constraint set supports two lifecycle stages:
- Before preprocessing: Raw constraints live in
unsorted - After preprocessing:
unsortedis empty, constraints are categorized
Use is_categorized to check which stage the constraint set is in.
Attributes:
| Name | Type | Description |
|---|---|---|
unsorted |
List[Union[Constraint, CTCS]]
|
Raw constraints before categorization. Empty after preprocessing. |
ctcs |
List[CTCS]
|
CTCS (continuous-time) constraints. |
nodal |
List[NodalConstraint]
|
Non-convex nodal constraints (will be lowered to JAX). |
nodal_convex |
List[NodalConstraint]
|
Convex nodal constraints (will be lowered to CVXPy). |
cross_node |
List[CrossNodeConstraint]
|
Non-convex cross-node constraints (will be lowered to JAX). |
cross_node_convex |
List[CrossNodeConstraint]
|
Convex cross-node constraints (will be lowered to CVXPy). |
Example
Before preprocessing (raw constraints)::
constraints = ConstraintSet(unsorted=[c1, c2, c3])
assert not constraints.is_categorized
After preprocessing (categorized)::
# preprocess_symbolic_problem drains unsorted -> fills categories
assert constraints.is_categorized
for c in constraints.nodal:
# Process non-convex nodal constraints
pass
Source code in openscvx/symbolic/constraint_set.py
is_categorized: bool
property
¶
True if all constraints have been sorted into categories.
After preprocessing, unsorted should be empty and all constraints
should be in their appropriate category lists.
SymbolicProblem
dataclass
¶
Container for symbolic problem specification.
This dataclass holds a trajectory optimization problem in symbolic form, either as raw user input or after preprocessing/augmentation. It provides a typed interface for the preprocessing and lowering pipeline.
Lifecycle Stages
- Before preprocessing: User creates with raw dynamics, states, controls, and unsorted constraints. Propagation fields are None.
- After preprocessing: Dynamics and states are augmented (CTCS, time dilation), constraints are categorized, propagation fields are populated.
Use is_preprocessed to check whether preprocessing has completed.
Attributes:
| Name | Type | Description |
|---|---|---|
dynamics |
Expr
|
Symbolic dynamics expression (dx/dt = f(x, u)). After preprocessing, includes CTCS augmented state dynamics. |
states |
List[State]
|
List of State objects. After preprocessing, includes time state and CTCS augmented states. |
controls |
List[Control]
|
List of Control objects. After preprocessing, includes time dilation control. |
constraints |
ConstraintSet
|
ConstraintSet holding all constraints. Before preprocessing,
raw constraints live in |
parameters |
Dict[str, any]
|
Dictionary mapping parameter names to numpy arrays. |
N |
int
|
Number of discretization nodes. |
node_intervals |
List[Tuple[int, int]]
|
List of (start, end) tuples for CTCS constraint intervals. Populated during preprocessing when CTCS constraints are sorted. |
dynamics_prop |
Optional[Expr]
|
Propagation dynamics (may include extra states). None before preprocessing, populated after. |
states_prop |
Optional[List[State]]
|
Propagation states (may include extra states). None before preprocessing, populated after. |
controls_prop |
Optional[List[Control]]
|
Propagation controls (typically same as controls). None before preprocessing, populated after. |
algebraic_prop |
Optional[Dict[str, Expr]]
|
Algebraic outputs computed during propagation (no integration). None before preprocessing, populated after. |
Example
Before preprocessing::
problem = SymbolicProblem(
dynamics=dynamics_expr,
states=[x, v],
controls=[u],
constraints=ConstraintSet(unsorted=[c1, c2, c3]),
parameters={"mass": 1.0},
N=50,
)
assert not problem.is_preprocessed
After preprocessing::
processed = preprocess_symbolic_problem(problem, time=time_config)
assert processed.is_preprocessed
assert processed.constraints.is_categorized
# Now ready for lowering
lowered = lower_symbolic_problem(processed)
Source code in openscvx/symbolic/problem.py
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | |
is_preprocessed: bool
property
¶
True if the problem has been preprocessed and is ready for lowering.
A problem is considered preprocessed when: 1. All constraints have been categorized (unsorted is empty) 2. Propagation dynamics have been set up
citations() -> Dict[str, List[str]]
¶
Collect BibTeX citations from every expression node in the problem.
Walks the dynamics, constraint, and propagation expression graphs and
gathers :meth:~openscvx.symbolic.expr.expr.Expr.citation from each
node, so :meth:openscvx.Problem.citation can credit the published
methods a problem actually uses (e.g. GMSR STL operators, jaxlie-backed
Lie-group maps). Works at either lifecycle stage: unsorted constraints
are scanned before preprocessing, categorized ones after.
Returns:
| Type | Description |
|---|---|
Dict[str, List[str]]
|
Mapping from node class name to the deduplicated BibTeX entries |
Dict[str, List[str]]
|
cited by nodes of that name, containing only names that cite |
Dict[str, List[str]]
|
anything. Same-named classes (e.g. the GMSR and stljax |
Dict[str, List[str]]
|
share a key; their entries are merged. |