Skip to content

Commit

Permalink
Fix: Solve strange behavior with qubit_properties in Target. (#13400
Browse files Browse the repository at this point in the history
)

The previous implementation of the Target would always make sure to receive a real value for `num_qubits` or it would default to zero. Mistakenly because of the behavior of `Target::from_configuration` it was assumed that `num_qubits` could be `None` unless otherwise specified. However, the default behavior should be to make `num_qubits` zero unless specified otherwise.

The following commits fix this behavior by fixing the signature of the rust `Target` to have default values and adding an extra check when comparing against `qubit_properties`.

A test casde based on @wshanks findings in #13393 was also included in these additions.
  • Loading branch information
raynelfss authored Nov 6, 2024
1 parent 3be806d commit 6ed7743
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 9 deletions.
17 changes: 8 additions & 9 deletions crates/accelerate/src/target_transpiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,18 +227,18 @@ impl Target {
#[new]
#[pyo3(signature = (
description = None,
num_qubits = None,
num_qubits = 0,
dt = None,
granularity = None,
min_length = None,
pulse_alignment = None,
acquire_alignment = None,
granularity = 1,
min_length = 1,
pulse_alignment = 1,
acquire_alignment = 1,
qubit_properties = None,
concurrent_measurements = None,
))]
fn new(
description: Option<String>,
num_qubits: Option<usize>,
mut num_qubits: Option<usize>,
dt: Option<f64>,
granularity: Option<u32>,
min_length: Option<usize>,
Expand All @@ -247,10 +247,9 @@ impl Target {
qubit_properties: Option<Vec<PyObject>>,
concurrent_measurements: Option<Vec<Vec<PhysicalQubit>>>,
) -> PyResult<Self> {
let mut num_qubits = num_qubits;
if let Some(qubit_properties) = qubit_properties.as_ref() {
if let Some(num_qubits) = num_qubits {
if num_qubits != qubit_properties.len() {
if num_qubits.is_some_and(|num_qubits| num_qubits > 0) {
if num_qubits.unwrap() != qubit_properties.len() {
return Err(PyValueError::new_err(
"The value of num_qubits specified does not match the \
length of the input qubit_properties list",
Expand Down
15 changes: 15 additions & 0 deletions test/python/transpiler/test_target.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
Fake7QPulseV1,
)
from test import QiskitTestCase # pylint: disable=wrong-import-order
from qiskit.providers.backend import QubitProperties
from test.python.providers.fake_mumbai_v2 import ( # pylint: disable=wrong-import-order
FakeMumbaiFractionalCX,
)
Expand Down Expand Up @@ -1185,6 +1186,20 @@ def test_target_serialization_preserve_variadic(self):
# Perform check again, should not throw exception
self.assertTrue(deserialized_target.instruction_supported("u_var", (0, 1)))

def test_target_no_num_qubits_qubit_properties(self):
"""Checks that a Target can be initialized with no qubits but a list of Qubit Properities"""

# Initialize target qubit properties
qubit_properties = [QubitProperties()]

# Initialize the Target with only a list of qubit properties
target = Target(
qubit_properties=qubit_properties,
)

# Check that the Target num_qubit attribute matches the length of qubit properties
self.assertEqual(target.num_qubits, len(qubit_properties))


class TestPulseTarget(QiskitTestCase):
def setUp(self):
Expand Down

0 comments on commit 6ed7743

Please sign in to comment.