csnlp.wrappers.PwaMpc#

class csnlp.wrappers.PwaMpc(*args, **kwargs)[source]#

Bases: Mpc[SymType]

MPC controller for piecewise affine (PWA) systems. A PWA system is characterized by linear dynamics that switch between different regions of the state-action space. In mathematical terms, given a PWA system with \(s\) regions, the dynamics are

\[\begin{split}x_+ = \begin{cases} A_1 x + B_1 u + c_1 & \text{if } S_1 x + R_1 u \leq T_1 \\ & \vdots \\ A_i x + B_i u + c_i & \text{if } S_i x + R_i u \leq T_i \\ & \vdots \\ A_s x + B_s u + c_s & \text{if } S_s x + R_s u \leq T_s \end{cases}\end{split}\]

This MPC controller class can then handle two different types of specifications for the dynamics.

  • affine time-varying dynamics: the MPC controller can be considered as a linear MPC controller with time-varying dynamics, in which case the dynamics must be defined via the set_affine_time_varying_dynamics method. Then, prior to solving the optimization problem, the sequence of regions to be active at each time-step needs to be set via set_switching_sequence by the user/externally.

  • optimzing also the sequence: alternatively, the sequence of PWA regions can be optimized over, in which case the dynamics must be defined via the set_pwa_dynamics method. Following [2], the PWA dynamics are converted to mixed-logical dynamical form, and the ensuing MPC optimization becomes a mixed-integer optimization problem. This is done under the hood via the set_pwa_dynamics method. See also [3] for further details.

Parameters:
nlpNlp

NLP scheme to be wrapped

prediction_horizonint

A positive integer for the prediction horizon of the MPC controller.

control_horizonint, optional

A positive integer for the control horizon of the MPC controller. If not given, it is set equal to the control horizon.

input_spacingint, optional

Spacing between independent input actions. This argument allows to reduce the number of free actions along the control horizon by allowing only the first action every n to be free, and the following n-1 to be fixed equal to that action (where n is given by input_spacing). By default, no spacing is allowed, i.e., 1.

shooting‘single’ or ‘multi’, optional

Type of approach in the direct shooting for parametrizing the control trajectory. See Section 8.5 in [6]. By default, direct shooting is used.

Raises:
ValueError

Raises if the shooting method is invalid; or if any of the horizons are invalid; or if the number of scenarios is not a positive integer.

Methods

action(name[, size, discrete, lb, ub])

Adds a control action variable to the MPC controller along the whole control horizon.

constraint(name, lhs, op, rhs[, soft, simplify])

See csnlp.Nlp.constraint.

disturbance(name[, size])

Adds a disturbance parameter to the MPC controller along the whole prediction horizon.

get_optimal_switching_sequence(sol)

Returns the optimal switching sequence of regions for the state trajectory along the prediction horizon, which can be extracted from the solution of the corresponding mixed-integer optimization MPC problem (i.e., when the dynamics are set via set_pwa_dynamics, which allows to optimize over the sequence as well, though more computationally expensive).

is_wrapped(wrapper_type)

Gets whether the NLP instance is wrapped or not by the given wrapper type.

set_affine_dynamics(A, B[, D, c, ...])

Sets affine dynamics as the controller's prediction model and creates the corresponding dynamics constraints.

set_affine_time_varying_dynamics(pwa_system)

Sets affine time-varying dynamics as the controller's prediction model and creates the corresponding dynamics constraints.

set_nonlinear_dynamics(F[, parallelization, ...])

Sets the nonlinear dynamics of the controller's prediction model and creates the corresponding dynamics constraints.

set_pwa_dynamics(pwa_system, D, E[, ...])

Sets the piecewise affine dynamics of the system for the MPC controller, creating auxiliary variables and constraints to handle the PWA switching.

set_switching_sequence(sequence)

Sets the sequence of regions to be active at each time step along the MPC prediction horizon.

solve([pars, vals0])

state(name[, size, discrete, lb, ub, ...])

Adds a state variable to the MPC controller along the whole prediction horizon.

validate_pwa_dimensions(pwa_system)

Validates that the dimensions are correct for all matrices in the passed PWA system.

Attributes

actions

Gets the control actions of the MPC controller.

actions_expanded

Gets the expanded control actions of the MPC controller.

control_horizon

Gets the control horizon of the MPC controller.

disturbances

Gets the disturbance parameters of the MPC controller.

first_actions

Gets the first (along the prediction horizon) actions of the controller.

first_states

Gets the first (along the prediction horizon) states of the controller.

initial_states

Gets the initial states (parameters) of the MPC controller.

na

Gets the number of actions of the MPC controller.

nd

Gets the number of disturbances in the MPC controller.

ns

