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
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion mpqp/core/circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -932,7 +932,7 @@ def to_other_language(
new_circ.name = self.label

for instruction in self.instructions:
if isinstance(instruction, ExpectationMeasure):
if isinstance(instruction, (ExpectationMeasure, Breakpoint)):
# these measures have no equivalent in Qiskit
continue
qiskit_inst = instruction.to_other_language(language, qiskit_parameters)
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 @@ -31,3 +31,5 @@ def to_other_language(
from qiskit.circuit.library import Barrier as QiskitBarrier

return QiskitBarrier(self.size)
else:
raise NotImplementedError(f"{language} is not supported")
12 changes: 12 additions & 0 deletions mpqp/core/instruction/breakpoint.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
from __future__ import annotations
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):
Expand Down Expand Up @@ -30,3 +35,10 @@ def __repr__(self) -> str:
f"Breakpoint(targets={self.targets}, draw_circuit={self.draw_circuit},"
f" enabled={self.enabled}, label={self.label})"
)

def to_other_language(
self,
language: Language = Language.QISKIT,
qiskit_parameters: Optional[set["Parameter"]] = None,
):
raise NotImplementedError(f"{language} is not supported")
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
16 changes: 13 additions & 3 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 @@ -323,6 +325,10 @@ 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()
else:
raise NotImplementedError(f"Error: {language} is not supported")


class X(OneQubitNoParamGate, InvolutionGate):
Expand Down Expand Up @@ -1282,6 +1288,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."""
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
116 changes: 110 additions & 6 deletions mpqp/execution/devices.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,22 @@ def has_reduced_gate_set(self) -> bool:
``True`` if this device only handles a restricted set of gates."""
return False

@abstractmethod
def supports_samples(self) -> bool:
pass

@abstractmethod
def supports_state_vector(self) -> bool:
pass

@abstractmethod
def supports_observable(self) -> bool:
pass

@abstractmethod
def supports_observable_ideal(self) -> bool:
pass


