Skip to content

Commit

Permalink
Merge branch 'main' into dag-concatenate
Browse files Browse the repository at this point in the history
  • Loading branch information
raynelfss authored Oct 16, 2024
2 parents 85b3bc3 + 50f2965 commit b87e528
Show file tree
Hide file tree
Showing 57 changed files with 644 additions and 467 deletions.
182 changes: 64 additions & 118 deletions Cargo.lock

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ license = "Apache-2.0"
#
# Each crate can add on specific features freely as it inherits.
[workspace.dependencies]
bytemuck = "1.18"
bytemuck = "1.19"
indexmap.version = "2.6.0"
hashbrown.version = "0.14.5"
num-bigint = "0.4"
num-complex = "0.4"
ndarray = "^0.15.6"
numpy = "0.21.0"
ndarray = "0.15"
numpy = "0.22.0"
smallvec = "1.13"
thiserror = "1.0"
rustworkx-core = "0.15"
Expand All @@ -34,7 +34,7 @@ rayon = "1.10"
# distributions). We only activate that feature when building the C extension module; we still need
# it disabled for Rust-only tests to avoid linker errors with it not being loaded. See
# https://pyo3.rs/main/features#extension-module for more.
pyo3 = { version = "0.21.2", features = ["abi3-py39"] }
pyo3 = { version = "0.22.5", features = ["abi3-py39"] }

# These are our own crates.
qiskit-accelerate = { path = "crates/accelerate" }
Expand Down
2 changes: 1 addition & 1 deletion crates/accelerate/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,4 @@ version = "0.18.22"
features = ["macro"]

[features]
cache_pygates = ["qiskit-circuit/cache_pygates"]
cache_pygates = ["qiskit-circuit/cache_pygates"]
1 change: 1 addition & 0 deletions crates/accelerate/src/barrier_before_final_measurement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use qiskit_circuit::Qubit;
static FINAL_OP_NAMES: [&str; 2] = ["measure", "barrier"];

