From d226c0ba86436dc539f685126df36f9054f3461f Mon Sep 17 00:00:00 2001 From: kenny-heitritter Date: Tue, 7 Jan 2025 18:56:35 +0000 Subject: [PATCH] refactor + add base class examples as starting point --- qbraid_algorithms/qrc/__init__.py | 8 +-- qbraid_algorithms/qrc/dynamics/base.py | 53 ++++++++++++++ .../qrc/{ => dynamics}/magnus_expansion.py | 0 .../qrc/{ => dynamics}/time_evolution.py | 0 qbraid_algorithms/qrc/encoding/base.py | 56 +++++++++++++++ .../qrc/{ => encoding}/encoding.py | 0 qbraid_algorithms/qrc/model/base.py | 70 +++++++++++++++++++ .../qrc/{ => model}/qrc_model.py | 4 +- 8 files changed, 185 insertions(+), 6 deletions(-) create mode 100644 qbraid_algorithms/qrc/dynamics/base.py rename qbraid_algorithms/qrc/{ => dynamics}/magnus_expansion.py (100%) rename qbraid_algorithms/qrc/{ => dynamics}/time_evolution.py (100%) create mode 100644 qbraid_algorithms/qrc/encoding/base.py rename qbraid_algorithms/qrc/{ => encoding}/encoding.py (100%) create mode 100644 qbraid_algorithms/qrc/model/base.py rename qbraid_algorithms/qrc/{ => model}/qrc_model.py (98%) diff --git a/qbraid_algorithms/qrc/__init__.py b/qbraid_algorithms/qrc/__init__.py index c264380..317c6e9 100644 --- a/qbraid_algorithms/qrc/__init__.py +++ b/qbraid_algorithms/qrc/__init__.py @@ -34,10 +34,10 @@ """ -from .encoding import PCA, one_hot_encoding -from .magnus_expansion import MagnusExpansion -from .qrc_model import DetuningLayer, QRCModel -from .time_evolution import AnalogProgramEvolver +from .encoding.encoding import PCA, one_hot_encoding +from .dynamics.magnus_expansion import MagnusExpansion +from .model.qrc_model import DetuningLayer, QRCModel +from .dynamics.time_evolution import AnalogProgramEvolver __all__ = [ "QRCModel", diff --git a/qbraid_algorithms/qrc/dynamics/base.py b/qbraid_algorithms/qrc/dynamics/base.py new file mode 100644 index 0000000..cc4e7dc --- /dev/null +++ b/qbraid_algorithms/qrc/dynamics/base.py @@ -0,0 +1,53 @@ +"""Base class for quantum dynamics implementations.""" + +from abc import ABC, abstractmethod +from typing import Optional, Union + +import numpy as np + + +class DynamicsBase(ABC): + """Abstract base class for quantum dynamics implementations. + + This class defines the interface that all quantum dynamics classes must implement. + It provides a standard way to evolve quantum states according to different + evolution schemes (Magnus expansion, analog evolution, etc.). + """ + + def __init__(self, num_sites: int, **kwargs): + """Initialize dynamics parameters. + + Args: + num_sites: Number of sites in the quantum system + **kwargs: Additional parameters specific to the dynamics implementation + """ + self.num_sites = num_sites + self._validate_parameters(**kwargs) + + @abstractmethod + def evolve( + self, + initial_state: np.ndarray, + time: Union[float, np.ndarray], + backend: Optional[str] = None + ) -> np.ndarray: + """Evolve the quantum state according to the dynamics. + + Args: + initial_state: Initial quantum state + time: Evolution time(s) + backend: Optional backend specification for computation + + Returns: + Evolved quantum state + """ + pass + + @abstractmethod + def _validate_parameters(self, **kwargs) -> None: + """Validate the parameters passed to the dynamics implementation.""" + pass + + def reset(self) -> None: + """Reset any internal state of the dynamics.""" + pass \ No newline at end of file diff --git a/qbraid_algorithms/qrc/magnus_expansion.py b/qbraid_algorithms/qrc/dynamics/magnus_expansion.py similarity index 100% rename from qbraid_algorithms/qrc/magnus_expansion.py rename to qbraid_algorithms/qrc/dynamics/magnus_expansion.py diff --git a/qbraid_algorithms/qrc/time_evolution.py b/qbraid_algorithms/qrc/dynamics/time_evolution.py similarity index 100% rename from qbraid_algorithms/qrc/time_evolution.py rename to qbraid_algorithms/qrc/dynamics/time_evolution.py diff --git a/qbraid_algorithms/qrc/encoding/base.py b/qbraid_algorithms/qrc/encoding/base.py new file mode 100644 index 0000000..33d492f --- /dev/null +++ b/qbraid_algorithms/qrc/encoding/base.py @@ -0,0 +1,56 @@ +"""Base class for encoding classical data into quantum states.""" + +from abc import ABC, abstractmethod +from typing import Optional + +import numpy as np + + +class EncoderBase(ABC): + """Abstract base class for encoding classical data into quantum states. + + This class defines the interface for transforming classical data into a format + suitable for quantum evolution, with methods for both encoding and decoding. + """ + + def __init__(self, input_dim: int, output_dim: int, **kwargs): + """Initialize encoder parameters. + + Args: + input_dim: Dimension of input classical data + output_dim: Dimension of encoded quantum data + **kwargs: Additional parameters specific to the encoding method + """ + self.input_dim = input_dim + self.output_dim = output_dim + self._validate_dimensions() + + @abstractmethod + def encode(self, data: np.ndarray, normalize: bool = True) -> np.ndarray: + """Transform classical data into quantum encoding. + + Args: + data: Classical data to encode + normalize: Whether to normalize the encoded data + + Returns: + Encoded quantum data + """ + pass + + @abstractmethod + def decode(self, encoded_data: np.ndarray) -> np.ndarray: + """Transform encoded quantum data back to classical form. + + Args: + encoded_data: Encoded quantum data + + Returns: + Decoded classical data + """ + pass + + def _validate_dimensions(self) -> None: + """Validate input and output dimensions.""" + if self.input_dim <= 0 or self.output_dim <= 0: + raise ValueError("Dimensions must be positive integers") \ No newline at end of file diff --git a/qbraid_algorithms/qrc/encoding.py b/qbraid_algorithms/qrc/encoding/encoding.py similarity index 100% rename from qbraid_algorithms/qrc/encoding.py rename to qbraid_algorithms/qrc/encoding/encoding.py diff --git a/qbraid_algorithms/qrc/model/base.py b/qbraid_algorithms/qrc/model/base.py new file mode 100644 index 0000000..9a4f2f8 --- /dev/null +++ b/qbraid_algorithms/qrc/model/base.py @@ -0,0 +1,70 @@ +"""Base class for quantum reservoir computing models.""" + +from abc import ABC, abstractmethod +from typing import Optional, Tuple + +import numpy as np + +from ..dynamics.base import DynamicsBase +from ..encoding.base import EncoderBase + + +class QRCModelBase(ABC): + """Abstract base class for quantum reservoir computing models. + + This class combines encoding and dynamics components to create a complete + quantum reservoir computing model. + """ + + def __init__( + self, + encoder: EncoderBase, + dynamics: DynamicsBase, + random_state: Optional[int] = None + ): + """Initialize the QRC model. + + Args: + encoder: Encoder for transforming classical data + dynamics: Quantum dynamics implementation + random_state: Random seed for reproducibility + """ + self.encoder = encoder + self.dynamics = dynamics + self._set_random_state(random_state) + + @abstractmethod + def fit( + self, + X: np.ndarray, + y: np.ndarray, + **kwargs + ) -> "QRCModelBase": + """Train the model on given data. + + Args: + X: Training input data + y: Training target values + **kwargs: Additional training parameters + + Returns: + self: The trained model + """ + pass + + @abstractmethod + def predict(self, X: np.ndarray) -> np.ndarray: + """Make predictions using the trained model. + + Args: + X: Input data for prediction + + Returns: + Model predictions + """ + pass + + def _set_random_state(self, random_state: Optional[int]) -> None: + """Set random state for reproducibility.""" + if random_state is not None: + np.random.seed(random_state) \ No newline at end of file diff --git a/qbraid_algorithms/qrc/qrc_model.py b/qbraid_algorithms/qrc/model/qrc_model.py similarity index 98% rename from qbraid_algorithms/qrc/qrc_model.py rename to qbraid_algorithms/qrc/model/qrc_model.py index 9733113..5ae24b3 100644 --- a/qbraid_algorithms/qrc/qrc_model.py +++ b/qbraid_algorithms/qrc/model/qrc_model.py @@ -22,8 +22,8 @@ from bloqade.emulate.ir.state_vector import StateVector from bloqade.ir.location import Chain -from .encoding import PCA -from .time_evolution import AnalogProgramEvolver +from ..encoding.encoding import PCA +from ..dynamics.time_evolution import AnalogProgramEvolver @dataclass