Gets the number of states of the MPC controller.

nslacks

Gets the number of slacks of the MPC controller.

prediction_horizon

Gets the prediction horizon of the MPC controller.

slacks

Gets the slack variables of the MPC controller.

states

Gets the states of the MPC controller.

tva_dynamics_name

unwrapped

'Returns the original NLP of the wrapper.

action(name, size=1, discrete=False, lb=-inf, ub=inf)#

Adds a control action variable to the MPC controller along the whole control horizon. Automatically expands this action to be of the same length of the prediction horizon by padding with the final action.

Parameters:
namestr

Name of the control action.

sizeint, optional

Size of the control action (assumed to be a vector). Defaults to 1.

discretebool, optional

Flag indicating if the action is discrete. Defaults to False.

lbarray_like, casadi.DM, optional

Hard lower bound of the control action, by default -np.inf.

ubarray_like, casadi.DM, optional

Hard upper bound of the control action, by default +np.inf.

Returns:
actioncasadi.SX or MX

The control action symbolic variable.

action_expandedcasadi.SX or MX

The same control action variable, but expanded to the same length of the prediction horizon.

Return type:

tuple[TypeVar(SymType, SX, MX), TypeVar(SymType, SX, MX)]

property actions: dict[str, SymType]#

Gets the control actions of the MPC controller.

property actions_expanded: dict[str, SymType]#

Gets the expanded control actions of the MPC controller.

constraint(name, lhs, op, rhs, soft=False, simplify=True)#

See csnlp.Nlp.constraint.

Return type:

tuple[TypeVar(SymType, SX, MX), ...]

property control_horizon: int#

Gets the control horizon of the MPC controller.

disturbance(name, size=1)#

Adds a disturbance parameter to the MPC controller along the whole prediction horizon.

Parameters:
namestr

Name of the disturbance.

sizeint, optional

Size of the disturbance (assumed to be a vector). Defaults to 1.

Returns:
casadi.SX or MX

The symbol for the new disturbance in the MPC controller.

Return type:

TypeVar(SymType, SX, MX)

property disturbances: dict[str, SymType]#

Gets the disturbance parameters of the MPC controller.

property first_actions: dict[str, SymType]#

Gets the first (along the prediction horizon) actions of the controller.

property first_states: dict[str, SymType]#

Gets the first (along the prediction horizon) states of the controller.

static get_optimal_switching_sequence(sol)[source]#

Returns the optimal switching sequence of regions for the state trajectory along the prediction horizon, which can be extracted from the solution of the corresponding mixed-integer optimization MPC problem (i.e., when the dynamics are set via set_pwa_dynamics, which allows to optimize over the sequence as well, though more computationally expensive).

Parameters:
solSolution

An optimal solution of the mixed-integer PWA MPC problem.

Returns:
array of ints

An array of integers representing the indices of the regions that active at each time step along the prediction horizon, i.e., the k-th entry of this array represents the index of the region the predicted state is in at time step k.

Raises:
KeyError

Raises if the solution does not contain the variable delta, e.g., the solution was not obtained from a mixed-integer optimization problem, or the dynamics were not set via set_pwa_dynamics.

Return type:

ndarray[tuple[Any, ...], dtype[integer]]

property initial_states: dict[str, SymType]#

Gets the initial states (parameters) of the MPC controller.

is_wrapped(wrapper_type)#

Gets whether the NLP instance is wrapped or not by the given wrapper type.

Parameters:
wrapper_typetype of Wrapper

Type of wrapper to check if the NLP is wrapped with.

Returns:
bool

True if wrapped by an instance of wrapper_type; False, otherwise.

Return type:

bool

property na: int#

Gets the number of actions of the MPC controller.

property nd: int#

Gets the number of disturbances in the MPC controller.

property ns: int#

Gets the number of states of the MPC controller.

property nslacks: int#

Gets the number of slacks of the MPC controller.

property prediction_horizon: int#

Gets the prediction horizon of the MPC controller.

set_affine_dynamics(A, B, D=None, c=None, parallelization='thread', max_num_threads=None)#

Sets affine dynamics as the controller’s prediction model and creates the corresponding dynamics constraints. The dynamics are in the affine form

\[x_+ = A x + B u + D w + c,\]

where \(x_+\) is the next state, \(x\) is the current state, \(u\) is the control action, \(w\) is the disturbance, and \(c\) is a constant term.

Parameters:
Asymbolic or numerical array

The state matrix \(A\) in the dynamics equation. Can also be sparse.

Bsymbolic or numerical array

The action matrix \(B\) in the dynamics equation. Can also be sparse.

Dsymbolic or numerical array, optional

The disturbance matrix \(D\) in the dynamics equation. Must be None if no disturbances were provided via the disturbance method. Can also be sparse.

