Skip to content

Commit

Permalink
✅ improved testing
Browse files Browse the repository at this point in the history
  • Loading branch information
nquetschlich committed Nov 27, 2024
1 parent 6ea6582 commit 93d32dd
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 81 deletions.
32 changes: 14 additions & 18 deletions src/mqt/bench/devices/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@ def get_single_qubit_gate_fidelity(self, gate_type: str, qubit: int) -> float:
gate_type: name of the gate
qubit: index of the qubit
"""
if self.calibration is None:
self.read_calibration()
self.check_calibration()

assert self.calibration is not None

Expand All @@ -58,15 +57,19 @@ def get_single_qubit_gate_fidelity(self, gate_type: str, qubit: int) -> float:

return self.calibration.get_single_qubit_gate_fidelity(gate_type, qubit)

def check_calibration(self) -> None:
"""Check if the calibration data is read and do so if that was not the case."""
if self.calibration is None:
self.read_calibration()

def get_single_qubit_gate_duration(self, gate_type: str, qubit: int) -> float:
"""Get the single-qubit gate duration for a given gate type and qubit.
Arguments:
gate_type: name of the gate
qubit: index of the qubit
"""
if self.calibration is None:
self.read_calibration()
self.check_calibration()
assert self.calibration is not None

if gate_type not in self.gateset.gates:
Expand All @@ -83,8 +86,7 @@ def get_two_qubit_gate_fidelity(self, gate_type: str, qubit1: int, qubit2: int)
qubit1: index of the first qubit
qubit2: index of the second qubit
"""
if self.calibration is None:
self.read_calibration()
self.check_calibration()
assert self.calibration is not None

if gate_type not in self.gateset.gates:
Expand All @@ -101,8 +103,7 @@ def get_two_qubit_gate_duration(self, gate_type: str, qubit1: int, qubit2: int)
qubit1: index of the first qubit
qubit2: index of the second qubit
"""
if self.calibration is None:
self.read_calibration()
self.check_calibration()
assert self.calibration is not None

if gate_type not in self.gateset.gates:
Expand All @@ -117,8 +118,7 @@ def get_readout_fidelity(self, qubit: int) -> float:
Arguments:
qubit: index of the qubit
"""
if self.calibration is None:
self.read_calibration()
self.check_calibration()
assert self.calibration is not None

return self.calibration.get_readout_fidelity(qubit)
Expand All @@ -129,8 +129,7 @@ def get_readout_duration(self, qubit: int) -> float:
Arguments:
qubit: index of the qubit
"""
if self.calibration is None:
self.read_calibration()
self.check_calibration()
assert self.calibration is not None

return self.calibration.get_readout_duration(qubit)
Expand All @@ -141,8 +140,7 @@ def get_single_qubit_gates(self) -> set[str]:
Returns:
list of single-qubit gates
"""
if self.calibration is None:
self.read_calibration()
self.check_calibration()
assert self.calibration is not None
return {gate for qubit in range(self.num_qubits) for gate in self.calibration.single_qubit_gate_fidelity[qubit]}

Expand All @@ -152,8 +150,7 @@ def get_two_qubit_gates(self) -> set[str]:
Returns:
list of two-qubit gates
"""
if self.calibration is None:
self.read_calibration()
self.check_calibration()
assert self.calibration is not None
return {
gate
Expand All @@ -172,8 +169,7 @@ def sanitize_device(self) -> None:
* all two-qubit gates have fidelity data for all qubit pairs in the coupling map.
This is accomplished by substituting the missing fidelity data with the average fidelity for the gate.
"""
if self.calibration is None:
self.read_calibration()
self.check_calibration()
assert self.calibration is not None

# ensure that all single-qubit gates have fidelity data for all qubits in the coupling map
Expand Down
9 changes: 0 additions & 9 deletions src/mqt/bench/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,15 +92,6 @@ def get_default_qasm_output_path() -> str:
return str(resources.files("mqt.bench") / "qasm_output")


def get_default_evaluation_output_path() -> str:
"""Returns the path where all .qasm files are stored."""
return str(resources.files("mqt.bench") / "evaluation")


def get_zip_folder_path() -> str:
"""Returns the path where the zip file is stored."""
return str(resources.files("mqt.bench") / "qasm_output")


