Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: validity for gate, job_type, measure, noise, pauli_string and other_instructions #106

Merged
merged 13 commits into from
Nov 20, 2024
Merged
1 change: 1 addition & 0 deletions mpqp/all.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
H,
Id,
P,
CP,
ParametrizedGate,
Rk,
Rk_dagger,
Expand Down
4 changes: 1 addition & 3 deletions mpqp/core/circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -956,7 +956,7 @@ def to_other_language(
new_circ.name = self.label

for instruction in self.instructions:
if isinstance(instruction, Measure):
if isinstance(instruction, (Measure, Breakpoint)):
continue
qiskit_inst = instruction.to_other_language(language, qiskit_parameters)
if TYPE_CHECKING:
Expand All @@ -983,8 +983,6 @@ def to_other_language(
qargs = instruction.targets
elif isinstance(instruction, Barrier):
qargs = range(self.nb_qubits)
elif isinstance(instruction, Breakpoint):
continue
else:
raise ValueError(f"Instruction not handled: {instruction}")

Expand Down
2 changes: 2 additions & 0 deletions mpqp/core/instruction/barrier.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ def to_other_language(
elif language == Language.QASM2:
qubits = ",".join([f"q[{j}]" for j in self.targets])
return "barrier " + qubits + ";"
else:
raise NotImplementedError(f"{language} is not supported")

def __repr__(self):
return f"{type(self).__name__}({self.size})"
7 changes: 4 additions & 3 deletions mpqp/core/instruction/breakpoint.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from __future__ import annotations
from typing import Optional

from qiskit.circuit import Parameter
from typing import TYPE_CHECKING, Optional

from mpqp.core.instruction import Instruction
from mpqp.core.languages import Language

if TYPE_CHECKING:
from qiskit.circuit import Parameter


class Breakpoint(Instruction):
"""A breakpoint is a special instruction that will display the state of the
Expand Down
1 change: 1 addition & 0 deletions mpqp/core/instruction/gates/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
H,
Id,
P,
CP,
Rk,
Rk_dagger,
Rx,
Expand Down
1 change: 1 addition & 0 deletions mpqp/core/instruction/gates/gate.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ def to_canonical_matrix(self) -> Matrix:
[0, 0, 0, 1]]

"""
pass

def inverse(self) -> Gate:
"""Computing the inverse of this gate.
Expand Down
93 changes: 89 additions & 4 deletions mpqp/core/instruction/gates/native_gates.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

from __future__ import annotations

import inspect
import sys
from abc import abstractmethod
from numbers import Integral
from typing import TYPE_CHECKING, Optional
Expand Down Expand Up @@ -406,6 +408,8 @@ def to_other_language(
if self.label:
return self.qiskit_gate(label=self.label)
return self.qiskit_gate()
elif language == Language.BRAKET:
return self.braket_gate()
elif language == Language.QASM2:

instruction_str = self.qasm2_gate
Expand Down Expand Up @@ -594,6 +598,63 @@ def to_canonical_matrix(self) -> Matrix:
)


class CP(RotationGate, ControlledGate):
"""Two-qubit Controlled-P gate.

Args:
theta: Parameter representing the phase to apply.
control: Index referring to the qubit used to control the gate.
target: Index referring to the qubit on which the gate will be applied.

Example:
>>> pprint(CP(0.5, 0, 1).to_matrix())
[[1, 0, 0, 0 ],
[0, 1, 0, 0 ],
[0, 0, 1, 0 ],
[0, 0, 0, 0.87758+0.47943j]]

"""

@classproperty
def braket_gate(cls):
from braket.circuits import gates

return gates.CPhaseShift

@classproperty
def qiskit_gate(cls):
from qiskit.circuit.library import CPhaseGate

return CPhaseGate

# TODO: this is a special case, see if it needs to be generalized
qlm_aqasm_keyword = "CNOT;PH"
qiskit_string = "cp"

def __init__(self, theta: Expr | float, control: int, target: int):
self.parameters = [theta]
ControlledGate.__init__(self, [control], [target], P(theta, target), "CP")
definition = UnitaryMatrix(
self.to_canonical_matrix(), **self.native_gate_options
)
ParametrizedGate.__init__(self, definition, [target], [theta], "CP")

def to_canonical_matrix(self):
e = exp(self.theta * 1j) # pyright: ignore[reportOperatorIssue]
return np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, e]])

def __repr__(self) -> str:
theta = int(self.theta) if self.theta == int(self.theta) else self.theta
return f"{type(self).__name__}({theta}, {self.controls[0]}, {self.targets[0]})"

def inverse(self) -> Gate:
return self.__class__(-self.parameters[0], self.controls[0], self.targets[0])

nb_qubits = ( # pyright: ignore[reportAssignmentType,reportIncompatibleMethodOverride]
2
)


class S(OneQubitNoParamGate):
"""One qubit S gate. It's equivalent to ``P(pi/2)``.
It can also be defined as the square-root of the Z (Pauli) gate.
Expand Down Expand Up @@ -1141,7 +1202,7 @@ def to_other_language(

instruction_str = self.qasm2_gate
instruction_str += (
f"({float_to_qasm_str(2 * np.pi / (2 ** float(self.k)))})"
f"({float_to_qasm_str(-2 * np.pi / (2 ** float(self.k)))})"
)

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

def to_other_language(
self,
language: Language = Language.QISKIT,
qiskit_parameters: Optional[set["Parameter"]] = None,
):
if language == Language.QASM2:
from mpqp.qasm.mpqp_to_qasm import float_to_qasm_str

instruction_str = self.qasm2_gate
instruction_str += (
f"({float_to_qasm_str(-2 * np.pi / (2 ** float(self.k)))})"
)

qubits = ",".join([f"q[{j}]" for j in self.controls]) + ","
qubits += ",".join([f"q[{j}]" for j in self.targets])

return instruction_str + " " + qubits + ";"
else:
return super().to_other_language(language, qiskit_parameters)


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


NATIVE_GATES = [CNOT, CRk, CZ, H, Id, P, Rk, Rx, Ry, Rz, S, SWAP, T, TOF, U, X, Y, Z]
# 3M-TODO : check the possibility to detect when a custom gate can be defined as a native gate, problem with
# parametrized gates maybe
NATIVE_GATES = [
cls
for _, cls in inspect.getmembers(sys.modules[__name__], inspect.isclass)
if issubclass(cls, NativeGate)
and not any("ABC" in base.__name__ for base in cls.__bases__)
]
"""All concrete native gates."""
6 changes: 5 additions & 1 deletion mpqp/core/instruction/measurement/pauli_string.py
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,7 @@ def to_other_language(

return cirq_pauli_string
else:
raise ValueError(f"Unsupported language: {language}")
raise NotImplementedError(f"Unsupported language: {language}")

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

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


class PauliStringAtom(PauliStringMonomial):
Expand Down Expand Up @@ -1020,6 +1022,8 @@ def to_other_language(
return pauli_gate_map[self.label](
LineQubit(0) if target is None else target
)
else:
raise NotImplementedError(f"Unsupported language: {language}")


_allow_atom_creation = True
Expand Down
9 changes: 8 additions & 1 deletion mpqp/execution/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# pyright: reportUnusedImport=false
from .devices import ATOSDevice, AvailableDevice, AWSDevice, GOOGLEDevice, IBMDevice
from .devices import (
ATOSDevice,
AvailableDevice,
AWSDevice,
GOOGLEDevice,
IBMDevice,
AZUREDevice,
)
from .job import Job, JobStatus, JobType
from .result import BatchResult, Result, Sample, StateVector
from .runner import adjust_measure, run, submit
Expand Down
Loading