Skip to content

Commit 1fca9e6

Browse files
Merge pull request #106 from ColibrITD-SAS/chore-features-for-all-providers
test: validity for gate, job_type, measure, noise, pauli_string and other_instructions
2 parents da0d6fa + 7c5db8c commit 1fca9e6

22 files changed

+617
-66
lines changed

mpqp/all.py

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
H,
4141
Id,
4242
P,
43+
CP,
4344
ParametrizedGate,
4445
Rk,
4546
Rk_dagger,

mpqp/core/circuit.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -956,7 +956,7 @@ def to_other_language(
956956
new_circ.name = self.label
957957

958958
for instruction in self.instructions:
959-
if isinstance(instruction, Measure):
959+
if isinstance(instruction, (Measure, Breakpoint)):
960960
continue
961961
qiskit_inst = instruction.to_other_language(language, qiskit_parameters)
962962
if TYPE_CHECKING:
@@ -983,8 +983,6 @@ def to_other_language(
983983
qargs = instruction.targets
984984
elif isinstance(instruction, Barrier):
985985
qargs = range(self.nb_qubits)
986-
elif isinstance(instruction, Breakpoint):
987-
continue
988986
else:
989987
raise ValueError(f"Instruction not handled: {instruction}")
990988

mpqp/core/instruction/barrier.py

+2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ def to_other_language(
3434
elif language == Language.QASM2:
3535
qubits = ",".join([f"q[{j}]" for j in self.targets])
3636
return "barrier " + qubits + ";"
37+
else:
38+
raise NotImplementedError(f"{language} is not supported")
3739

3840
def __repr__(self):
3941
return f"{type(self).__name__}({self.size})"

mpqp/core/instruction/breakpoint.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
from __future__ import annotations
2-
from typing import Optional
3-
4-
from qiskit.circuit import Parameter
2+
from typing import TYPE_CHECKING, Optional
53

64
from mpqp.core.instruction import Instruction
75
from mpqp.core.languages import Language
86

7+
if TYPE_CHECKING:
8+
from qiskit.circuit import Parameter
9+
910

1011
class Breakpoint(Instruction):
1112
"""A breakpoint is a special instruction that will display the state of the

mpqp/core/instruction/gates/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
H,
1414
Id,
1515
P,
16+
CP,
1617
Rk,
1718
Rk_dagger,
1819
Rx,

mpqp/core/instruction/gates/gate.py

+1
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ def to_canonical_matrix(self) -> Matrix:
144144
[0, 0, 0, 1]]
145145
146146
"""
147+
pass
147148

148149
def inverse(self) -> Gate:
149150
"""Computing the inverse of this gate.

mpqp/core/instruction/gates/native_gates.py

+89-4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
from __future__ import annotations
1515

16+
import inspect
17+
import sys
1618
from abc import abstractmethod
1719
from numbers import Integral
1820
from typing import TYPE_CHECKING, Optional
@@ -406,6 +408,8 @@ def to_other_language(
406408
if self.label:
407409
return self.qiskit_gate(label=self.label)
408410
return self.qiskit_gate()
411+
elif language == Language.BRAKET:
412+
return self.braket_gate()
409413
elif language == Language.QASM2:
410414

411415
instruction_str = self.qasm2_gate
@@ -594,6 +598,63 @@ def to_canonical_matrix(self) -> Matrix:
594598
)
595599

596600

601+
class CP(RotationGate, ControlledGate):
602+
"""Two-qubit Controlled-P gate.
603+
604+
Args:
605+
theta: Parameter representing the phase to apply.
606+
control: Index referring to the qubit used to control the gate.
607+
target: Index referring to the qubit on which the gate will be applied.
608+
609+
Example:
610+
>>> pprint(CP(0.5, 0, 1).to_matrix())
611+
[[1, 0, 0, 0 ],
612+
[0, 1, 0, 0 ],
613+
[0, 0, 1, 0 ],
614+
[0, 0, 0, 0.87758+0.47943j]]
615+
616+
"""
617+
618+
@classproperty
619+
def braket_gate(cls):
620+
from braket.circuits import gates
621+
622+
return gates.CPhaseShift
623+
624+
@classproperty
625+
def qiskit_gate(cls):
626+
from qiskit.circuit.library import CPhaseGate
627+
628+
return CPhaseGate
629+
630+
# TODO: this is a special case, see if it needs to be generalized
631+
qlm_aqasm_keyword = "CNOT;PH"
632+
qiskit_string = "cp"
633+
634+
def __init__(self, theta: Expr | float, control: int, target: int):
635+
self.parameters = [theta]
636+
ControlledGate.__init__(self, [control], [target], P(theta, target), "CP")
637+
definition = UnitaryMatrix(
638+
self.to_canonical_matrix(), **self.native_gate_options
639+
)
640+
ParametrizedGate.__init__(self, definition, [target], [theta], "CP")
641+
642+
def to_canonical_matrix(self):
643+
e = exp(self.theta * 1j) # pyright: ignore[reportOperatorIssue]
644+
return np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, e]])
645+
646+
def __repr__(self) -> str:
647+
theta = int(self.theta) if self.theta == int(self.theta) else self.theta
648+
return f"{type(self).__name__}({theta}, {self.controls[0]}, {self.targets[0]})"
649+
650+
def inverse(self) -> Gate:
651+
return self.__class__(-self.parameters[0], self.controls[0], self.targets[0])
652+
653+
nb_qubits = ( # pyright: ignore[reportAssignmentType,reportIncompatibleMethodOverride]
654+
2
655+
)
656+
657+
597658
class S(OneQubitNoParamGate):
598659
"""One qubit S gate. It's equivalent to ``P(pi/2)``.
599660
It can also be defined as the square-root of the Z (Pauli) gate.
@@ -1141,7 +1202,7 @@ def to_other_language(
11411202

11421203
instruction_str = self.qasm2_gate
11431204
instruction_str += (
1144-
f"({float_to_qasm_str(2 * np.pi / (2 ** float(self.k)))})"
1205+
f"({float_to_qasm_str(-2 * np.pi / (2 ** float(self.k)))})"
11451206
)
11461207

11471208
qubits = ",".join([f"q[{j}]" for j in self.targets])
@@ -1402,6 +1463,26 @@ def __repr__(self) -> str:
14021463
def inverse(self) -> Gate:
14031464
return CRk(self.k, self.controls[0], self.targets[0])
14041465

1466+
def to_other_language(
1467+
self,
1468+
language: Language = Language.QISKIT,
1469+
qiskit_parameters: Optional[set["Parameter"]] = None,
1470+
):
1471+
if language == Language.QASM2:
1472+
from mpqp.qasm.mpqp_to_qasm import float_to_qasm_str
1473+
1474+
instruction_str = self.qasm2_gate
1475+
instruction_str += (
1476+
f"({float_to_qasm_str(-2 * np.pi / (2 ** float(self.k)))})"
1477+
)
1478+
1479+
qubits = ",".join([f"q[{j}]" for j in self.controls]) + ","
1480+
qubits += ",".join([f"q[{j}]" for j in self.targets])
1481+
1482+
return instruction_str + " " + qubits + ";"
1483+
else:
1484+
return super().to_other_language(language, qiskit_parameters)
1485+
14051486

14061487
class TOF(InvolutionGate, ControlledGate, NoParameterGate):
14071488
"""Three-qubit Controlled-Controlled-NOT gate, also known as Toffoli Gate
@@ -1453,6 +1534,10 @@ def to_canonical_matrix(self):
14531534
)
14541535

14551536

1456-
NATIVE_GATES = [CNOT, CRk, CZ, H, Id, P, Rk, Rx, Ry, Rz, S, SWAP, T, TOF, U, X, Y, Z]
1457-
# 3M-TODO : check the possibility to detect when a custom gate can be defined as a native gate, problem with
1458-
# parametrized gates maybe
1537+
NATIVE_GATES = [
1538+
cls
1539+
for _, cls in inspect.getmembers(sys.modules[__name__], inspect.isclass)
1540+
if issubclass(cls, NativeGate)
1541+
and not any("ABC" in base.__name__ for base in cls.__bases__)
1542+
]
1543+
"""All concrete native gates."""

mpqp/core/instruction/measurement/pauli_string.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -681,7 +681,7 @@ def to_other_language(
681681

682682
return cirq_pauli_string
683683
else:
684-
raise ValueError(f"Unsupported language: {language}")
684+
raise NotImplementedError(f"Unsupported language: {language}")
685685

686686
def to_dict(self) -> dict[str, float]:
687687
"""Converts the PauliString object to a dictionary representation.
@@ -869,6 +869,8 @@ def to_other_language(
869869
]
870870

871871
return reduce(mul, cirq_atoms) * self.coef
872+
else:
873+
raise NotImplementedError(f"Unsupported language: {language}")
872874

873875

874876
class PauliStringAtom(PauliStringMonomial):
@@ -1020,6 +1022,8 @@ def to_other_language(
10201022
return pauli_gate_map[self.label](
10211023
LineQubit(0) if target is None else target
10221024
)
1025+
else:
1026+
raise NotImplementedError(f"Unsupported language: {language}")
10231027

10241028

10251029
_allow_atom_creation = True

mpqp/execution/__init__.py

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# pyright: reportUnusedImport=false
2-
from .devices import ATOSDevice, AvailableDevice, AWSDevice, GOOGLEDevice, IBMDevice
2+
from .devices import (
3+
ATOSDevice,
4+
AvailableDevice,
5+
AWSDevice,
6+
GOOGLEDevice,
7+
IBMDevice,
8+
AZUREDevice,
9+
)
310
from .job import Job, JobStatus, JobType
411
from .result import BatchResult, Result, Sample, StateVector
512
from .runner import adjust_measure, run, submit

0 commit comments

Comments
 (0)