Source code for do_dpc.dpc.mpc_oracle
"""
This module implements the MPCOracle class for benchmarking purposes.
The MPCOracle class does not estimate a model using the collected trajectory data.
Instead, it uses the actual system matrices A, B, C, D and the optimal infinite Kalman Gain K.
Hence, it is named "oracle" as it has perfect knowledge of the system.
"""
import numpy as np
from do_dpc.control_utils.control_structs import InputOutputTrajectory
from do_dpc.dpc.dpc import DPC
from do_dpc.dpc.dpc_structs import DPCParameters
from do_dpc.dpc.mpc import MPC, MPCSystemMatrices
[docs]
@DPC.register("MPCOracle")
class MPCOracle(MPC):
"""
MPCOracle class for benchmarking purposes.
This class uses the actual system matrices and the optimal infinite horizon Kalman Gain K.
It does not estimate a model from the collected trajectory data.
Note:
This controller is useful for benchmarking the performance of other data-driven controllers by
providing the ideal scenario where the system matrices and Kalman gain are known.
Attributes:
sys_data (MPCSystemMatrices): Contains the actual system matrices and optimal Kalman Gain K.
n_state (int): The number of states in the system.
dpc_params (DPCParameters): Controller configuration parameters passed from the parent class.
Args:
dpc_params (DPCParameters): Controller configuration parameters.
n_state (int): Number of states in the system.
sys_data (MPCSystemMatrices): Actual system matrices and Kalman Gain.
Raises:
ValueError: If `n_state` does not match the number of states in `sys_data`.
"""
def __init__(
self,
dpc_params: DPCParameters,
n_state: int,
sys_data: MPCSystemMatrices,
):
"""
Initializes the MPCOracle controller.
Args:
n_state (int): Number of states in the system.
sys_data (MPCSystemMatrices): Actual system matrices and Kalman Gain.
Raises:
ValueError: If `n_state` does not match the number of states in `sys_data`.
"""
if n_state != sys_data.sys.A.shape[0]:
raise ValueError(
f"n_state must match the number of states in sys_data, expected: {sys_data.sys.A.shape[0]}"
)
self.sys_data = sys_data
super().__init__(dpc_params, self._create_empty_training_data(100), n_state=n_state)
def calculate_system_data(self) -> MPCSystemMatrices:
"""
Returns the actual system data for the MPCOracle.
Returns:
MPCSystemMatrices: An instance containing the system matrices and Kalman Gain.
"""
return self.sys_data
def _create_empty_training_data(self, num_samples: int) -> InputOutputTrajectory:
"""
Creates an empty training dataset with zeroed input and output arrays.
Parameters:
num_samples (int): The number of samples for the training data.
Must be a positive integer.
Returns:
InputOutputTrajectory: A data structure containing zero-initialized
input (u) and output (y) arrays.
Raises:
ValueError: If num_samples is not a positive integer.
"""
if not isinstance(num_samples, int) or num_samples <= 0:
raise ValueError("num_samples must be a positive integer.")
p, _ = self.sys_data.sys.C.shape
_, m = self.sys_data.sys.B.shape
y = np.zeros((p, num_samples))
u = np.zeros((m, num_samples))
return InputOutputTrajectory(y=y, u=u)