pockit.lobatto

Submodule for Legendre-Gauss-Lobatto pseudo-spectral methods.

The Lobatto phase is suitable for problems with continuous state and control variables.

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

Phase( 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 check_discontinuous( self, variable, static_parameter: Optional[Iterable[float]] = None, tolerance_discontinuous: float = 0.001, tolerance_mesh: float = 0.0001) -> bool:

Lobatto nodes cannot approximate discontinuous functions precisely.

Use radau nodes instead.

Raises:
  • NotImplementedError: Always
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 error. Same as check_continuous().

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_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:

Lobatto nodes cannot approximate discontinuous functions precisely.

Use radau nodes instead.

Raises:
  • NotImplementedError: Always
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 continuous error tolerance. Same as refine_continuous().

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.

A system is the higher level objective of a multiple-phase optimal control problem.

System( static_parameter: int | list[str], simplify: bool = False, parallel: bool = False, fastmath: bool = False)

Initialize a system with given static parameters.

If static_parameter is an integer, the names are generated automatically as \( s_0, s_1, \dots, s_{n-1} \).

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:
  • static_parameter: Number of static parameters or list of static parameter names.
  • 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 check_discontinuous( self, value: Variable | list[typing.Union[Variable, typing.Iterable[float]]], tolerance_discontinuous: float = 0.001, tolerance_mesh: float = 0.0001) -> bool:

Lobatto nodes cannot approximate discontinuous functions precisely.

Use radau nodes instead.

Raises:
  • NotImplementedError: Always
def check( self, value: Variable | list[typing.Union[Variable, typing.Iterable[float]]], 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 error. Same as check_continuous().

Arguments:
  • value: The variable to be checked. If the system has only one phase and no static variables, value can be a single Variable object. Otherwise, value should be a list of Variable objects, one for each Phase, followed by an array as values of static variables.
  • 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_discontinuous( self, value: Variable | list[typing.Union[Variable, typing.Iterable[float]]], 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):

Lobatto nodes cannot approximate discontinuous functions precisely.

Use radau nodes instead.

Raises:
  • NotImplementedError: Always
def refine( self, value: Variable | list[typing.Union[Variable, typing.Iterable[float]]], 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):

Adjust the mesh and the number of interpolation points to match the continuous error tolerance. Same as refine_continuous().

Arguments:
  • value: The variable to be checked. If the system has only one phase and no static variables, value can be a single Variable object. Otherwise, value should be a list of Variable objects, one for each Phase, followed by an array as values of static variables.
  • 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.
Returns:

The Variable s interpolated to the new discretization scheme.

Optimization variable for a discretized phase.

Variable objects provide two kinds of interfaces:

  • Plain 1D array for passing to the solver;
  • Methods for quickly accessing specific variables for users to set and extract corresponding values.

Besides, Variable provides methods to generate interpolation matrices for mesh adaption and plotting.

Generally, users need not create Variable objects directly. A better way is to use the func:constant_guess and func:linear_guess functions to generate a starting point and possibly adjust it manually.

Variable( phase: Phase, data: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]])
Arguments:
  • phase: The Phase object to create the Variable for.
  • data: The underlying data array.
constant_guess = functools.partial(<function constant_guess_base>, <class 'Variable'>)
linear_guess = functools.partial(<function linear_guess_base>, <class 'Variable'>)