pockit.base.phasebase

class BcType(enum.Enum):

Enum class to represent the type of boundary conditions.

FREE = <BcType.FREE: 0>

Free boundary condition.

FIXED = <BcType.FIXED: 1>

Fixed boundary condition.

FUNC = <BcType.FUNC: 2>

Boundary condition as a function of static parameters.

class BcInfo(BcInfo):

Named tuple to store boundary condition information.

BcInfo(t, v)

Create new instance of BcInfo(t, v)

t: BcType

Type of the boundary condition.

v: None | float | pockit.base.fastfunc.FastFunc

Value of the boundary condition.

class PhaseBase(abc.ABC):

A phase is a lower level objective of a multiple-phase optimal control problem.

PhaseBase( identifier: int, state: int | list[str], control: int | list[str], symbol_static_parameter: list[sympy.core.symbol.Symbol], simplify: bool = False, parallel: bool = False, fastmath: bool = False)

Initialize a phase with given state, control, and static variables.

States and controls can be given as the number of variables or the list of variable names. If names are given, they are used as the names of the variables. Otherwise, the names are generated automatically as \( x_0, x_1, \dots, x_{n - 1} \).

Static variables should be identical to those defined in the system level.

The identifier should be unique for each phase in a given system to avoid possible name conflict.

It is recommended to use the System.new_phase() method of the System object to create phases instead of manually using this method.

If simplify is True, every symbolic expression will be simplified (by sympy.simplify()) before being compiled. This will slow down the speed of compilation.

If parallel is True, the parallel flag will be passed to the Numba JIT compiler, which will generate parallel code for multicore CPUs. This will slow down the speed of compilation and sometimes the speed of execution.

If fastmath is True, the fastmath flag will be passed to the Numba JIT compiler, see Numba and LLVM documentations for details.

Arguments:
  • state: Number of state variables or list of state variable names.
  • control: Number of control variables or list of control variable names.
  • symbol_static_parameter: list of static parameters, should be identical to those in the System object.
  • identifier: Unique identifier of the phase.
  • simplify: Whether to use Sympy to simplify sympy.Expr before compilation.
  • parallel: Whether to use Numba parallel mode.
  • fastmath: Whether to use Numba fastmath mode.
def set_dynamics( self, dynamics: list[float | sympy.core.expr.Expr], *, cache: Optional[str] = None) -> Self:

Set the dynamics of the phase.

Arguments:
  • dynamics: List of time derivatives of states composed with x, u, t, and s.
  • cache: Path to the directory to store the compiled functions.
def set_integral( self, integral: list[float | sympy.core.expr.Expr], *, cache: Optional[str] = None) -> Self:

Set the integrals of the phase.

Symbols \( I_0, I_1, \dots, I_{n - 1} \) will be automatically generated and set as a list as the attribute I to represent corresponding integrals.

Arguments:
  • integral: List of integrals to be concerned composed with x, u, t, and s.
  • cache: Path to the directory to store the compiled functions.
def set_phase_constraint( self, phase_constraint: list[sympy.core.expr.Expr], lower_bound: list[float], upper_bound: list[float], bang_bang_control: bool | list[bool] = False, *, cache: Optional[str] = None) -> Self:

Set phase constraints of the system, which is enforced in the entire time interval of the phase.

For equality constraints, set the corresponding entry of lower_bounds and upper_bounds to the same value. For one-sided inequality constraints, set the corresponding entry of lower_bounds or upper_bounds to -inf or inf. If the problem to be solved is a bang-bang control problem, set bang_bang_control as a list of bools indicating whether the corresponding phase constraint is a bang-bang constraint. If all phase constraints are bang-bang constraints, bang_bang_control can also be set to True directly.

Arguments:
  • phase_constraint: List of phase constraints composed with x, u, t, and s
  • lower_bound: List of lower bounds of phase constraints
  • upper_bound: List of upper bounds of phase constraints
  • bang_bang_control: List of bools indicating whether the corresponding phase constraint is a bang-bang constraint. Alternatively, set bang_bang_control as a single bool to apply to all phase constraints.
  • cache: Path to the directory to store the compiled functions.