#[pyfunction]
#[pyo3(signature=(dag, label=None))]
pub fn barrier_before_final_measurements(
py: Python,
dag: &mut DAGCircuit,
Expand Down
7 changes: 2 additions & 5 deletions crates/accelerate/src/check_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,7 @@ fn recurse<'py>(
let check_qubits = |qubits: &[Qubit]| -> bool {
match wire_map {
Some(wire_map) => {
let mapped_bits = [
wire_map[qubits[0].0 as usize],
wire_map[qubits[1].0 as usize],
];
let mapped_bits = [wire_map[qubits[0].index()], wire_map[qubits[1].index()]];
edge_set.contains(&[mapped_bits[0].into(), mapped_bits[1].into()])
}
None => edge_set.contains(&[qubits[0].into(), qubits[1].into()]),
Expand All @@ -58,7 +55,7 @@ fn recurse<'py>(
.map(|inner| {
let outer = qubits[inner];
match wire_map {
Some(wire_map) => wire_map[outer.0 as usize],
Some(wire_map) => wire_map[outer.index()],
None => outer,
}
})
Expand Down
1 change: 1 addition & 0 deletions crates/accelerate/src/circuit_library/quantum_volume.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ fn random_unitaries(seed: u64, size: usize) -> impl Iterator<Item = Array2<Compl
const UNITARY_PER_SEED: usize = 50;

#[pyfunction]
#[pyo3(signature=(num_qubits, depth, seed=None))]
pub fn quantum_volume(
py: Python,
num_qubits: u32,
Expand Down
5 changes: 3 additions & 2 deletions crates/accelerate/src/commutation_checker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ impl CommutationChecker {
first_qargs
.iter()
.enumerate()
.map(|(i, q)| (q, Qubit(i as u32))),
.map(|(i, q)| (q, Qubit::new(i))),
);
let mut num_qubits = first_qargs.len() as u32;
for q in second_qargs {
Expand Down Expand Up @@ -574,7 +574,7 @@ fn get_relative_placement(
) -> SmallVec<[Option<Qubit>; 2]> {
let mut qubits_g2: HashMap<&Qubit, Qubit> = HashMap::with_capacity(second_qargs.len());
second_qargs.iter().enumerate().for_each(|(i_g1, q_g1)| {
qubits_g2.insert_unique_unchecked(q_g1, Qubit(i_g1 as u32));
qubits_g2.insert_unique_unchecked(q_g1, Qubit::new(i_g1));
});

first_qargs
Expand Down Expand Up @@ -613,6 +613,7 @@ impl CommutationLibrary {
#[pymethods]
impl CommutationLibrary {
#[new]
#[pyo3(signature=(py_any=None))]
fn new(py_any: Option<Bound<PyAny>>) -> Self {
match py_any {
Some(pyob) => CommutationLibrary {
Expand Down
12 changes: 5 additions & 7 deletions crates/accelerate/src/elide_permutations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ fn run(py: Python, dag: &mut DAGCircuit) -> PyResult<Option<(DAGCircuit, Vec<usi
match (inst.op.name(), inst.condition()) {
("swap", None) => {
let qargs = dag.get_qargs(inst.qubits);
let index0 = qargs[0].0 as usize;
let index1 = qargs[1].0 as usize;
let index0 = qargs[0].index();
let index1 = qargs[1].index();
mapping.swap(index0, index1);
}
("permutation", None) => {
Expand All @@ -55,7 +55,7 @@ fn run(py: Python, dag: &mut DAGCircuit) -> PyResult<Option<(DAGCircuit, Vec<usi
let qindices: Vec<usize> = dag
.get_qargs(inst.qubits)
.iter()
.map(|q| q.0 as usize)
.map(|q| q.index())
.collect();

let remapped_qindices: Vec<usize> = (0..qindices.len())
Expand All @@ -79,9 +79,7 @@ fn run(py: Python, dag: &mut DAGCircuit) -> PyResult<Option<(DAGCircuit, Vec<usi
let cargs = dag.get_cargs(inst.clbits);
let mapped_qargs: Vec<Qubit> = qargs
.iter()
.map(|q| q.0 as usize)
.map(|q| mapping[q])
.map(|q| Qubit(q.try_into().unwrap()))
.map(|q| Qubit::new(mapping[q.index()]))
.collect();

new_dag.apply_operation_back(
Expand All @@ -92,7 +90,7 @@ fn run(py: Python, dag: &mut DAGCircuit) -> PyResult<Option<(DAGCircuit, Vec<usi
inst.params.as_deref().cloned(),
inst.extra_attrs.clone(),
#[cfg(feature = "cache_pygates")]
None,
inst.py_op.get().map(|x| x.clone_ref(py)),
)?;
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/accelerate/src/equivalence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ pub struct GateOper {
}

impl<'py> FromPyObject<'py> for GateOper {
fn extract(ob: &'py PyAny) -> PyResult<Self> {
fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self> {
let op_struct: OperationFromPython = ob.extract()?;
Ok(Self {
operation: op_struct.operation,
Expand Down
3 changes: 2 additions & 1 deletion crates/accelerate/src/error_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ pub struct ErrorMap {
#[pymethods]
impl ErrorMap {
#[new]
#[pyo3(text_signature = "(/, size=None)")]
#[pyo3(signature=(size=None))]
fn new(size: Option<usize>) -> Self {
match size {
Some(size) => ErrorMap {
Expand Down Expand Up @@ -100,6 +100,7 @@ impl ErrorMap {
Ok(self.error_map.contains_key(&key))
}

#[pyo3(signature=(key, default=None))]
fn get(&self, py: Python, key: [PhysicalQubit; 2], default: Option<PyObject>) -> PyObject {
match self.error_map.get(&key).copied() {
Some(val) => val.to_object(py),
Expand Down
17 changes: 10 additions & 7 deletions crates/accelerate/src/euler_one_qubit_decomposer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ pub struct OneQubitGateErrorMap {
#[pymethods]
impl OneQubitGateErrorMap {
#[new]
#[pyo3(signature=(num_qubits=None))]
fn new(num_qubits: Option<usize>) -> Self {
OneQubitGateErrorMap {
error_map: match num_qubits {
Expand Down Expand Up @@ -392,6 +393,7 @@ fn circuit_rr(
}

#[pyfunction]
#[pyo3(signature=(target_basis, theta, phi, lam, phase, simplify, atol=None))]
pub fn generate_circuit(
target_basis: &EulerBasis,
theta: f64,
Expand Down Expand Up @@ -673,7 +675,7 @@ impl Default for EulerBasisSet {
}

#[derive(Clone, Debug, Copy, Eq, Hash, PartialEq)]
#[pyclass(module = "qiskit._accelerate.euler_one_qubit_decomposer")]
#[pyclass(module = "qiskit._accelerate.euler_one_qubit_decomposer", eq, eq_int)]
pub enum EulerBasis {
U3 = 0,
U321 = 1,
Expand Down Expand Up @@ -808,6 +810,7 @@ fn compute_error_str(
}

#[pyfunction]
#[pyo3(signature=(circuit, qubit, error_map=None))]
pub fn compute_error_list(
circuit: Vec<PyRef<DAGOpNode>>,
qubit: usize,
Expand Down Expand Up @@ -1103,7 +1106,7 @@ pub(crate) fn optimize_1q_gates_decomposition(
continue;
}
}
if basis_gates_per_qubit[qubit.0 as usize].is_none() {
if basis_gates_per_qubit[qubit.index()].is_none() {
let basis_gates = match target {
Some(target) => Some(
target
Expand All @@ -1115,11 +1118,11 @@ pub(crate) fn optimize_1q_gates_decomposition(
basis.map(|basis| basis.iter().map(|x| x.as_str()).collect())
}
};
basis_gates_per_qubit[qubit.0 as usize] = basis_gates;
basis_gates_per_qubit[qubit.index()] = basis_gates;
}
let basis_gates = &basis_gates_per_qubit[qubit.0 as usize].as_ref();
let basis_gates = &basis_gates_per_qubit[qubit.index()].as_ref();

let target_basis_set = &mut target_basis_per_qubit[qubit.0 as usize];
let target_basis_set = &mut target_basis_per_qubit[qubit.index()];
if !target_basis_set.initialized() {
match target {
Some(_target) => EULER_BASES
Expand Down Expand Up @@ -1168,7 +1171,7 @@ pub(crate) fn optimize_1q_gates_decomposition(
target_basis_set.remove(EulerBasis::ZSX);
}
}
let target_basis_set = &target_basis_per_qubit[qubit.0 as usize];
let target_basis_set = &target_basis_per_qubit[qubit.index()];
let operator = raw_run
.iter()
.map(|node_index| {
Expand Down Expand Up @@ -1201,7 +1204,7 @@ pub(crate) fn optimize_1q_gates_decomposition(
let sequence = unitary_to_gate_sequence_inner(
aview2(&operator),
target_basis_set,
qubit.0 as usize,
qubit.index(),
None,
true,
None,
Expand Down
6 changes: 3 additions & 3 deletions crates/accelerate/src/gate_direction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ where
let block_ok = if let Some(mapping) = qubit_mapping {
let mapping = inst_qargs // Create a temp mapping for the recursive call
.iter()
.map(|q| mapping[q.0 as usize])
.map(|q| mapping[q.index()])
.collect::<Vec<Qubit>>();

check_gate_direction(py, &inner_dag, gate_complies, Some(&mapping))?
Expand All @@ -128,8 +128,8 @@ where
Some(mapping) => gate_complies(
packed_inst,
&[
mapping[inst_qargs[0].0 as usize],
mapping[inst_qargs[1].0 as usize],
mapping[inst_qargs[0].index()],
mapping[inst_qargs[1].index()],
],
),
None => gate_complies(packed_inst, inst_qargs),
Expand Down
12 changes: 4 additions & 8 deletions crates/accelerate/src/gates_in_basis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ fn any_gate_missing_from_target(dag: &DAGCircuit, target: &Target) -> PyResult<b

if gate.op.control_flow() {
for block in gate.op.blocks() {
let block_qubits = (0..block.num_qubits()).map(|i| Qubit(i.try_into().unwrap()));
let block_qubits = (0..block.num_qubits()).map(Qubit::new);
let inner_wire_map = qargs
.iter()
.zip(block_qubits)
Expand Down Expand Up @@ -74,13 +74,9 @@ fn any_gate_missing_from_target(dag: &DAGCircuit, target: &Target) -> PyResult<b
}

// In the outer DAG, virtual and physical bits are the same thing.
let wire_map: HashMap<Qubit, PhysicalQubit> =
HashMap::from_iter((0..dag.num_qubits()).map(|i| {
(
Qubit(i.try_into().unwrap()),
PhysicalQubit::new(i.try_into().unwrap()),
)
}));
let wire_map: HashMap<Qubit, PhysicalQubit> = HashMap::from_iter(
(0..dag.num_qubits()).map(|i| (Qubit::new(i), PhysicalQubit::new(i.try_into().unwrap()))),
);

// Process the DAG.
for gate in dag.op_nodes(true) {
Expand Down
6 changes: 5 additions & 1 deletion crates/accelerate/src/nlayout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ macro_rules! qubit_newtype {
}

impl pyo3::FromPyObject<'_> for $id {
fn extract(ob: &PyAny) -> PyResult<Self> {
fn extract_bound(ob: &Bound<'_, PyAny>) -> PyResult<Self> {
Ok(Self(ob.extract()?))
}
}
Expand All @@ -60,6 +60,10 @@ macro_rules! qubit_newtype {
fn get_dtype_bound(py: Python<'_>) -> Bound<'_, numpy::PyArrayDescr> {
u32::get_dtype_bound(py)
}

fn clone_ref(&self, _py: Python<'_>) -> Self {
*self
}
}
};
}
Expand Down
2 changes: 2 additions & 0 deletions crates/accelerate/src/results/marginalization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ fn marginalize<T: std::ops::AddAssign + Copy>(
}

#[pyfunction]
#[pyo3(signature=(counts, indices=None))]
pub fn marginal_counts(
counts: HashMap<String, u64>,
indices: Option<Vec<usize>>,
Expand All @@ -70,6 +71,7 @@ pub fn marginal_counts(
}

#[pyfunction]
#[pyo3(signature=(counts, indices=None))]
pub fn marginal_distribution(
counts: HashMap<String, f64>,
indices: Option<Vec<usize>>,
Expand Down
2 changes: 1 addition & 1 deletion crates/accelerate/src/sabre/heuristic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use pyo3::Python;

/// Affect the dynamic scaling of the weight of node-set-based heuristics (basic and lookahead).
#[pyclass]
#[pyo3(module = "qiskit._accelerate.sabre", frozen)]
#[pyo3(module = "qiskit._accelerate.sabre", frozen, eq)]
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum SetScaling {
/// No dynamic scaling of the weight.
Expand Down
2 changes: 1 addition & 1 deletion crates/accelerate/src/sabre/neighbor_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ impl std::ops::Index<PhysicalQubit> for NeighborTable {
#[pymethods]
impl NeighborTable {
#[new]
#[pyo3(text_signature = "(/, adjacency_matrix=None)")]
#[pyo3(signature = (adjacency_matrix=None))]
pub fn new(adjacency_matrix: Option<PyReadonlyArray2<f64>>) -> PyResult<Self> {
let run_in_parallel = getenv_use_multiple_threads();
let neighbors = match adjacency_matrix {
Expand Down
1 change: 1 addition & 0 deletions crates/accelerate/src/sabre/route.rs
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,7 @@ impl<'a, 'b> RoutingState<'a, 'b> {
/// logical position of the qubit that began in position `i`.
#[pyfunction]
#[allow(clippy::too_many_arguments)]
#[pyo3(signature=(dag, neighbor_table, distance_matrix, heuristic, initial_layout, num_trials, seed=None, run_in_parallel=None))]
pub fn sabre_routing(
py: Python,
dag: &SabreDAG,
Expand Down
2 changes: 1 addition & 1 deletion crates/accelerate/src/stochastic_swap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ fn swap_trial(
/// will be ``(None, None, max int)``.
#[pyfunction]
#[pyo3(
text_signature = "(num_trials, num_qubits, int_layout, int_qubit_subset, int_gates, cdist, cdist2, edges, /, seed=None)"
signature = (num_trials, num_qubits, int_layout, int_qubit_subset, int_gates, cdist, cdist2, edges, seed=None)
)]
pub fn swap_trials(
num_trials: u64,
Expand Down
Loading

0 comments on commit b87e528

Please sign in to comment.