Skip to main content
Version: v0.7.0 beta

Transition Equality Constraint Definition

Transition equality constraints describe the equality relationships of optimization variables between adjacent stages. OPTIMake supports the following types of transition equality constraints:

  • differential_equation: Differential equation
  • discrete_equation: Discrete equation
  • external_discrete_equation: Discrete equation, defined through external C/C++ functions

After defining the constraint, use the following interface to add it:

prob.equality(eq, weight_soft, penalty_type)

The function parameters of the equality interface are defined as follows (see Constraint Transformation for details on constraint softening):

  • eq: The transition equality constraint, type can be differential_equation, discrete_equation, external_discrete_equation
  • weight_soft: The penalty weight when softening this constraint, must be non-negative, can be a constant or an expression in terms of parameter pp, default value is all inf, indicating a hard constraint. This parameter can be a list with the same dimension as the constraint or a single value (meaning the same penalty weight is used for each dimension of the constraint)
  • penalty_type: The penalty type for softening this constraint, options are 'none', 'quadratic', 'l1', default value is all 'none', indicating a hard constraint. This parameter can be a list with the same dimension as the constraint or a single value (meaning the same penalty type is used for each dimension of the constraint)
info
  • When the constraint type is external_discrete_equation or differential_equation (with discretization_method set to 'irk2' or 'irk4'), prob.equality can only be called once to set the constraint
  • For other constraint types, prob.equality can be called multiple times to add multiple constraints

differential_equation

differential_equation defines a transition equality constraint of the form x˙=h(v,p)\dot x = h(v,p), which requires specifying a discretization step size and discretization method.

Below is an example of defining a transition equality constraint through the differential_equation interface:

# ts, length are previously defined parameters
eq = differential_equation(
state=[x, y, phi],
state_dot=[v * cos(phi), v * sin(phi), v * tan(delta) / length],
stepsize=ts,
discretization_method='forward_euler')
prob.equality(eq)

The function parameters of the differential_equation interface are defined as follows:

  • state: The state variables, corresponding to xx, type is a list of optimization variables

  • state_dot: The state derivatives, corresponding to h(v,p)h(v,p), type is list

  • stepsize: The discretization step size, can be a constant, an expression in terms of parameter pp, or an expression in terms of optimization variable vv

  • discretization_method: The discretization method, options are:

    • 'forward_euler': Forward Euler
    • 'erk2': Explicit 2nd-order Runge-Kutta
    • 'erk4': Explicit 4th-order Runge-Kutta
    • 'backward_euler': Backward Euler
    • 'trapezoid': Trapezoidal rule
    • 'irk2': Implicit 2nd-order Runge-Kutta (midpoint rule)
    • 'irk4': Implicit 4th-order Runge-Kutta

discrete_equation

A discrete equation has the form hnext(vi+1,pi+1)=hthis(vi,p)h_{next}(v_{i+1}, p_{i+1}) = h_{this}(v_i, p). Below is an example of defining a transition equality constraint through the discrete equation interface (a discrete system using the 'forward_euler' method):

# ts, length are previously defined parameters
eq = discrete_equation(
expr_this_stage=[
x + ts * v * cos(phi),
y + ts * v * sin(phi),
phi + ts * v * tan(delta) / length],
expr_next_stage=[x, y, phi])
prob.equality(eq)

The parameters of the discrete equation interface are as follows:

  • expr_this_stage: The function expression for the current stage, corresponding to hthis(vi,p)h_{this}(v_i, p), type is list
  • expr_next_stage: The function expression for the next stage, corresponding to hnext(vi+1,pi+1)h_{next}(v_{i+1}, p_{i+1}), type is list
info

If you only need to describe the equality relationship of optimization variables within the current stage, you can set expr_this_stage or expr_next_stage to all zeros.

external_discrete_equation

A discrete_equation defined through external C/C++ functions, with the form hnext(vi+1,pi+1)=hthis(vi,p)h_{next}(v_{i+1}, p_{i+1}) = h_{this}(v_i, p). During modeling, the sparsity of its Jacobian & Hessian can be specified to accelerate computation.

Below is an example of external_discrete_equation:

eq_spy_jac_this = \
[[1, 0, 1, 1],
[0, 1, 1, 1],
[0, 0, 1, 1]]

eq_spy_jac_next = \
[[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0]]

eq_spy_hess_this = \
[[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 1, 1],
[0, 0, 1, 1]]

eq_spy_hess_next = \
[[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]]

eq = external_discrete_equation(
dim = 3,
sparsity_jacobian_this_stage=eq_spy_jac_this,
sparsity_jacobian_next_stage=eq_spy_jac_next,
sparsity_hessian_this_stage=eq_spy_hess_this,
sparsity_hessian_next_stage=eq_spy_hess_next)
prob.equality(eq)

The parameters of the external_discrete_equation interface are as follows:

  • dim: The dimension of the constraint
  • sparsity_jacobian_this_stage (optional): The sparsity pattern of the Jacobian of hthis(vi,p)h_{this}(v_i, p), a matrix of dimension dim×nv\times n_{v}, where 0 represents sparse and 1 represents dense; default value is all 1.0
  • sparsity_jacobian_next_stage (optional): The sparsity pattern of the Jacobian of hnext(vi+1,pi+1)h_{next}(v_{i+1}, p_{i+1}), a matrix of dimension dim×nv\times n_{v}, where 0 represents sparse and 1 represents dense; default value is all 1.0
  • sparsity_hessian_this_stage (optional): The sparsity pattern of the Hessian of yThthis(vi,p)y^T h_{this}(v_i, p) (where y is a Lagrange multiplier of dimension dim×1\times 1), a symmetric matrix of dimension nv×nvn_{v} \times n_{v}, where 0 represents sparse and 1 represents dense; default value is all 1.0
  • sparsity_hessian_next_stage (optional): The sparsity pattern of the Hessian of yThnext(vi+1,pi+1)y^T h_{next}(v_{i+1}, p_{i+1}), a symmetric matrix of dimension nv×nvn_{v} \times n_{v}, where 0 represents sparse and 1 represents dense; default value is all 1.0