Skip to content

Commit

Permalink
Merge branch 'main' into move-target
Browse files Browse the repository at this point in the history
  • Loading branch information
raynelfss authored Jul 24, 2024
2 parents f6e8189 + ffead59 commit 96bd389
Show file tree
Hide file tree
Showing 38 changed files with 872 additions and 636 deletions.
4 changes: 3 additions & 1 deletion crates/accelerate/src/convert_2q_block_matrix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,9 @@ pub fn change_basis(matrix: ArrayView2<Complex64>) -> Array2<Complex64> {

#[pyfunction]
pub fn collect_2q_blocks_filter(node: &Bound<PyAny>) -> Option<bool> {
let Ok(node) = node.downcast::<DAGOpNode>() else { return None };
let Ok(node) = node.downcast::<DAGOpNode>() else {
return None;
};
let node = node.borrow();
match node.instruction.op() {
gate @ (OperationRef::Standard(_) | OperationRef::Gate(_)) => Some(
Expand Down
4 changes: 3 additions & 1 deletion crates/accelerate/src/euler_one_qubit_decomposer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1045,7 +1045,9 @@ fn matmul_1q(operator: &mut [[Complex64; 2]; 2], other: Array2<Complex64>) {

#[pyfunction]
pub fn collect_1q_runs_filter(node: &Bound<PyAny>) -> bool {
let Ok(node) = node.downcast::<DAGOpNode>() else { return false };
let Ok(node) = node.downcast::<DAGOpNode>() else {
return false;
};
let node = node.borrow();
let op = node.instruction.op();
op.num_qubits() == 1
Expand Down
183 changes: 136 additions & 47 deletions crates/accelerate/src/two_qubit_decompose.rs

Large diffs are not rendered by default.

15 changes: 11 additions & 4 deletions crates/circuit/src/circuit_instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,9 @@ impl CircuitInstruction {
if other.is_instance_of::<PyTuple>() {
return Ok(Some(self_._legacy_format(py)?.eq(other)?));
}
let Ok(other) = other.downcast::<CircuitInstruction>() else { return Ok(None) };
let Ok(other) = other.downcast::<CircuitInstruction>() else {
return Ok(None);
};
let other = other.try_borrow()?;

Ok(Some(
Expand Down Expand Up @@ -471,7 +473,7 @@ impl CircuitInstruction {
/// though you can also accept `ob: OperationFromPython` directly, if you don't also need a handle
/// to the Python object that it came from. The handle is useful for the Python-operation caching.
#[derive(Debug)]
pub(crate) struct OperationFromPython {
pub struct OperationFromPython {
pub operation: PackedOperation,
pub params: SmallVec<[Param; 3]>,
pub extra_attrs: Option<Box<ExtraInstructionAttributes>>,
Expand Down Expand Up @@ -508,7 +510,10 @@ impl<'py> FromPyObject<'py> for OperationFromPython {
let Some(standard) = ob_type
.getattr(intern!(py, "_standard_gate"))
.and_then(|standard| standard.extract::<StandardGate>())
.ok() else { break 'standard };
.ok()
else {
break 'standard;
};

// If the instruction is a controlled gate with a not-all-ones control state, it doesn't
// fit our definition of standard. We abuse the fact that we know our standard-gate
Expand Down Expand Up @@ -581,7 +586,9 @@ impl<'py> FromPyObject<'py> for OperationFromPython {

/// Convert a sequence-like Python object to a tuple.
fn as_tuple<'py>(py: Python<'py>, seq: Option<Bound<'py, PyAny>>) -> PyResult<Bound<'py, PyTuple>> {
let Some(seq) = seq else { return Ok(PyTuple::empty_bound(py)) };
let Some(seq) = seq else {
return Ok(PyTuple::empty_bound(py));
};
if seq.is_instance_of::<PyTuple>() {
Ok(seq.downcast_into_exact::<PyTuple>()?)
} else if seq.is_instance_of::<PyList>() {
Expand Down
4 changes: 3 additions & 1 deletion crates/circuit/src/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,9 @@ impl StandardGate {

pub fn __eq__(&self, other: &Bound<PyAny>) -> Py<PyAny> {
let py = other.py();
let Ok(other) = other.extract::<Self>() else { return py.NotImplemented() };
let Ok(other) = other.extract::<Self>() else {
return py.NotImplemented();
};
(*self == other).into_py(py)
}

Expand Down
4 changes: 3 additions & 1 deletion crates/circuit/src/packed_instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,9 @@ impl Drop for PackedOperation {
fn drop_pointer_as<T>(slf: &mut PackedOperation) {
// This should only ever be called when the pointer is valid, but this is defensive just
// to 100% ensure that our `Drop` implementation doesn't panic.
let Some(pointer) = slf.try_pointer() else { return };
let Some(pointer) = slf.try_pointer() else {
return;
};
// SAFETY: `PackedOperation` asserts ownership over its contents, and the contained
// pointer can only be null if we were already dropped. We set our discriminant to mark
// ourselves as plain old data immediately just as a defensive measure.
Expand Down
3 changes: 2 additions & 1 deletion qiskit/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@
_config = _user_config.get_config()

from qiskit.compiler import transpile, assemble, schedule, sequence

from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from .version import __version__

__all__ = [
Expand All @@ -116,4 +116,5 @@
"schedule",
"sequence",
"transpile",
"generate_preset_pass_manager",
]
Original file line number Diff line number Diff line change
Expand Up @@ -227,8 +227,8 @@ def mcrx(
"""
from .rx import RXGate

control_qubits = self.qbit_argument_conversion(q_controls)
target_qubit = self.qbit_argument_conversion(q_target)
control_qubits = self._qbit_argument_conversion(q_controls)
target_qubit = self._qbit_argument_conversion(q_target)
if len(target_qubit) != 1:
raise QiskitError("The mcrz gate needs a single qubit as target.")
all_qubits = control_qubits + target_qubit
Expand Down Expand Up @@ -292,11 +292,11 @@ def mcry(
"""
from .ry import RYGate

control_qubits = self.qbit_argument_conversion(q_controls)
target_qubit = self.qbit_argument_conversion(q_target)
control_qubits = self._qbit_argument_conversion(q_controls)
target_qubit = self._qbit_argument_conversion(q_target)
if len(target_qubit) != 1:
raise QiskitError("The mcrz gate needs a single qubit as target.")
ancillary_qubits = [] if q_ancillae is None else self.qbit_argument_conversion(q_ancillae)
ancillary_qubits = [] if q_ancillae is None else self._qbit_argument_conversion(q_ancillae)
all_qubits = control_qubits + target_qubit + ancillary_qubits
target_qubit = target_qubit[0]
self._check_dups(all_qubits)
Expand Down Expand Up @@ -365,8 +365,8 @@ def mcrz(
"""
from .rz import CRZGate, RZGate

control_qubits = self.qbit_argument_conversion(q_controls)
target_qubit = self.qbit_argument_conversion(q_target)
control_qubits = self._qbit_argument_conversion(q_controls)
target_qubit = self._qbit_argument_conversion(q_target)
if len(target_qubit) != 1:
raise QiskitError("The mcrz gate needs a single qubit as target.")
all_qubits = control_qubits + target_qubit
Expand Down
107 changes: 93 additions & 14 deletions qiskit/circuit/quantumcircuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
from qiskit.circuit.gate import Gate
from qiskit.circuit.parameter import Parameter
from qiskit.circuit.exceptions import CircuitError
from qiskit.utils import deprecate_func
from . import _classical_resource_map
from ._utils import sort_parameters
from .controlflow import ControlFlowOp, _builder_utils
Expand Down Expand Up @@ -1077,7 +1078,7 @@ def __init__(
self.name: str
"""A human-readable name for the circuit."""
if name is None:
self._base_name = self.cls_prefix()
self._base_name = self._cls_prefix()
self._name_update()
elif not isinstance(name, str):
raise CircuitError(
Expand Down Expand Up @@ -1400,24 +1401,47 @@ def _increment_instances(cls):
cls.instances += 1

@classmethod
@deprecate_func(
since=1.2,
removal_timeline="in the 2.0 release",
additional_msg="This method is only used as an internal helper "
"and will be removed with no replacement.",
)
def cls_instances(cls) -> int:
"""Return the current number of instances of this class,
useful for auto naming."""
return cls.instances

@classmethod
def _cls_instances(cls) -> int:
"""Return the current number of instances of this class,
useful for auto naming."""
return cls.instances

@classmethod
@deprecate_func(
since=1.2,
removal_timeline="in the 2.0 release",
additional_msg="This method is only used as an internal helper "
"and will be removed with no replacement.",
)
def cls_prefix(cls) -> str:
"""Return the prefix to use for auto naming."""
return cls.prefix

@classmethod
def _cls_prefix(cls) -> str:
"""Return the prefix to use for auto naming."""
return cls.prefix

def _name_update(self) -> None:
"""update name of instance using instance number"""
if not is_main_process():
pid_name = f"-{mp.current_process().pid}"
else:
pid_name = ""

self.name = f"{self._base_name}-{self.cls_instances()}{pid_name}"
self.name = f"{self._base_name}-{self._cls_instances()}{pid_name}"

def has_register(self, register: Register) -> bool:
"""
Expand Down Expand Up @@ -1926,7 +1950,7 @@ def replace_var(var: expr.Var, cache: Mapping[expr.Var, expr.Var]) -> expr.Var:
mapped_qubits = dest.qubits
edge_map.update(zip(other.qubits, dest.qubits))
else:
mapped_qubits = dest.qbit_argument_conversion(qubits)
mapped_qubits = dest._qbit_argument_conversion(qubits)
if len(mapped_qubits) != other.num_qubits:
raise CircuitError(
f"Number of items in qubits parameter ({len(mapped_qubits)}) does not"
Expand All @@ -1942,7 +1966,7 @@ def replace_var(var: expr.Var, cache: Mapping[expr.Var, expr.Var]) -> expr.Var:
mapped_clbits = dest.clbits
edge_map.update(zip(other.clbits, dest.clbits))
else:
mapped_clbits = dest.cbit_argument_conversion(clbits)
mapped_clbits = dest._cbit_argument_conversion(clbits)
if len(mapped_clbits) != other.num_clbits:
raise CircuitError(
f"Number of items in clbits parameter ({len(mapped_clbits)}) does not"
Expand All @@ -1952,7 +1976,7 @@ def replace_var(var: expr.Var, cache: Mapping[expr.Var, expr.Var]) -> expr.Var:
raise CircuitError(
f"Duplicate clbits referenced in 'clbits' parameter: '{mapped_clbits}'"
)
edge_map.update(zip(other.clbits, dest.cbit_argument_conversion(clbits)))
edge_map.update(zip(other.clbits, dest._cbit_argument_conversion(clbits)))

for gate, cals in other.calibrations.items():
dest._calibrations[gate].update(cals)
Expand Down Expand Up @@ -2267,38 +2291,91 @@ def __getitem__(self, item):
return self._data[item]

@staticmethod
@deprecate_func(
since=1.2,
removal_timeline="in the 2.0 release",
additional_msg="This method is only used as an internal helper "
"and will be removed with no replacement.",
)
def cast(value: S, type_: Callable[..., T]) -> Union[S, T]:
"""Best effort to cast value to type. Otherwise, returns the value."""
try:
return type_(value)
except (ValueError, TypeError):
return value

@staticmethod
def _cast(value: S, type_: Callable[..., T]) -> Union[S, T]:
"""Best effort to cast value to type. Otherwise, returns the value."""
try:
return type_(value)
except (ValueError, TypeError):
return value

@deprecate_func(
since=1.2,
removal_timeline="in the 2.0 release",
additional_msg="This method is only used as an internal helper "
"and will be removed with no replacement.",
)
def qbit_argument_conversion(self, qubit_representation: QubitSpecifier) -> list[Qubit]:
"""
Converts several qubit representations (such as indexes, range, etc.)
into a list of qubits.
Args:
qubit_representation (Object): representation to expand
qubit_representation: Representation to expand.
Returns:
List(Qubit): the resolved instances of the qubits.
The resolved instances of the qubits.
"""

return self._qbit_argument_conversion(qubit_representation)

def _qbit_argument_conversion(self, qubit_representation: QubitSpecifier) -> list[Qubit]:
"""
Converts several qubit representations (such as indexes, range, etc.)
into a list of qubits.
Args:
qubit_representation: Representation to expand.
Returns:
The resolved instances of the qubits.
"""
return _bit_argument_conversion(
qubit_representation, self.qubits, self._qubit_indices, Qubit
)

@deprecate_func(
since=1.2,
removal_timeline="in the 2.0 release",
additional_msg="This method is only used as an internal helper "
"and will be removed with no replacement.",
)
def cbit_argument_conversion(self, clbit_representation: ClbitSpecifier) -> list[Clbit]:
"""
Converts several classical bit representations (such as indexes, range, etc.)
into a list of classical bits.
Args:
clbit_representation (Object): representation to expand
clbit_representation : Representation to expand.
Returns:
List(tuple): Where each tuple is a classical bit.
A list of tuples where each tuple is a classical bit.
"""
return self._cbit_argument_conversion(clbit_representation)

def _cbit_argument_conversion(self, clbit_representation: ClbitSpecifier) -> list[Clbit]:
"""
Converts several classical bit representations (such as indexes, range, etc.)
into a list of classical bits.
Args:
clbit_representation: Representation to expand.
Returns:
A list of tuples where each tuple is a classical bit.
"""
return _bit_argument_conversion(
clbit_representation, self.clbits, self._clbit_indices, Clbit
Expand All @@ -2317,7 +2394,7 @@ def _append_standard_gate(
if params is None:
params = []

expanded_qargs = [self.qbit_argument_conversion(qarg) for qarg in qargs or []]
expanded_qargs = [self._qbit_argument_conversion(qarg) for qarg in qargs or []]
for param in params:
Gate.validate_parameter(op, param)

Expand Down Expand Up @@ -2416,8 +2493,8 @@ def append(
" which are not in this circuit"
)

expanded_qargs = [self.qbit_argument_conversion(qarg) for qarg in qargs or []]
expanded_cargs = [self.cbit_argument_conversion(carg) for carg in cargs or []]
expanded_qargs = [self._qbit_argument_conversion(qarg) for qarg in qargs or []]
expanded_cargs = [self._cbit_argument_conversion(carg) for carg in cargs or []]

instructions = InstructionSet(resource_requester=circuit_scope.resolve_classical_resource)
# For Operations that are non-Instructions, we use the Instruction's default method
Expand Down Expand Up @@ -4416,7 +4493,9 @@ def barrier(self, *qargs: QubitSpecifier, label=None) -> InstructionSet:

if qargs:
# This uses a `dict` not a `set` to guarantee a deterministic order to the arguments.
qubits = tuple({q: None for qarg in qargs for q in self.qbit_argument_conversion(qarg)})
qubits = tuple(
{q: None for qarg in qargs for q in self._qbit_argument_conversion(qarg)}
)
return self.append(
CircuitInstruction(Barrier(len(qubits), label=label), qubits, ()), copy=False
)
Expand Down Expand Up @@ -5448,7 +5527,7 @@ def mcx(

# check ancilla input
if ancilla_qubits:
_ = self.qbit_argument_conversion(ancilla_qubits)
_ = self._qbit_argument_conversion(ancilla_qubits)

try:
gate = available_implementations[mode]
Expand Down
4 changes: 2 additions & 2 deletions qiskit/circuit/quantumcircuitdata.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ def _resolve_legacy_value(self, operation, qargs, cargs) -> CircuitInstruction:
if not isinstance(operation, Operation):
raise CircuitError("object is not an Operation.")

expanded_qargs = [self._circuit.qbit_argument_conversion(qarg) for qarg in qargs or []]
expanded_cargs = [self._circuit.cbit_argument_conversion(carg) for carg in cargs or []]
expanded_qargs = [self._circuit._qbit_argument_conversion(qarg) for qarg in qargs or []]
expanded_cargs = [self._circuit._cbit_argument_conversion(carg) for carg in cargs or []]

if isinstance(operation, Instruction):
broadcast_args = list(operation.broadcast_arguments(expanded_qargs, expanded_cargs))
Expand Down
2 changes: 1 addition & 1 deletion qiskit/compiler/scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from qiskit.exceptions import QiskitError
from qiskit.pulse import InstructionScheduleMap, Schedule
from qiskit.providers.backend import Backend
from qiskit.scheduler import ScheduleConfig
from qiskit.scheduler.config import ScheduleConfig
from qiskit.scheduler.schedule_circuit import schedule_circuit
from qiskit.utils.parallel import parallel_map

Expand Down
Loading

0 comments on commit 96bd389

Please sign in to comment.