def set_boundary_condition( self, initial_value: list[None | float | sympy.core.expr.Expr], terminal_value: list[None | float | sympy.core.expr.Expr], initial_time: None | float | sympy.core.expr.Expr, terminal_time: None | float | sympy.core.expr.Expr, *, cache: Optional[str] = None) -> Self:

Set the boundary condition and initial/terminal time of the phase.

initial_time, terminal_time, and each element of initial_value and terminal_value can be set as None for free, a floating number for fixed, or sympy.Expr of static parameters.

Arguments:
  • initial_value: List of initial values of states.
  • terminal_value: List of terminal values of states.
  • initial_time: Initial time.
  • terminal_time: Terminal time.
  • cache: Path to the directory to store the compiled functions.
def set_discretization( self, mesh: Union[int, Iterable[float]], num_point: Union[int, Iterable[int]]):

Set the discretization scheme of the system.

mesh will be rescaled when needed. If it is set to an integer, a uniform mesh will be used. If set with an array, it will be used as mesh directly after scaling.

num_point decides the number of interpolation/integration points in each subinterval. Same number of points will be used in all subintervals if set with an integer.

Arguments:
  • mesh: Number of mesh or mesh points.
  • num_point: Number of interpolation and integration points in each subinterval.
def check_continuous( self, variable, static_parameter: Optional[Iterable[float]] = None, absolute_tolerance_continuous: float = 1e-08, relative_tolerance_continuous: float = 1e-08, tolerance_mesh: float = 0.0001) -> bool:

Check the continuous error.

Arguments:
  • variable: Variable to be checked.
  • static_parameter: Static parameter to be checked. Set to None if the phase has no static parameters.
  • absolute_tolerance_continuous: Absolute tolerance for continuous error.
  • relative_tolerance_continuous: Relative tolerance for continuous error.
  • tolerance_mesh: Skip the check if the mesh width is smaller than this value.
Returns:

True if the error is within the tolerance, False otherwise.

def check_discontinuous( self, variable, static_parameter: Optional[Iterable[float]] = None, tolerance_discontinuous: float = 0.001, tolerance_mesh: float = 0.0001) -> bool:

Check the discontinuous error.

Arguments:
  • variable: Variable to be checked.
  • static_parameter: Static parameter to be checked. Set to None if the phase has no static parameters.
  • tolerance_discontinuous: In each subinterval, after scaling to [0, 1], the bang-bang control functions should either be less than tolerance_discontinuous or greater than 1 - tolerance_discontinuous simultaneously.
  • tolerance_mesh: Skip the check if the mesh width is smaller than this value.
Returns:

True if the error is within the tolerance, False otherwise.

def check( self, variable, static_parameter: Optional[Iterable[float]] = None, absolute_tolerance_continuous: float = 1e-08, relative_tolerance_continuous: float = 1e-08, tolerance_discontinuous: float = 0.001, tolerance_mesh: float = 0.0001) -> bool:

Check the continuous and discontinuous error.

Arguments:
  • variable: Variable to be checked.
  • static_parameter: Static parameter to be checked. Set to None if the phase has no static parameters.
  • absolute_tolerance_continuous: Absolute tolerance for continuous error.
  • relative_tolerance_continuous: Relative tolerance for continuous error.
  • tolerance_discontinuous: In each subinterval, after scaling to [0, 1], the bang-bang control functions should either be less than tolerance_discontinuous or greater than 1 - tolerance_discontinuous simultaneously.
  • tolerance_mesh: Skip the check if the mesh width is smaller than this value.
Returns:

True if the error is within the tolerance, False otherwise.

def refine_continuous( self, variable, static_parameter: Optional[Iterable[float]] = None, absolute_tolerance_continuous: float = 1e-08, relative_tolerance_continuous: float = 1e-08, num_point_min: int = 6, num_point_max: int = 12, mesh_length_min: float = 0.001, mesh_length_max: float = 1.0) -> None:

Adjust the mesh and the number of interpolation points to match the continuous error tolerance.