csymbolic or numerical array, optional

The constant term \(c\) in the dynamics equation. By default, None. If not provided, the dynamics become linear instead of affine.

parallelization“serial”, “unroll”, “inline”, “thread”, “openmp”

The type of parallelization to use (see casadi.Function.map) when applying the dynamics along the horizon in multiple shooting. By default, "thread" is selected.

max_num_threadsint, optional

Maximum number of threads to use in parallelization (if in multiple shooting). See casadi.Function.map for more information. By default, set equal to the prediction horizon.

Returns:
Optional 4-tuple of symbolic or numerical arrays

In multiple shooting, returns a tuple of None. In single shooting, returns the matrices \(F, G, H, L\) that parametrize the dynamics. See, e.g., [5].

Raises:
RuntimeError

Raises if the dynamics were already set.

ValueError

Raises if any of the matrices have the wrong shape; or if D was not provided but disturbances were set; or if D was provided but there are no disturbances set.

Return type:

tuple[Optional[TypeVar(MatType, TypeVar(SymType, SX, MX), DM, ndarray)], Optional[TypeVar(MatType, TypeVar(SymType, SX, MX), DM, ndarray)], Optional[TypeVar(MatType, TypeVar(SymType, SX, MX), DM, ndarray)], Optional[TypeVar(MatType, TypeVar(SymType, SX, MX), DM, ndarray)]]

set_affine_time_varying_dynamics(pwa_system)[source]#

Sets affine time-varying dynamics as the controller’s prediction model and creates the corresponding dynamics constraints. The dynamics in the affine time-varying form are described as

\[x_{k+1} = A_k x_k + B_k u_k + c_k.\]

where \(x_k\) and \(x_{k+1}\) are the current and next state, \(u_k\) is the control action, \(w_k\) is the disturbance, and \(A_k, B_k, c_k\) are the constant matrices of the region to be visited by the state trajectory at time step k. By setting the dynamics with this method, the user can then specify the switching sequence of regions to be active at each time step along the prediction horizon via set_switching_sequence, and solve a much simpler optimization problem, as the sequence is fixed. Instead, if set_pwa_dynamics is used, the sequence of regions is optimized over via a (usually expensive) mixed-integer optimization problem.

Parameters:
pwa_systemsequence of PwaRegion

A sequence of PwaRegion objects, where the i-th object contains the matrices defining the i-th region of the PWA system.

Returns:
Optional 3-tuple of symbolic or numerical arrays

In multiple shooting, returns a tuple of None. In single shooting, returns the matrices \(F, G, L\) that parametrize the dynamics. See, e.g., [5].

Raises:
RuntimeError

Raises if the dynamics were already set.

ValueError

Raises if the dimensions of any matrix in any region do not match the expected shape.

Return type:

tuple[Optional[TypeVar(SymType, SX, MX)], Optional[TypeVar(SymType, SX, MX)], Optional[TypeVar(SymType, SX, MX)]]

set_nonlinear_dynamics(F, parallelization='thread', max_num_threads_or_unrolling_base=None)#

Sets the nonlinear dynamics of the controller’s prediction model and creates the corresponding dynamics constraints.

Parameters:
Fcasadi.Function or callable

A CasADi function of the form \(x_+ = F(x,u)\) or \(x+ = F(x,u,d)\), where \(x,u,d\) are the state, action, and disturbance respectively, \(F\) is a generic nonlinear function and \(x_+\) is the next state.

parallelization“serial”, “unroll”, “inline”, “thread”, “openmp”

The type of parallelization to use (see casadi.Function.map) when applying the dynamics along the horizon in multiple shooting. By default, "thread" is selected.

max_num_threads_or_unrolling_baseint, optional

Maximum number of threads to use in parallelization (if in multiple shooting), or the base for unrolling (if in single shooting). See casadi.Function.map and casadi.Function.mapaccum for more information, respectively. By default, set equal to the prediction horizon.

Raises:
ValueError

Raises if the dynamics do not accept 2 or 3 input arguments.

RuntimeError

Raises if the dynamics have been already set; or if the function F does not accept the expected input sizes.

Return type:

None

set_pwa_dynamics(pwa_system, D, E, clp_opts=None, parallelization='thread', max_num_threads=None)[source]#

Sets the piecewise affine dynamics of the system for the MPC controller, creating auxiliary variables and constraints to handle the PWA switching. In order to perform the conversion of the PWA dynamics to mixed-logical dynamical form, the method solves a series of linear programmes via the CLP solver. Parallelization can also be enabled to speed up the process.

Parameters:
pwa_systemcollection of PwaRegion

