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

Rebalance CircuitInstruction and PackedInstruction #12730

Merged
merged 11 commits into from
Jul 23, 2024
5 changes: 3 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ license = "Apache-2.0"
#
# Each crate can add on specific features freely as it inherits.
[workspace.dependencies]
bytemuck = "1.16"
indexmap.version = "2.2.6"
hashbrown.version = "0.14.0"
num-complex = "0.4"
Expand Down
75 changes: 30 additions & 45 deletions crates/accelerate/src/convert_2q_block_matrix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,33 +23,32 @@ use numpy::{IntoPyArray, PyArray2, PyReadonlyArray2};
use smallvec::SmallVec;

use qiskit_circuit::bit_data::BitData;
use qiskit_circuit::circuit_instruction::{operation_type_to_py, CircuitInstruction};
use qiskit_circuit::circuit_instruction::CircuitInstruction;
use qiskit_circuit::dag_node::DAGOpNode;
use qiskit_circuit::gate_matrix::ONE_QUBIT_IDENTITY;
use qiskit_circuit::imports::QI_OPERATOR;
use qiskit_circuit::operations::{Operation, OperationType};
use qiskit_circuit::operations::{Operation, OperationRef};

use crate::QiskitError;

fn get_matrix_from_inst<'py>(
py: Python<'py>,
inst: &'py CircuitInstruction,
) -> PyResult<Array2<Complex64>> {
match inst.operation.matrix(&inst.params) {
Some(mat) => Ok(mat),
None => match inst.operation {
OperationType::Standard(_) => Err(QiskitError::new_err(
"Parameterized gates can't be consolidated",
)),
OperationType::Gate(_) => Ok(QI_OPERATOR
.get_bound(py)
.call1((operation_type_to_py(py, inst)?,))?
.getattr(intern!(py, "data"))?
.extract::<PyReadonlyArray2<Complex64>>()?
.as_array()
.to_owned()),
_ => unreachable!("Only called for unitary ops"),
},
if let Some(mat) = inst.op().matrix(&inst.params) {
Ok(mat)
} else if inst.operation.try_standard_gate().is_some() {
Err(QiskitError::new_err(
"Parameterized gates can't be consolidated",
))
} else {
Ok(QI_OPERATOR
.get_bound(py)
.call1((inst.get_operation(py)?,))?
.getattr(intern!(py, "data"))?
.extract::<PyReadonlyArray2<Complex64>>()?
.as_array()
.to_owned())
}
}

Expand Down Expand Up @@ -127,34 +126,20 @@ pub fn change_basis(matrix: ArrayView2<Complex64>) -> Array2<Complex64> {

#[pyfunction]
pub fn collect_2q_blocks_filter(node: &Bound<PyAny>) -> Option<bool> {
match node.downcast::<DAGOpNode>() {
Ok(bound_node) => {
let node = bound_node.borrow();
match &node.instruction.operation {
OperationType::Standard(gate) => Some(
gate.num_qubits() <= 2
&& node
.instruction
.extra_attrs
.as_ref()
.and_then(|attrs| attrs.condition.as_ref())
.is_none()
&& !node.is_parameterized(),
),
OperationType::Gate(gate) => Some(
gate.num_qubits() <= 2
&& node
.instruction
.extra_attrs
.as_ref()
.and_then(|attrs| attrs.condition.as_ref())
.is_none()
&& !node.is_parameterized(),
),
_ => Some(false),
}
}
Err(_) => None,
let Ok(node) = node.downcast::<DAGOpNode>() else { return None };
let node = node.borrow();
match node.instruction.op() {
gate @ (OperationRef::Standard(_) | OperationRef::Gate(_)) => Some(
gate.num_qubits() <= 2
&& node
.instruction
.extra_attrs
.as_ref()
.and_then(|attrs| attrs.condition.as_ref())
.is_none()
&& !node.is_parameterized(),
),
_ => Some(false),
}
}

Expand Down
33 changes: 12 additions & 21 deletions crates/accelerate/src/euler_one_qubit_decomposer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -743,7 +743,7 @@ pub fn compute_error_list(
.iter()
.map(|node| {
(
node.instruction.operation.name().to_string(),
node.instruction.op().name().to_string(),
smallvec![], // Params not needed in this path
)
})
Expand Down Expand Up @@ -988,11 +988,10 @@ pub fn optimize_1q_gates_decomposition(
.iter()
.map(|node| {
if let Some(err_map) = error_map {
error *=
compute_error_term(node.instruction.operation.name(), err_map, qubit)
error *= compute_error_term(node.instruction.op().name(), err_map, qubit)
}
node.instruction
.operation
.op()
.matrix(&node.instruction.params)
.expect("No matrix defined for operation")
})
Expand Down Expand Up @@ -1046,24 +1045,16 @@ fn matmul_1q(operator: &mut [[Complex64; 2]; 2], other: Array2<Complex64>) {

#[pyfunction]
pub fn collect_1q_runs_filter(node: &Bound<PyAny>) -> bool {
let op_node = node.downcast::<DAGOpNode>();
match op_node {
Ok(bound_node) => {
let node = bound_node.borrow();
node.instruction.operation.num_qubits() == 1
&& node.instruction.operation.num_clbits() == 0
&& node
.instruction
.operation
.matrix(&node.instruction.params)
.is_some()
&& match &node.instruction.extra_attrs {
None => true,
Some(attrs) => attrs.condition.is_none(),
}
let Ok(node) = node.downcast::<DAGOpNode>() else { return false };
let node = node.borrow();
let op = node.instruction.op();
op.num_qubits() == 1
&& op.num_clbits() == 0
&& op.matrix(&node.instruction.params).is_some()
&& match &node.instruction.extra_attrs {
None => true,
Some(attrs) => attrs.condition.is_none(),
}
Err(_) => false,
}
}

#[pymodule]
Expand Down
1 change: 1 addition & 0 deletions crates/circuit/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ name = "qiskit_circuit"
doctest = false

[dependencies]
bytemuck.workspace = true
hashbrown.workspace = true
num-complex.workspace = true
ndarray.workspace = true
Expand Down
Loading
Loading