-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #20 from qiboteam/model
Implements the structure of a general `qiboml` model
- Loading branch information
Showing
21 changed files
with
1,528 additions
and
363 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# A single CI script with github workflow | ||
name: Build wheels and deploy | ||
|
||
on: | ||
workflow_dispatch: | ||
push: | ||
merge_group: | ||
release: | ||
types: | ||
- published | ||
|
||
jobs: | ||
build: | ||
strategy: | ||
matrix: | ||
os: [ubuntu-latest, macos-latest, windows-latest] | ||
python-version: [ 3.9, '3.10', '3.11', '3.12'] | ||
uses: qiboteam/workflows/.github/workflows/deploy-pip-poetry.yml@v1 | ||
with: | ||
os: ${{ matrix.os }} | ||
python-version: ${{ matrix.python-version }} | ||
publish: ${{ github.event_name == 'release' && github.event.action == 'published' && matrix.os == 'ubuntu-latest' && matrix.python-version == '3.10' }} | ||
poetry-extras: "--with tests" | ||
secrets: inherit |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,28 @@ | ||
import importlib.metadata as im | ||
from typing import Union | ||
|
||
import numpy.typing as npt | ||
|
||
from qiboml.backends.__init__ import MetaBackend | ||
|
||
__version__ = im.version(__package__) | ||
|
||
ndarray = npt.NDArray | ||
|
||
try: | ||
from tensorflow import Tensor as tf_tensor | ||
|
||
from qiboml.models import keras | ||
|
||
ndarray = Union[ndarray, tf_tensor] | ||
except ImportError: # pragma: no cover | ||
pass | ||
|
||
try: | ||
from torch import Tensor as pt_tensor | ||
|
||
from qiboml.models import pytorch | ||
|
||
ndarray = Union[ndarray, pt_tensor] | ||
except ImportError: # pragma: no cover | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,18 @@ | ||
import random | ||
|
||
import numpy as np | ||
from qibo import Circuit, gates | ||
|
||
|
||
def reuploading_circuit(nqubits, nlayers): | ||
c = Circuit(nqubits) | ||
for _ in range(nlayers): | ||
for q in range(nqubits): | ||
c.add(gates.RY(q, 0)) | ||
c.add(gates.RZ(q, 0)) | ||
for q in range(0, nqubits - 1, 1): | ||
c.add(gates.CNOT(q0=q, q1=q + 1)) | ||
c.add(gates.CNOT(q0=nqubits - 1, q1=0)) | ||
c.add(gates.M(*range(nqubits))) | ||
return c | ||
def ReuploadingCircuit(nqubits: int, qubits: list[int] = None) -> Circuit: | ||
if qubits is None: | ||
qubits = list(range(nqubits)) | ||
|
||
circuit = Circuit(nqubits) | ||
for q in qubits: | ||
circuit.add(gates.RY(q, theta=random.random() * np.pi, trainable=True)) | ||
circuit.add(gates.RZ(q, theta=random.random() * np.pi, trainable=True)) | ||
for i, q in enumerate(qubits[:-2]): | ||
circuit.add(gates.CNOT(q0=q, q1=qubits[i + 1])) | ||
circuit.add(gates.CNOT(q0=qubits[-1], q1=qubits[0])) | ||
return circuit |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
from dataclasses import dataclass | ||
from typing import Union | ||
|
||
from qibo import Circuit, gates | ||
from qibo.backends import Backend, _check_backend | ||
from qibo.config import raise_error | ||
from qibo.hamiltonians import Hamiltonian | ||
|
||
from qiboml import ndarray | ||
|
||
|
||
@dataclass | ||
class QuantumDecoding: | ||
|
||
nqubits: int | ||
qubits: list[int] = None | ||
nshots: int = 1000 | ||
analytic: bool = True | ||
backend: Backend = None | ||
_circuit: Circuit = None | ||
|
||
def __post_init__(self): | ||
if self.qubits is None: | ||
self.qubits = list(range(self.nqubits)) | ||
self._circuit = Circuit(self.nqubits) | ||
self.backend = _check_backend(self.backend) | ||
self._circuit.add(gates.M(*self.qubits)) | ||
|
||
def __call__(self, x: Circuit) -> "CircuitResult": | ||
return self.backend.execute_circuit(x + self._circuit, nshots=self.nshots) | ||
|
||
@property | ||
def circuit( | ||
self, | ||
): | ||
return self._circuit | ||
|
||
def set_backend(self, backend): | ||
self.backend = backend | ||
|
||
@property | ||
def output_shape(self): | ||
raise_error(NotImplementedError) | ||
|
||
|
||
@dataclass | ||
class Probabilities(QuantumDecoding): | ||
|
||
def __call__(self, x: Circuit) -> ndarray: | ||
return super().__call__(x).probabilities() | ||
|
||
@property | ||
def output_shape(self): | ||
return (1, 2**self.nqubits) | ||
|
||
|
||
@dataclass | ||
class Expectation(QuantumDecoding): | ||
|
||
observable: Union[ndarray, Hamiltonian] = None | ||
analytic: bool = False | ||
|
||
def __post_init__(self): | ||
if self.observable is None: | ||
raise_error( | ||
RuntimeError, | ||
"Please provide an observable for expectation value calculation.", | ||
) | ||
super().__post_init__() | ||
|
||
def __call__(self, x: Circuit) -> ndarray: | ||
if self.analytic: | ||
return self.observable.expectation( | ||
super().__call__(x).state(), | ||
).reshape(1, 1) | ||
else: | ||
return self.observable.expectation_from_samples( | ||
super().__call__(x).frequencies(), | ||
qubit_map=self.qubits, | ||
).reshape(1, 1) | ||
|
||
@property | ||
def output_shape(self): | ||
return (1, 1) | ||
|
||
def set_backend(self, backend): | ||
super().set_backend(backend) | ||
self.observable.backend = backend | ||
|
||
|
||
@dataclass | ||
class State(QuantumDecoding): | ||
|
||
def __call__(self, x: Circuit) -> ndarray: | ||
state = super().__call__(x).state() | ||
return self.backend.np.vstack( | ||
(self.backend.np.real(state), self.backend.np.imag(state)) | ||
).reshape(self.output_shape) | ||
|
||
@property | ||
def output_shape(self): | ||
return (2, 1, 2**self.nqubits) | ||
|
||
|
||
@dataclass | ||
class Samples(QuantumDecoding): | ||
|
||
def __post_init__(self): | ||
super().__post_init__() | ||
self.analytic = False | ||
|
||
def forward(self, x: Circuit) -> ndarray: | ||
return self.backend.cast(super().__call__(x).samples(), self.backend.precision) | ||
|
||
@property | ||
def output_shape(self): | ||
return (self.nshots, len(self.qubits)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
from abc import ABC, abstractmethod | ||
from dataclasses import dataclass | ||
|
||
import numpy as np | ||
from qibo import Circuit, gates | ||
from qibo.config import raise_error | ||
|
||
from qiboml import ndarray | ||
|
||
|
||
@dataclass | ||
class QuantumEncoding(ABC): | ||
|
||
nqubits: int | ||
qubits: list[int] = None | ||
_circuit: Circuit = None | ||
|
||
def __post_init__( | ||
self, | ||
): | ||
if self.qubits is None: | ||
self.qubits = list(range(self.nqubits)) | ||
self._circuit = Circuit(self.nqubits) | ||
|
||
@abstractmethod | ||
def __call__(self, x: ndarray) -> Circuit: | ||
pass | ||
|
||
@property | ||
def circuit( | ||
self, | ||
): | ||
return self._circuit | ||
|
||
|
||
@dataclass | ||
class PhaseEncoding(QuantumEncoding): | ||
|
||
def __post_init__( | ||
self, | ||
): | ||
super().__post_init__() | ||
for q in self.qubits: | ||
self._circuit.add(gates.RY(q, theta=0.0, trainable=False)) | ||
|
||
def _set_phases(self, x: ndarray): | ||
for gate, phase in zip(self._circuit.parametrized_gates, x.ravel()): | ||
gate.parameters = phase | ||
|
||
def __call__(self, x: ndarray) -> Circuit: | ||
self._set_phases(x) | ||
return self._circuit | ||
|
||
|
||
@dataclass | ||
class BinaryEncoding(QuantumEncoding): | ||
|
||
def __call__(self, x: ndarray) -> Circuit: | ||
if x.shape[-1] != len(self.qubits): | ||
raise_error( | ||
RuntimeError, | ||
f"Invalid input dimension {x.shape[-1]}, but the allocated qubits are {self.qubits}.", | ||
) | ||
circuit = self.circuit.copy() | ||
ones = np.flatnonzero(x.ravel() == 1) | ||
for bit in ones: | ||
circuit.add(gates.X(self.qubits[bit])) | ||
return circuit |
Oops, something went wrong.