A collection of PwaRegion objects, where the i-th object contains the matrices defining the i-th region of the PWA system.

Darray or casadi.DM of shape (n_ineq, ns + na)

The (possibly sparse) matrix D defining the polytopic constraints on the state-action space \(D [x^\top, u^\top]^\top \leq E\), where ns and na are the numbers of states and actions in the MPC problem, respectively.

Earray of shape (n_ineq,)

The matrix E defining the polytopic constraints on the state-action space \(D [x^\top, u^\top]^\top \leq E\).

clp_optsdict, optional

Options for the CLP solver. Defaults to None.

parallelization“serial”, “unroll”, “inline”, “thread”, “openmp”

The type of parallelization to use (see casadi.Function.map) when solving the linear programmes. By default, "thread" is selected.

max_num_threadsint, optional

Maximum number of threads to use in parallelization; if None, the number of threads is equal to the number of regions in the system.

Raises:
RuntimeError

Raises if the dynamics were already set, or if lower and upper bounds on the states and/or actions are set.

ValueError

Raises if the dimensions of any matrix in any region do not match the expected shape.

Return type:

None

Notes

When multiple states and/or control inputs are defined, these are concatenated into the single vectors \(x\) and \(u\), respectively. Also, this function will raise an error if lower and upper bounds on any state or action are set. This is because these bounds should be instead specified via the matrices D and E. Moreover, this function only uses these matrices for internal computations, so the user should take care to impose the constraints \(D [x^\top, u^\top]^\top \leq E\) in the optimization problem, as well as any other, via the constraint method.

set_switching_sequence(sequence)[source]#

Sets the sequence of regions to be active at each time step along the MPC prediction horizon. Then, when solved, the MPC optimization will only optimze over the action and state trajectories, while enforcing the sequence of regions visited by the states to be the one provided here.

Parameters:
sequencecollection of int

A collection of integers representing the indices of the regions to be active at each time step along the prediction horizon, i.e., the k-th entry of this collection represents the index of the region the state must be at time step k.

Raises:
ValueError

Raises if dynamics have not been set via set_affine_time_varying_dynamics; if the sequence is not the same length as the prediction horizon; if the sequence does not contain integers; if the sequence contains integers that exceed the number of PWA regions specified via set_affine_time_varying_dynamics.

Return type:

None

Notes

For internal validation purposes, please call first set_affine_time_varying_dynamics and only then call this method.

property slacks: dict[str, SymType]#

Gets the slack variables of the MPC controller.

solve(pars=None, vals0=None)[source]#
Return type:

Solution[TypeVar(SymType, SX, MX)]

state(name, size=1, discrete=False, lb=-inf, ub=inf, bound_initial=True, bound_terminal=True)#

Adds a state variable to the MPC controller along the whole prediction horizon. Automatically creates the constraint on the initial conditions for this state.

Parameters:
namestr

Name of the state.

sizeint

Size of the state (assumed to be a vector).

discretebool, optional

Flag indicating if the state is discrete. Defaults to False.

lbarray_like, casadi.DM, optional

Hard lower bound of the state, by default -np.inf.

ubarray_like, casadi.DM, optional

Hard upper bound of the state, by default +np.inf.

bound_initialbool, optional

If False, then the upper and lower bounds on the initial state are not imposed, i.e., set to +/- np.inf (since the initial state is constrained to be equal to the current state of the system, it is sometimes advantageous to remove its bounds). By default True.

bound_terminalbool, optional

Same as above, but for the terminal state. By default True.

Returns:
statecasadi.SX or MX or None

The state symbolic variable. If shooting=single, then None is returned since the state will only be available once the dynamics are set.

initial statecasadi.SX or MX

The initial state symbolic parameter.

Raises:
ValueError

Raises if there exists already a state with the same name.

RuntimeError

Raises in single shooting if lower or upper bounds have been specified, since these can only be set after the dynamics have been set via the constraint method.

Return type:

tuple[Optional[TypeVar(SymType, SX, MX)], TypeVar(SymType, SX, MX)]

property states: dict[str, SymType]#

Gets the states of the MPC controller.

tva_dynamics_name = 'tva_dyn'#
property unwrapped: Nlp[SymType]#

‘Returns the original NLP of the wrapper.

validate_pwa_dimensions(pwa_system)[source]#

Validates that the dimensions are correct for all matrices in the passed PWA system.

Parameters:
pwa_systemiterable of PwaRegion

An iterable of PwaRegion objects, where the i-th object contains the matrices defining the i-th region of the PWA system.

Raises:
ValueError

Raises if the dimensions of any matrix in any region do not match the expected shape.

Return type:

None

Examples using csnlp.wrappers.PwaMpc#

MPC controller for PWA systems

MPC controller for PWA systems