class IBMDevice(AvailableDevice):
"""Enum regrouping all available devices provided by IBM Quantum.
Expand Down Expand Up @@ -123,15 +139,33 @@ def has_reduced_gate_set(self) -> bool:
IBMDevice.AER_SIMULATOR_EXTENDED_STABILIZER,
}

def supports_statevector(self):
def is_simulator(self) -> bool:
return self in {
IBMDevice.AER_SIMULATOR,
IBMDevice.AER_SIMULATOR_STATEVECTOR,
IBMDevice.AER_SIMULATOR_DENSITY_MATRIX,
IBMDevice.AER_SIMULATOR_STABILIZER,
IBMDevice.AER_SIMULATOR_EXTENDED_STABILIZER,
IBMDevice.AER_SIMULATOR_MATRIX_PRODUCT_STATE,
}

def is_noisy_simulator(self) -> bool:
return self.is_simulator()

def supports_samples(self) -> bool:
return True

def supports_state_vector(self) -> bool:
return self in {
IBMDevice.AER_SIMULATOR,
IBMDevice.AER_SIMULATOR_STATEVECTOR,
IBMDevice.AER_SIMULATOR_MATRIX_PRODUCT_STATE,
IBMDevice.AER_SIMULATOR_EXTENDED_STABILIZER,
}

def is_simulator(self) -> bool:
def supports_observable(self) -> bool:
return True

def supports_observable_ideal(self) -> bool:
return self in {
IBMDevice.AER_SIMULATOR,
IBMDevice.AER_SIMULATOR_STATEVECTOR,
Expand All @@ -141,9 +175,6 @@ def is_simulator(self) -> bool:
IBMDevice.AER_SIMULATOR_MATRIX_PRODUCT_STATE,
}

def is_noisy_simulator(self) -> bool:
return self.is_simulator()


class ATOSDevice(AvailableDevice):
"""Enum regrouping all available devices provided by ATOS."""
Expand Down Expand Up @@ -194,6 +225,27 @@ def from_str_remote(name: str):
return elem
raise ValueError(f"No device found for name `{name}`.")

def supports_samples(self) -> bool:
return True

def supports_state_vector(self) -> bool:
return self in {
ATOSDevice.MYQLM_PYLINALG,
ATOSDevice.MYQLM_CLINALG,
ATOSDevice.QLM_LINALG,
ATOSDevice.QLM_MPS,
}

def supports_observable(self) -> bool:
return self in {
ATOSDevice.MYQLM_PYLINALG,
ATOSDevice.MYQLM_CLINALG,
ATOSDevice.QLM_LINALG,
}

def supports_observable_ideal(self) -> bool:
return True


class AWSDevice(AvailableDevice):
"""Enum regrouping all available devices provided by AWS Braket."""
Expand Down Expand Up @@ -296,6 +348,24 @@ def from_arn(arn: str):
return elem
raise ValueError(f"No device found for ARN `{arn}`.")

def supports_samples(self) -> bool:
return True

def supports_state_vector(self) -> bool:
return self in {
AWSDevice.BRAKET_LOCAL_SIMULATOR,
AWSDevice.BRAKET_SV1_SIMULATOR,
}

def supports_observable(self) -> bool:
return True

def supports_observable_ideal(self) -> bool:
return self in {
AWSDevice.BRAKET_LOCAL_SIMULATOR,
AWSDevice.BRAKET_TN1_SIMULATOR,
}


class GOOGLEDevice(AvailableDevice):
"""Enum regrouping all available devices provided by CIRQ."""
Expand Down Expand Up @@ -337,6 +407,28 @@ def has_reduced_gate_set(self) -> bool:
GOOGLEDevice.IONQ_QPU,
}

def supports_samples(self) -> bool:
return True

def supports_state_vector(self) -> bool:
return self in {
GOOGLEDevice.CIRQ_LOCAL_SIMULATOR,
}

def supports_observable(self) -> bool:
return self in {
GOOGLEDevice.PROCESSOR_RAINBOW,
GOOGLEDevice.PROCESSOR_WEBER,
GOOGLEDevice.CIRQ_LOCAL_SIMULATOR,
}

def supports_observable_ideal(self) -> bool:
return self in {
GOOGLEDevice.PROCESSOR_RAINBOW,
GOOGLEDevice.PROCESSOR_WEBER,
GOOGLEDevice.CIRQ_LOCAL_SIMULATOR,
}


class AZUREDevice(AvailableDevice):
"""Enum regrouping all available devices provided by AZURE."""
Expand Down Expand Up @@ -371,3 +463,15 @@ def is_noisy_simulator(self) -> bool:

def is_ionq(self):
return self.name.startswith("IONQ")

def supports_samples(self) -> bool:
return not self == AZUREDevice.MICROSOFT_ESTIMATOR

def supports_state_vector(self) -> bool:
return False

def supports_observable(self) -> bool:
return False

def supports_observable_ideal(self) -> bool:
return False
2 changes: 1 addition & 1 deletion mpqp/execution/providers/ibm.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ def check_job_compatibility(job: Job):
f"{list(map(lambda cls: cls.__name__, job.job_type.value))}. "
f"{type(job.measure).__name__} was given instead."
)
if job.job_type == JobType.STATE_VECTOR and not job.device.supports_statevector():
if job.job_type == JobType.STATE_VECTOR and not job.device.supports_state_vector():
raise DeviceJobIncompatibleError(
"Cannot reconstruct state vector with this device. Please use "
f"{IBMDevice.AER_SIMULATOR_STATEVECTOR} instead (or change the job "
Expand Down
17 changes: 16 additions & 1 deletion mpqp/noise/noise_model.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from __future__ import annotations

import inspect
import sys
from abc import ABC, abstractmethod
from functools import reduce
from itertools import product
Expand Down Expand Up @@ -312,7 +314,6 @@ def __init__(

prob_upper_bound = 1 if dimension == 1 else 1 + 1 / (dimension**2 - 1)
if not (0 <= prob <= prob_upper_bound):
print(dimension, prob, prob_upper_bound)
raise ValueError(
f"Invalid probability: {prob} but should have been between 0 "
f"and {prob_upper_bound}."
Expand Down Expand Up @@ -410,6 +411,8 @@ def to_other_language(
method_2q="equal_probs",
depol_type="pauli",
)
else:
raise NotImplementedError(f"Depolarizing is not implemented for {language}")

def info(self) -> str:
dimension = f" and dimension {self.dimension}" if self.dimension != 1 else ""
Expand Down Expand Up @@ -828,3 +831,15 @@ def __init__(self):
raise NotImplementedError(
f"{type(self).__name__} noise model is not yet implemented."
)


NOISE_MODELS = [
cls
for _, cls in inspect.getmembers(sys.modules[__name__], inspect.isclass)
if issubclass(cls, NoiseModel)
and not (
any("ABC" in base.__name__ for base in cls.__bases__)
or "M-TODO" in (cls.__doc__ or "")
)
]
"""All concrete noise models."""
Loading