Arguments:
  • variable: Variable of the previous iteration.
  • static_parameter: Static parameter of the previous iteration. Set to None if the phase has no static parameters.
  • absolute_tolerance_continuous: Absolute tolerance for continuous error.
  • relative_tolerance_continuous: Relative tolerance for continuous error.
  • num_point_min: Minimum number of interpolation points.
  • num_point_max: Maximum number of interpolation points.
  • mesh_length_min: Minimum mesh length.
  • mesh_length_max: Maximum mesh length.
def refine_discontinuous( self, variable, static_parameter: Optional[Iterable[float]] = None, tolerance_discontinuous: float = 0.001, num_point_min: int = 6, num_point_max: int = 12, mesh_length_min: float = 0.001, mesh_length_max: float = 1.0) -> None:

Adjust the mesh and the number of interpolation points to match the discontinuous error tolerance.

Arguments:
  • variable: Variable of the previous iteration.
  • static_parameter: Static parameter of the previous iteration. Set to None if the phase has no static parameters.
  • tolerance_discontinuous: In each subinterval, after scaling to [0, 1], the bang-bang control functions should either be less than tolerance_discontinuous or greater than 1 - tolerance_discontinuous simultaneously.
  • num_point_min: Minimum number of interpolation points.
  • num_point_max: Maximum number of interpolation points.
  • mesh_length_min: Minimum mesh length.
  • mesh_length_max: Maximum mesh length.
def refine( self, variable, static_parameter: Optional[Iterable[float]] = None, absolute_tolerance_continuous: float = 1e-08, relative_tolerance_continuous: float = 1e-08, tolerance_discontinuous: float = 0.001, num_point_min: int = 6, num_point_max: int = 12, mesh_length_min: float = 0.001, mesh_length_max: float = 1.0) -> None:

Adjust the mesh and the number of interpolation points to match the error tolerances.

If the discontinuous error is not within the tolerance, refine for discontinuous error. Otherwise, if the continuous error is not within the tolerance, refine for continuous error. At most one of the continuous or discontinuous refinements will be performed.

Arguments:
  • variable: Variable of the previous iteration.
  • static_parameter: Static parameter of the previous iteration. Set to None if the phase has no static parameters.
  • absolute_tolerance_continuous: Absolute tolerance for continuous error.
  • relative_tolerance_continuous: Relative tolerance for continuous error.
  • tolerance_discontinuous: In each subinterval, after scaling to [0, 1], the bang-bang control functions should either be less than tolerance_discontinuous or greater than 1 - tolerance_discontinuous simultaneously.
  • num_point_min: Minimum number of interpolation points.
  • num_point_max: Maximum number of interpolation points.
  • mesh_length_min: Minimum mesh length.
  • mesh_length_max: Maximum mesh length.
n_x: int

Number of state variables.

x: list[sympy.core.symbol.Symbol]

sympy.Symbol s of state variables.

n_u: int

Number of control variables.

u: list[sympy.core.symbol.Symbol]

sympy.Symbol s of control variables.

n: int

Number of state and control variables.

n_s: int

Number of static parameters.

s: list[sympy.core.symbol.Symbol]

sympy.Symbol s of static parameters.

t: sympy.core.symbol.Symbol

The sympy.Symbol representing the time.

n_d: int

Number of dynamics.

n_I: int

Number of integrals.

I: list[sympy.core.symbol.Symbol]

sympy.Symbol s of integrals.

n_c: int

Number of phase constraints.

v_lb: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]]

Lower bounds of optimization variables.

v_ub: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]]

Upper bounds of optimization variables.

c_lb: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]]

Lower bounds of optimization constraints.

c_ub: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]]

Upper bounds of optimization constraints.

s_b: list[tuple[int, float, float]]

Bounds of static parameters.

bc_0: list[None | float | sympy.core.expr.Expr]

Initial boundary conditions.

bc_f: list[None | float | sympy.core.expr.Expr]

Terminal boundary conditions.

pockit.base.fastfunc.FastFunc s of bang-bang constraints.

(scaled to [0, 1].)

n_b: int

Number of bang-bang constraints.

