Skip to content

Commit c04594b

Browse files
Merge pull request #38 from ColibrITD-SAS/functional_tests_execution
Functional tests execution in ideal case
2 parents 0879434 + 5f96d02 commit c04594b

File tree

6 files changed

+365
-343
lines changed

6 files changed

+365
-343
lines changed

mpqp/execution/runner.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from __future__ import annotations
22

33
from numbers import Complex
4-
from typing import Optional, Union
4+
from typing import Optional, Sequence, Union
55

66
import numpy as np
77
from sympy import Expr
@@ -20,6 +20,7 @@
2020
from mpqp.execution.providers.ibm import run_ibm, submit_ibmq
2121
from mpqp.execution.result import BatchResult, Result
2222
from mpqp.tools.errors import RemoteExecutionError
23+
from mpqp.tools.generics import OneOrMany
2324

2425

2526
@typechecked
@@ -147,7 +148,7 @@ def _run_single(
147148
@typechecked
148149
def run(
149150
circuit: QCircuit,
150-
device: AvailableDevice | list[AvailableDevice],
151+
device: OneOrMany[AvailableDevice],
151152
values: Optional[dict[Expr | str, Complex]] = None,
152153
) -> Union[Result, BatchResult]:
153154
"""Runs the circuit on the backend, or list of backend, provided in
@@ -198,7 +199,7 @@ def run(
198199
if values is None:
199200
values = {}
200201

201-
if isinstance(device, list):
202+
if isinstance(device, Sequence):
202203
# Duplicate devices are removed
203204
set_device = list(set(device))
204205
if len(set_device) == 1:

mpqp/tools/generics.py

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from typeguard import typechecked
99

1010
T = TypeVar("T")
11+
OneOrMany = Union[T, Sequence[T]]
1112
ListOrSingle = Union[list[T], T]
1213
"""Type alias for both elements of type ``T``, or list of elements of type ``T``."""
1314
ArbitraryNestedSequence = Union[Sequence["ArbitraryNestedSequence"], T]

mpqp/tools/maths.py

+77-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
from __future__ import annotations
22

3+
import math
4+
from functools import reduce
35
from numbers import Complex, Real
46
from typing import TYPE_CHECKING
57

68
import numpy as np
79
import numpy.typing as npt
810
import sympy as sp
11+
from qiskit import quantum_info
12+
from scipy.linalg import inv, sqrtm
913
from sympy import Expr, I, pi # pyright: ignore[reportUnusedImport]
1014
from typeguard import typechecked
1115

@@ -41,7 +45,7 @@ def normalize(v: npt.NDArray[np.complex64]) -> npt.NDArray[np.complex64]:
4145

4246
@typechecked
4347
def matrix_eq(lhs: Matrix, rhs: Matrix) -> bool:
44-
r"""Checks whether two matrix are element-wise equal, within a tolerance.
48+
r"""Checks whether two matrix (including vectors) are element-wise equal, within a tolerance.
4549
4650
For respectively each elements `a` and `b` of both inputs, we check this
4751
specific condition: `|a - b| \leq (atol + rtol * |b|)`.
@@ -182,3 +186,75 @@ def exp(angle: Expr | Complex) -> sp.Expr | complex:
182186
res = sp.exp(angle)
183187
assert isinstance(res, Expr)
184188
return res
189+
190+
191+
def rand_orthogonal_matrix_seed(size: int, seed: int) -> npt.NDArray[np.complex64]:
192+
"""Generate a random orthogonal matrix with a given seed.
193+
194+
Args:
195+
size: Size (number of columns, or rows) of the squared matrix to generate.
196+
seed: Seed used to control the random generation of the matrix.
197+
198+
Returns:
199+
A random orthogonal Matrix.
200+
"""
201+
# TODO: example
202+
np.random.seed(seed)
203+
m = np.random.rand(size, size)
204+
return m.dot(inv(sqrtm(m.T.dot(m))))
205+
206+
207+
def rand_orthogonal_matrix(size: int) -> npt.NDArray[np.complex64]:
208+
"""Generate a random orthogonal matrix without a given seed"""
209+
# TODO: to comment + examples
210+
m = np.random.rand(size, size)
211+
return m.dot(inv(sqrtm(m.T.dot(m))))
212+
213+
214+
def rand_clifford_matrix(nb_qubits: int) -> npt.NDArray[np.complex64]:
215+
"""Generate a random Clifford matrix"""
216+
# TODO: to comment + examples
217+
return quantum_info.random_clifford(
218+
nb_qubits
219+
).to_matrix() # pyright: ignore[reportReturnType]
220+
221+
222+
def rand_unitary_2x2_matrix() -> npt.NDArray[np.complex64]:
223+
"""Generate a random one-qubit unitary matrix"""
224+
# TODO: to comment + examples
225+
theta, phi, gamma = np.random.rand(3) * 2 * math.pi
226+
c, s, eg, ep = (
227+
np.cos(theta / 2),
228+
np.sin(theta / 2),
229+
np.exp(gamma * 1j),
230+
np.exp(phi * 1j),
231+
)
232+
return np.array([[c, -eg * s], [eg * s, eg * ep * c]])
233+
234+
235+
def rand_product_local_unitaries(nb_qubits: int) -> npt.NDArray[np.complex64]:
236+
"""
237+
Generate a random tensor product of unitary matrices
238+
239+
Args:
240+
nb_qubits: Number of qubits on which the product of unitaries will act.
241+
"""
242+
return reduce(
243+
np.kron,
244+
[rand_unitary_2x2_matrix() for _ in range(nb_qubits - 1)],
245+
np.eye(1, dtype=np.complex64),
246+
)
247+
248+
249+
def rand_hermitian_matrix(size: int) -> npt.NDArray[np.complex64]:
250+
"""Generate a random Hermitian matrix.
251+
252+
Args:
253+
size: Size (number of columns, or rows) of the squared matrix to generate.
254+
255+
Returns:
256+
A random orthogonal Matrix.
257+
"""
258+
# TODO: examples
259+
m = np.random.rand(size, size).astype(np.complex64)
260+
return m + m.conjugate().transpose()

pytest.ini

+3-1
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,6 @@ filterwarnings =
1414
ignore:Setting metadata to None.*:DeprecationWarning
1515
ignore:divide by zero.*:RuntimeWarning
1616
ignore:The qiskit.extensions module is pending deprecation.*:PendingDeprecationWarning
17-
ignore:Building a flow controller with keyword arguments is going to be deprecated.*:PendingDeprecationWarning
17+
ignore:Building a flow controller with keyword arguments is going to be deprecated.*:PendingDeprecationWarning
18+
ignore:.*OpenQASM language features that m.*
19+
ignore:.*OpenQASMTranslationWarning.*

0 commit comments

Comments
 (0)