def get_examplary_max_cut_qp(n_nodes: int, degree: int = 2) -> QuadraticProgram:
"""Returns a quadratic problem formulation of a max cut problem of a random graph.
Expand Down
85 changes: 31 additions & 54 deletions tests/devices/test_devices.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,60 +47,7 @@ def test_unsupported_device() -> None:

def test_device_calibration_autoread() -> None:
"""Test that all device calibration methods raise errors when no calibration data is available."""
device = IBMWashington()
qubit1, qubit2 = 0, 1
gate1 = "x"
gate2 = "cx"
wrong_gate = "wrong"
wrong_qubit = -1

# Test all methods with missing calibration data and therefore autoread
assert 0 <= device.get_single_qubit_gate_fidelity(gate1, qubit1) <= 1
with pytest.raises(
ValueError, match=f"Single-qubit fidelity for gate {wrong_gate} and qubit {wrong_qubit} not available."
):
device.calibration.get_single_qubit_gate_fidelity(wrong_gate, wrong_qubit)
device.calibration = None
device.get_single_qubit_gate_duration(gate1, qubit1)
with pytest.raises(
ValueError, match=f"Single-qubit duration for gate {wrong_gate} and qubit {wrong_qubit} not available."
):
device.calibration.get_single_qubit_gate_duration(wrong_gate, wrong_qubit)
device.calibration = None
device.get_two_qubit_gate_fidelity(gate2, qubit1, qubit2)
with pytest.raises(
ValueError,
match=f"Two-qubit fidelity for gate {wrong_gate} and qubits {wrong_qubit} and {wrong_qubit} not available.",
):
device.calibration.get_two_qubit_gate_fidelity(wrong_gate, wrong_qubit, wrong_qubit)
device.calibration = None
device.get_two_qubit_gate_duration(gate2, qubit1, qubit2)
with pytest.raises(
ValueError,
match=f"Two-qubit duration for gate {wrong_gate} and qubits {wrong_qubit} and {wrong_qubit} not available.",
):
device.calibration.get_two_qubit_gate_duration(wrong_gate, wrong_qubit, wrong_qubit)
device.calibration = None
device.get_readout_fidelity(qubit1)
with pytest.raises(ValueError, match=f"Readout fidelity for qubit {wrong_qubit} not available."):
device.calibration.get_readout_fidelity(wrong_qubit)
device.calibration = None
device.get_readout_duration(qubit1)
with pytest.raises(ValueError, match=f"Readout duration for qubit {wrong_qubit} not available."):
device.calibration.get_readout_duration(wrong_qubit)
device.calibration = None
device.sanitize_device()
device.calibration = None
for gate in device.get_single_qubit_gates():
assert gate in device.gateset.gates
device.calibration = None
for gate in device.get_two_qubit_gates():
assert gate in device.gateset.gates

with pytest.raises(ValueError, match=f"T1 for qubit {wrong_qubit} not available."):
device.calibration.get_t1(wrong_qubit)
with pytest.raises(ValueError, match=f"T2 for qubit {wrong_qubit} not available."):
device.calibration.get_t2(wrong_qubit)
IBMWashington()


def test_device_calibration_errors() -> None:
Expand All @@ -123,6 +70,7 @@ def test_device_calibration_errors() -> None:
device.get_readout_fidelity(qubit1)
with pytest.raises(ValueError, match="Readout duration values not available."):
device.get_readout_duration(qubit1)

with pytest.raises(ValueError, match="Single-qubit gate fidelity values not available."):
device.calibration.get_single_qubit_gate_fidelity(gate, qubit1)
with pytest.raises(ValueError, match="Single-qubit gate duration values not available."):
Expand All @@ -148,6 +96,35 @@ def test_device_calibration_errors() -> None:
with pytest.raises(ValueError, match="Readout duration values not available."):
device.calibration.compute_average_readout_duration()

device.read_calibration()
with pytest.raises(ValueError, match=f"Single-qubit fidelity for gate {gate} and qubit {qubit1} not available."):
device.calibration.get_single_qubit_gate_fidelity(gate, qubit1)
with pytest.raises(ValueError, match=f"Single-qubit duration for gate {gate} and qubit {qubit1} not available."):
device.calibration.get_single_qubit_gate_duration(gate, qubit1)
with pytest.raises(
ValueError,
match=f"Two-qubit fidelity for gate {gate} and qubits {qubit1} and {qubit2} not available.",
):
device.calibration.get_two_qubit_gate_fidelity(gate, qubit1, qubit2)
with pytest.raises(
ValueError,
match=f"Two-qubit duration for gate {gate} and qubits {qubit1} and {qubit2} not available.",
):
device.calibration.get_two_qubit_gate_duration(gate, qubit1, qubit2)
with pytest.raises(ValueError, match=f"Readout fidelity for qubit {qubit1} not available."):
device.calibration.get_readout_fidelity(qubit1)
with pytest.raises(ValueError, match=f"Readout duration for qubit {qubit1} not available."):
device.calibration.get_readout_duration(qubit1)
for gate in device.get_single_qubit_gates():
assert gate in device.gateset.gates
device.calibration = None
for gate in device.get_two_qubit_gates():
assert gate in device.gateset.gates
with pytest.raises(ValueError, match=f"T1 for qubit {qubit1} not available."):
device.calibration.get_t1(qubit1)
with pytest.raises(ValueError, match=f"T2 for qubit {qubit1} not available."):
device.calibration.get_t2(qubit1)


def test_get_device_calibration_path() -> None:
"""Test if the correct error message is shown if the calibration file does not exist."""
Expand Down
15 changes: 15 additions & 0 deletions tests/test_benchmark_generation.py
Original file line number Diff line number Diff line change
Expand Up @@ -374,3 +374,18 @@ def evaluate_benchmark_with_qasm_formats(
assert load_qasm2(filepath, custom_instructions=LEGACY_CUSTOM_INSTRUCTIONS)
else:
assert load_qasm3(filepath)

def test_bv() -> None:
"""Test the creation of the BV benchmark."""
qc = bv.create_circuit(3)
assert qc.depth() > 0
assert qc.num_qubits == 3
assert "bv" in qc.name

qc = bv.create_circuit(3, dynamic=True)
assert qc.depth() > 0
assert qc.num_qubits == 3
assert "bv" in qc.name

with pytest.raises(ValueError, match="Length of hidden_string must be num_qubits - 1."):
bv.create_circuit(3, hidden_string="wrong")

0 comments on commit 93d32dd

Please sign in to comment.