t_0: None | float | sympy.core.expr.Expr

Initial time.

t_f: None | float | sympy.core.expr.Expr

Terminal time.

N: int

Number of subintervals.

ok: bool

Whether the phase is fully configured.

Index partition of the state variables.

Index partition of the control variables.

Index partition of the middle-stage variables.

l_v: numpy.ndarray[typing.Any, numpy.dtype[numpy.int32]]

The left index of the state and control variables.

r_v: numpy.ndarray[typing.Any, numpy.dtype[numpy.int32]]

The right index of the state and control variables (exclusive).

t_m: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]]

Position of all interpolation nodes in the middle stage, scaled to [0, 1].

l_m: numpy.ndarray[typing.Any, numpy.dtype[numpy.int32]]

The left index of subintervals in the middle stage.

r_m: numpy.ndarray[typing.Any, numpy.dtype[numpy.int32]]

The right index of subintervals in the middle stage (exclusive).

L_m: int

The number of interpolation points in the middle stage.

w_m: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]]

The integration weights of the middle stage.

f_v2m: Callable[[numpy.ndarray[Any, numpy.dtype[numpy.float64]]], numpy.ndarray[Any, numpy.dtype[numpy.float64]]]

Function turns the state and control variables into the middle stage.

T_v: scipy.sparse._csr.csr_array

Translation matrix of a state variable to eliminate the integration coefficient.

Translation matrix of a state variable in COO format partitioned by the index.

I_m: scipy.sparse._csr.csr_array

Integration matrix of a middle-stage variable.

Integration matrix of a middle-stage variable in COO format partitioned by the index.

l_d: numpy.ndarray[typing.Any, numpy.dtype[numpy.int32]]

The left index of the dynamic constraints of each state variable.

r_d: numpy.ndarray[typing.Any, numpy.dtype[numpy.int32]]

The right index of the dynamic constraints of each state variable (exclusive).

t_m_aug: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]]

Position of all interpolation nodes in the middle stage, scaled to [0, 1] with one additional interpolation point in each subinterval.

l_m_aug: numpy.ndarray[typing.Any, numpy.dtype[numpy.int32]]

The left index of subintervals in the middle stage, with one additional interpolation point in each subinterval.

r_m_aug: numpy.ndarray[typing.Any, numpy.dtype[numpy.int32]]

The right index of subintervals in the middle stage (exclusive), with one additional interpolation point in each subinterval.

L_m_aug: int

The number of interpolation points in the middle stage, with one additional interpolation point in each subinterval.

w_aug: list[numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]]]

The integration weights of each subinterval in the middle stage, with one additional interpolation point in each subinterval.

P: Callable[[int], numpy.ndarray[Any, numpy.dtype[numpy.float64]]]

Function to compute the polynomial matrix given the number of interpolation points.

V_xu_aug: scipy.sparse._csr.csr_array

The value matrix translates all state and control variables to the middle stage with one additional interpolation point in each subinterval.

T_x_aug: scipy.sparse._csr.csr_array

The translation matrix of all state variables, with one additional interpolation point in each subinterval.

I_m_aug: scipy.sparse._csr.csr_array

The integration matrix of a middle-stage variable, with one additional interpolation point in each subinterval.

t_x: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]]

Position of all interpolation nodes of a state variable, scaled to [0, 1].

t_u: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]]

Position of all interpolation nodes of a control variable, scaled to [0, 1].

l_x: numpy.ndarray[typing.Any, numpy.dtype[numpy.int32]]

The left index of subintervals of a state variable.

r_x: numpy.ndarray[typing.Any, numpy.dtype[numpy.int32]]

The right index of subintervals of a state variable (exclusive).

l_u: numpy.ndarray[typing.Any, numpy.dtype[numpy.int32]]

The left index of subintervals of a control variable.

r_u: numpy.ndarray[typing.Any, numpy.dtype[numpy.int32]]

The right index of subintervals of a control variable (exclusive).

L_x: int

Length of all state variables.

L_xu: int

Length of all state and control variables.

L: int

Length of all state, control, and time variables.