From 1e634df711adbaf59daa5c7ac6a9e8211b32e5b0 Mon Sep 17 00:00:00 2001 From: Jake Lishman Date: Fri, 14 Feb 2025 14:52:24 +0000 Subject: [PATCH] Bump `rand` to 0.9 and associated crates (#13806) * Bump `rand` to 0.9 and associated crates This is a breaking API change, but our exposure is mostly just to some minor renames. Unfortunately the whole ecosystem hasn't migrated yet, so we're still compiling in multiple versions of `rand`, but with any luck, bumping hashbrown and dropping faer will help. * Fix random tests for new seeded behaviour * Fix mistaken test * Fix lint * Choose seed to match visual reference * Fix randomisation change in new test --- Cargo.lock | 142 +++++++++++++++--- crates/accelerate/Cargo.toml | 6 +- crates/accelerate/src/circuit_library/iqp.rs | 6 +- .../src/circuit_library/quantum_volume.rs | 4 +- crates/accelerate/src/sabre/layout.rs | 4 +- crates/accelerate/src/sabre/route.rs | 4 +- crates/accelerate/src/stochastic_swap.rs | 4 +- .../src/synthesis/clifford/random_clifford.rs | 12 +- crates/accelerate/src/synthesis/linear/lnn.rs | 4 +- .../accelerate/src/synthesis/linear/utils.rs | 4 +- crates/accelerate/src/twirling.rs | 2 +- test/python/compiler/test_compiler.py | 11 +- test/python/compiler/test_transpiler.py | 2 +- .../transpiler/test_preset_passmanagers.py | 66 +------- test/python/transpiler/test_sabre_layout.py | 28 ++-- test/python/transpiler/test_sabre_swap.py | 6 +- .../transpiler/test_swap_strategy_router.py | 7 +- .../transpiler/test_transpile_layout.py | 96 +----------- .../circuit/test_circuit_matplotlib_drawer.py | 2 +- 19 files changed, 185 insertions(+), 225 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1d757fd122b6..e7df450059b5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,7 +8,7 @@ version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" dependencies = [ - "getrandom", + "getrandom 0.2.15", "once_cell", "version_check", ] @@ -20,10 +20,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", - "getrandom", + "getrandom 0.2.15", "once_cell", "version_check", - "zerocopy", + "zerocopy 0.7.35", ] [[package]] @@ -366,8 +366,8 @@ dependencies = [ "num-complex", "num-traits", "paste", - "rand", - "rand_distr", + "rand 0.8.5", + "rand_distr 0.4.3", "rayon", "reborrow", "serde", @@ -542,7 +542,19 @@ checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.13.3+wasi-0.2.2", + "windows-targets 0.52.6", ] [[package]] @@ -863,7 +875,7 @@ checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ "bytemuck", "num-traits", - "rand", + "rand 0.8.5", ] [[package]] @@ -1056,7 +1068,7 @@ version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" dependencies = [ - "zerocopy", + "zerocopy 0.7.35", ] [[package]] @@ -1245,9 +1257,9 @@ dependencies = [ "pulp 0.21.4", "pyo3", "qiskit-circuit", - "rand", - "rand_distr", - "rand_pcg", + "rand 0.9.0", + "rand_distr 0.5.0", + "rand_pcg 0.9.0", "rayon", "rustiq-core", "rustworkx-core", @@ -1331,8 +1343,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.0", + "zerocopy 0.8.17", ] [[package]] @@ -1342,7 +1365,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.0", ] [[package]] @@ -1351,7 +1384,17 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.15", +] + +[[package]] +name = "rand_core" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b08f3c9802962f7e1b25113931d94f43ed9725bebc59db9d0c3e9a23b67e15ff" +dependencies = [ + "getrandom 0.3.1", + "zerocopy 0.8.17", ] [[package]] @@ -1361,7 +1404,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" dependencies = [ "num-traits", - "rand", + "rand 0.8.5", +] + +[[package]] +name = "rand_distr" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddc3b5afe4c995c44540865b8ca5c52e6a59fa362da96c5d30886930ddc8da1c" +dependencies = [ + "num-traits", + "rand 0.9.0", ] [[package]] @@ -1370,7 +1423,16 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59cad018caf63deb318e5a4586d99a24424a364f40f1e5778c29aca23f4fc73e" dependencies = [ - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_pcg" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b48ac3f7ffaab7fac4d2376632268aa5f89abdb55f7ebf8f4d11fffccb2320f7" +dependencies = [ + "rand_core 0.9.0", ] [[package]] @@ -1487,7 +1549,7 @@ checksum = "666b580cb45b60a39f5a17b284bbe8343cfcd67929931729b4afee19ec94d308" dependencies = [ "itertools 0.10.5", "petgraph", - "rand", + "rand 0.8.5", ] [[package]] @@ -1510,8 +1572,8 @@ dependencies = [ "num-traits", "petgraph", "priority-queue", - "rand", - "rand_pcg", + "rand 0.8.5", + "rand_pcg 0.3.1", "rayon", "rayon-cond", ] @@ -1757,6 +1819,15 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasi" +version = "0.13.3+wasi-0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +dependencies = [ + "wit-bindgen-rt", +] + [[package]] name = "wide" version = "0.7.32" @@ -1924,6 +1995,15 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "wit-bindgen-rt" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +dependencies = [ + "bitflags 2.8.0", +] + [[package]] name = "xshell" version = "0.2.7" @@ -1952,7 +2032,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ "byteorder", - "zerocopy-derive", + "zerocopy-derive 0.7.35", +] + +[[package]] +name = "zerocopy" +version = "0.8.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa91407dacce3a68c56de03abe2760159582b846c6a4acd2f456618087f12713" +dependencies = [ + "zerocopy-derive 0.8.17", ] [[package]] @@ -1965,3 +2054,14 @@ dependencies = [ "quote", "syn 2.0.96", ] + +[[package]] +name = "zerocopy-derive" +version = "0.8.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06718a168365cad3d5ff0bb133aad346959a2074bd4a85c121255a11304a8626" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] diff --git a/crates/accelerate/Cargo.toml b/crates/accelerate/Cargo.toml index 8058139c4f2c..e64131a762bf 100644 --- a/crates/accelerate/Cargo.toml +++ b/crates/accelerate/Cargo.toml @@ -15,9 +15,9 @@ workspace = true [dependencies] rayon.workspace = true numpy.workspace = true -rand = "0.8" -rand_pcg = "0.3" -rand_distr = "0.4.3" +rand = "0.9" +rand_pcg = "0.9" +rand_distr = "0.5" ahash.workspace = true num-traits = "0.2" num-complex.workspace = true diff --git a/crates/accelerate/src/circuit_library/iqp.rs b/crates/accelerate/src/circuit_library/iqp.rs index 4cb931f8c228..d55e74754722 100644 --- a/crates/accelerate/src/circuit_library/iqp.rs +++ b/crates/accelerate/src/circuit_library/iqp.rs @@ -80,14 +80,14 @@ fn generate_random_interactions(num_qubits: u32, seed: Option) -> Array2 Pcg64Mcg::seed_from_u64(seed), - None => Pcg64Mcg::from_entropy(), + None => Pcg64Mcg::from_os_rng(), }; let mut mat = Array2::zeros((num_qubits, num_qubits)); for i in 0..num_qubits { - mat[[i, i]] = rng.gen_range(0..8) as i64; + mat[[i, i]] = rng.random_range(0..8) as i64; for j in 0..i { - mat[[i, j]] = rng.gen_range(0..8) as i64; + mat[[i, j]] = rng.random_range(0..8) as i64; mat[[j, i]] = mat[[i, j]]; } } diff --git a/crates/accelerate/src/circuit_library/quantum_volume.rs b/crates/accelerate/src/circuit_library/quantum_volume.rs index 04b4fa3d4a0c..4c7899a72af1 100644 --- a/crates/accelerate/src/circuit_library/quantum_volume.rs +++ b/crates/accelerate/src/circuit_library/quantum_volume.rs @@ -125,9 +125,9 @@ pub fn quantum_volume( } let mut outer_rng = match seed { Some(seed) => Pcg64Mcg::seed_from_u64(seed), - None => Pcg64Mcg::from_entropy(), + None => Pcg64Mcg::from_os_rng(), }; - let seed_vec: Vec = rand::distributions::Standard + let seed_vec: Vec = rand::distr::StandardUniform .sample_iter(&mut outer_rng) .take(num_unitaries) .collect(); diff --git a/crates/accelerate/src/sabre/layout.rs b/crates/accelerate/src/sabre/layout.rs index cc4ab7ff19f7..d9f6fb3c938b 100644 --- a/crates/accelerate/src/sabre/layout.rs +++ b/crates/accelerate/src/sabre/layout.rs @@ -128,10 +128,10 @@ pub fn sabre_layout_and_routing( } let outer_rng = match seed { Some(seed) => Pcg64Mcg::seed_from_u64(seed), - None => Pcg64Mcg::from_entropy(), + None => Pcg64Mcg::from_os_rng(), }; let seed_vec: Vec = outer_rng - .sample_iter(&rand::distributions::Standard) + .sample_iter(&rand::distr::StandardUniform) .take(starting_layouts.len()) .collect(); let res = if run_in_parallel && starting_layouts.len() > 1 { diff --git a/crates/accelerate/src/sabre/route.rs b/crates/accelerate/src/sabre/route.rs index a1ec511f1aad..58ae257e73fc 100644 --- a/crates/accelerate/src/sabre/route.rs +++ b/crates/accelerate/src/sabre/route.rs @@ -502,10 +502,10 @@ pub fn swap_map( }; let outer_rng = match seed { Some(seed) => Pcg64Mcg::seed_from_u64(seed), - None => Pcg64Mcg::from_entropy(), + None => Pcg64Mcg::from_os_rng(), }; let seed_vec: Vec = outer_rng - .sample_iter(&rand::distributions::Standard) + .sample_iter(&rand::distr::StandardUniform) .take(num_trials) .collect(); if run_in_parallel { diff --git a/crates/accelerate/src/stochastic_swap.rs b/crates/accelerate/src/stochastic_swap.rs index a102d4525771..91568c863b44 100644 --- a/crates/accelerate/src/stochastic_swap.rs +++ b/crates/accelerate/src/stochastic_swap.rs @@ -260,10 +260,10 @@ pub fn swap_trials( RwLock::new(&mut best_possible); let outer_rng: Pcg64Mcg = match seed { Some(seed) => Pcg64Mcg::seed_from_u64(seed), - None => Pcg64Mcg::from_entropy(), + None => Pcg64Mcg::from_os_rng(), }; let seed_vec: Vec = outer_rng - .sample_iter(&rand::distributions::Standard) + .sample_iter(&rand::distr::StandardUniform) .take(num_trials as usize) .collect(); // Run in parallel only if we're not already in a multiprocessing context diff --git a/crates/accelerate/src/synthesis/clifford/random_clifford.rs b/crates/accelerate/src/synthesis/clifford/random_clifford.rs index 57531efcea55..21478314819d 100644 --- a/crates/accelerate/src/synthesis/clifford/random_clifford.rs +++ b/crates/accelerate/src/synthesis/clifford/random_clifford.rs @@ -29,7 +29,7 @@ fn sample_qmallows(n: usize, rng: &mut Pcg64Mcg) -> (Array1, Array1 for i in 0..n { let m = n - i; let eps: f64 = 4f64.powi(-(m as i32)); - let r: f64 = rng.gen(); + let r: f64 = rng.random(); let index: usize = -((r + (1f64 - r) * eps).log2().ceil() as isize) as usize; had[i] = index < m; let k = if index < m { index } else { 2 * m - index - 1 }; @@ -44,7 +44,7 @@ fn fill_tril(mut mat: ArrayViewMut2, rng: &mut Pcg64Mcg, symmetric: bool) let n = mat.shape()[0]; for i in 0..n { for j in 0..i { - mat[[i, j]] = rng.gen(); + mat[[i, j]] = rng.random(); if symmetric { mat[[j, i]] = mat[[i, j]]; } @@ -67,20 +67,20 @@ fn inverse_tril(mat: ArrayView2) -> Array2 { pub fn random_clifford_tableau_inner(num_qubits: usize, seed: Option) -> Array2 { let mut rng = match seed { Some(seed) => Pcg64Mcg::seed_from_u64(seed), - None => Pcg64Mcg::from_entropy(), + None => Pcg64Mcg::from_os_rng(), }; let (had, perm) = sample_qmallows(num_qubits, &mut rng); let mut gamma1: Array2 = Array2::from_elem((num_qubits, num_qubits), false); for i in 0..num_qubits { - gamma1[[i, i]] = rng.gen(); + gamma1[[i, i]] = rng.random(); } fill_tril(gamma1.view_mut(), &mut rng, true); let mut gamma2: Array2 = Array2::from_elem((num_qubits, num_qubits), false); for i in 0..num_qubits { - gamma2[[i, i]] = rng.gen(); + gamma2[[i, i]] = rng.random(); } fill_tril(gamma2.view_mut(), &mut rng, true); @@ -149,7 +149,7 @@ pub fn random_clifford_tableau_inner(num_qubits: usize, seed: Option) -> Ar let random_symplectic_mat = binary_matmul_inner(table1.view(), table.view()).unwrap(); // Generate random phases - let random_phases: Array2 = Array2::from_shape_fn((2 * num_qubits, 1), |_| rng.gen()); + let random_phases: Array2 = Array2::from_shape_fn((2 * num_qubits, 1), |_| rng.random()); let random_tableau: Array2 = concatenate( Axis(1), diff --git a/crates/accelerate/src/synthesis/linear/lnn.rs b/crates/accelerate/src/synthesis/linear/lnn.rs index edb1ae0913a2..eaec1faf1bf7 100644 --- a/crates/accelerate/src/synthesis/linear/lnn.rs +++ b/crates/accelerate/src/synthesis/linear/lnn.rs @@ -255,10 +255,10 @@ fn _north_west_to_identity(n: usize, mut mat: ArrayViewMut2) -> Instructio /// [1, 1, 1, 0] /// [0, 1, 0, 0] /// [1, 0, 0, 0]] - +/// /// According to [1] the synthesis is done on the inverse matrix /// so the matrix mat is inverted at this step - +/// /// References: /// [1]: Kutin, S., Moulton, D. P., Smithline, L. (2007). /// Computation at a Distance. diff --git a/crates/accelerate/src/synthesis/linear/utils.rs b/crates/accelerate/src/synthesis/linear/utils.rs index c620acb5eec0..b4d52692abf1 100644 --- a/crates/accelerate/src/synthesis/linear/utils.rs +++ b/crates/accelerate/src/synthesis/linear/utils.rs @@ -223,14 +223,14 @@ pub fn _row_sum(row_1: ArrayView1, row_2: ArrayView1) -> Result) -> Array2 { let mut rng = match seed { Some(seed) => Pcg64Mcg::seed_from_u64(seed), - None => Pcg64Mcg::from_entropy(), + None => Pcg64Mcg::from_os_rng(), }; let mut matrix = Array2::from_elem((num_qubits, num_qubits), false); loop { for value in matrix.iter_mut() { - *value = rng.gen_bool(0.5); + *value = rng.random_bool(0.5); } let rank = compute_rank_inner(matrix.view()); diff --git a/crates/accelerate/src/twirling.rs b/crates/accelerate/src/twirling.rs index 480b3924ea76..334f8fa555b2 100644 --- a/crates/accelerate/src/twirling.rs +++ b/crates/accelerate/src/twirling.rs @@ -398,7 +398,7 @@ pub(crate) fn twirl_circuit( ) -> PyResult> { let mut rng = match seed { Some(seed) => Pcg64Mcg::seed_from_u64(seed), - None => Pcg64Mcg::from_entropy(), + None => Pcg64Mcg::from_os_rng(), }; let twirling_mask: u8 = match twirled_gate { Some(gates) => { diff --git a/test/python/compiler/test_compiler.py b/test/python/compiler/test_compiler.py index 4b16e2ee45ab..455d6b81f1b7 100644 --- a/test/python/compiler/test_compiler.py +++ b/test/python/compiler/test_compiler.py @@ -16,7 +16,7 @@ import unittest from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit -from qiskit.transpiler import PassManager +from qiskit.transpiler import PassManager, CouplingMap from qiskit.circuit.library import U1Gate, U2Gate from qiskit.compiler import transpile from qiskit.providers.basic_provider import BasicSimulator @@ -172,13 +172,12 @@ def test_example_swap_bits(self): qc.measure(qr1[j], ans[j + n]) # First version: no mapping result = backend.run( - transpile(qc, backend), coupling_map=None, shots=1024, seed_simulator=14 + transpile(qc, backend, coupling_map=None), shots=1024, seed_simulator=14 ).result() self.assertEqual(result.get_counts(qc), {"010000": 1024}) # Second version: map to coupling graph result = backend.run( transpile(qc, backend, coupling_map=coupling_map), - coupling_map=coupling_map, shots=1024, seed_simulator=14, ).result() @@ -364,7 +363,6 @@ def test_grovers_circuit(self): self.backend, coupling_map=coupling_map, ), - coupling_map=coupling_map, seed_simulator=self.seed_simulator, shots=shots, ) @@ -416,8 +414,8 @@ def test_math_domain_error(self): transpile( circ, backend=self.backend, + coupling_map=coupling_map, ), - coupling_map=coupling_map, seed_simulator=self.seed_simulator, shots=shots, ) @@ -430,7 +428,8 @@ def test_random_parameter_circuit(self): """Run a circuit with randomly generated parameters.""" qasm_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "qasm") circ = QuantumCircuit.from_qasm_file(os.path.join(qasm_dir, "random_n5_d5.qasm")) - coupling_map = [[0, 1], [1, 2], [2, 3], [3, 4]] + coupling_map = CouplingMap([[0, 1], [1, 2], [2, 3], [3, 4]]) + coupling_map.make_symmetric() shots = 1024 qobj = self.backend.run( transpile(circ, backend=self.backend, coupling_map=coupling_map, seed_transpiler=42), diff --git a/test/python/compiler/test_transpiler.py b/test/python/compiler/test_transpiler.py index f1f691da5a89..a0ea0dc118da 100644 --- a/test/python/compiler/test_transpiler.py +++ b/test/python/compiler/test_transpiler.py @@ -2590,7 +2590,7 @@ def callback(**kwargs): tqc = transpile(qc, backend=backend, seed_transpiler=4242, callback=callback) self.assertTrue(vf2_post_layout_called) - self.assertEqual([0, 2, 1], _get_index_layout(tqc, qubits)) + self.assertEqual([2, 1, 0], _get_index_layout(tqc, qubits)) class StreamHandlerRaiseException(StreamHandler): diff --git a/test/python/transpiler/test_preset_passmanagers.py b/test/python/transpiler/test_preset_passmanagers.py index 5b23e777fac4..d26df3a24f66 100644 --- a/test/python/transpiler/test_preset_passmanagers.py +++ b/test/python/transpiler/test_preset_passmanagers.py @@ -976,69 +976,17 @@ def test_layout_tokyo_fully_connected_cx(self, level): for qubit_control in qr: if qubit_control != qubit_target: qc.cx(qubit_control, qubit_target) - - ancilla = QuantumRegister(15, "ancilla") - - trivial_layout = { - 0: qr[0], - 1: qr[1], - 2: qr[2], - 3: qr[3], - 4: qr[4], - 5: ancilla[0], - 6: ancilla[1], - 7: ancilla[2], - 8: ancilla[3], - 9: ancilla[4], - 10: ancilla[5], - 11: ancilla[6], - 12: ancilla[7], - 13: ancilla[8], - 14: ancilla[9], - 15: ancilla[10], - 16: ancilla[11], - 17: ancilla[12], - 18: ancilla[13], - 19: ancilla[14], - } - - sabre_layout = { - 0: ancilla[0], - 1: ancilla[1], - 2: ancilla[2], - 3: ancilla[3], - 4: ancilla[4], - 5: qr[1], - 6: qr[0], - 7: qr[4], - 8: ancilla[6], - 9: ancilla[7], - 10: qr[2], - 11: qr[3], - 12: ancilla[5], - 13: ancilla[8], - 14: ancilla[9], - 15: ancilla[10], - 16: ancilla[11], - 17: ancilla[12], - 18: ancilla[13], - 19: ancilla[14], - } - - expected_layout_level0 = trivial_layout - expected_layout_level1 = sabre_layout - expected_layout_level2 = sabre_layout - expected_layout_level3 = sabre_layout - expected_layouts = [ - expected_layout_level0, - expected_layout_level1, - expected_layout_level2, - expected_layout_level3, + [0, 1, 2, 3, 4], + [6, 5, 11, 10, 2], + [6, 5, 2, 11, 10], + [6, 5, 2, 11, 10], ] backend = GenericBackendV2(num_qubits=20, coupling_map=TOKYO_CMAP, seed=42) result = transpile(qc, backend, optimization_level=level, seed_transpiler=42) - self.assertEqual(result._layout.initial_layout._p2v, expected_layouts[level]) + self.assertEqual( + result.layout.initial_index_layout(filter_ancillas=True), expected_layouts[level] + ) @data(0, 1, 2, 3) def test_all_levels_use_trivial_if_perfect(self, level): diff --git a/test/python/transpiler/test_sabre_layout.py b/test/python/transpiler/test_sabre_layout.py index e189355d0b98..fdec5b98be85 100644 --- a/test/python/transpiler/test_sabre_layout.py +++ b/test/python/transpiler/test_sabre_layout.py @@ -66,7 +66,7 @@ def test_5q_circuit_20q_coupling(self): pass_.run(dag) layout = pass_.property_set["layout"] - self.assertEqual([layout[q] for q in circuit.qubits], [11, 10, 16, 5, 17]) + self.assertEqual([layout[q] for q in circuit.qubits], [3, 6, 8, 7, 12]) def test_6q_circuit_20q_coupling(self): """Test finds layout for 6q circuit on 20q device.""" @@ -98,7 +98,7 @@ def test_6q_circuit_20q_coupling(self): pass_.run(dag) layout = pass_.property_set["layout"] - self.assertEqual([layout[q] for q in circuit.qubits], [7, 8, 12, 6, 11, 13]) + self.assertEqual([layout[q] for q in circuit.qubits], [7, 8, 11, 12, 13, 6]) def test_6q_circuit_20q_coupling_with_partial(self): """Test finds layout for 6q circuit on 20q device.""" @@ -166,7 +166,7 @@ def test_6q_circuit_20q_coupling_with_target(self): pass_.run(dag) layout = pass_.property_set["layout"] - self.assertEqual([layout[q] for q in circuit.qubits], [7, 8, 12, 6, 11, 13]) + self.assertEqual([layout[q] for q in circuit.qubits], [7, 8, 11, 12, 13, 6]) def test_layout_with_classical_bits(self): """Test sabre layout with classical bits recreate from issue #8635.""" @@ -207,7 +207,7 @@ def test_layout_with_classical_bits(self): self.assertIsInstance(res, QuantumCircuit) layout = res._layout.initial_layout self.assertEqual( - [layout[q] for q in qc.qubits], [2, 0, 5, 1, 7, 3, 14, 6, 9, 8, 10, 11, 4, 12] + [layout[q] for q in qc.qubits], [14, 12, 5, 13, 26, 11, 19, 25, 18, 8, 17, 16, 9, 4] ) # pylint: disable=line-too-long @@ -271,7 +271,7 @@ def test_layout_many_search_trials(self): self.assertIsInstance(res, QuantumCircuit) layout = res._layout.initial_layout self.assertEqual( - [layout[q] for q in qc.qubits], [0, 12, 7, 3, 6, 11, 1, 10, 4, 9, 2, 5, 13, 8] + [layout[q] for q in qc.qubits], [0, 12, 7, 8, 6, 3, 1, 10, 4, 9, 2, 11, 13, 5] ) def test_support_var_with_rust_fastpath(self): @@ -291,7 +291,7 @@ def test_support_var_with_rust_fastpath(self): out = SabreLayout(CouplingMap.from_line(8), seed=0, swap_trials=2, layout_trials=2)(qc) self.assertIsInstance(out, QuantumCircuit) - self.assertEqual(out.layout.initial_index_layout(), [4, 5, 6, 3, 2, 0, 1, 7]) + self.assertEqual(out.layout.initial_index_layout(), [6, 5, 4, 2, 3, 0, 1, 7]) def test_support_var_with_explicit_routing_pass(self): """Test that the logic works if an explicit routing pass is given.""" @@ -372,7 +372,7 @@ def test_dual_ghz(self): ) layout_routing_pass(qc) layout = layout_routing_pass.property_set["layout"] - self.assertEqual([layout[q] for q in qc.qubits], [3, 1, 2, 5, 4, 6, 7, 8]) + self.assertEqual([layout[q] for q in qc.qubits], [3, 2, 1, 5, 4, 7, 6, 8]) def test_dual_ghz_with_wide_barrier(self): """Test a basic example with 2 circuit components and 2 cmap components.""" @@ -391,7 +391,7 @@ def test_dual_ghz_with_wide_barrier(self): ) layout_routing_pass(qc) layout = layout_routing_pass.property_set["layout"] - self.assertEqual([layout[q] for q in qc.qubits], [3, 1, 2, 5, 4, 6, 7, 8]) + self.assertEqual([layout[q] for q in qc.qubits], [3, 2, 1, 5, 4, 7, 6, 8]) def test_dual_ghz_with_intermediate_barriers(self): """Test dual ghz circuit with intermediate barriers local to each component.""" @@ -412,7 +412,7 @@ def test_dual_ghz_with_intermediate_barriers(self): ) layout_routing_pass(qc) layout = layout_routing_pass.property_set["layout"] - self.assertEqual([layout[q] for q in qc.qubits], [3, 1, 2, 5, 4, 6, 7, 8]) + self.assertEqual([layout[q] for q in qc.qubits], [3, 2, 1, 5, 4, 7, 6, 8]) def test_dual_ghz_with_intermediate_spanning_barriers(self): """Test dual ghz circuit with barrier in the middle across components.""" @@ -432,7 +432,7 @@ def test_dual_ghz_with_intermediate_spanning_barriers(self): ) layout_routing_pass(qc) layout = layout_routing_pass.property_set["layout"] - self.assertEqual([layout[q] for q in qc.qubits], [3, 1, 2, 5, 4, 6, 7, 8]) + self.assertEqual([layout[q] for q in qc.qubits], [3, 2, 1, 5, 4, 7, 6, 8]) def test_too_large_components(self): """Assert trying to run a circuit with too large a connected component raises.""" @@ -468,7 +468,7 @@ def test_with_partial_layout(self): ) pm.run(qc) layout = pm.property_set["layout"] - self.assertEqual([layout[q] for q in qc.qubits], [3, 1, 2, 5, 4, 6, 7, 8]) + self.assertEqual([layout[q] for q in qc.qubits], [3, 2, 1, 5, 4, 7, 6, 8]) def test_dag_fits_in_one_component(self): """Test that the output is valid if the DAG all fits in a single component of a disjoint @@ -482,8 +482,8 @@ def test_dag_fits_in_one_component(self): layout_routing_pass = SabreLayout(disjoint, seed=2025_02_12, swap_trials=1, layout_trials=1) out = layout_routing_pass(qc) self.assertEqual(len(out.layout.initial_layout), len(out.layout.final_layout)) - self.assertEqual(out.layout.initial_index_layout(filter_ancillas=False), [1, 0, 2, 3, 4, 5]) - self.assertEqual(out.layout.final_index_layout(filter_ancillas=False), [2, 0, 1, 3, 4, 5]) + self.assertEqual(out.layout.initial_index_layout(filter_ancillas=False), [1, 2, 0, 3, 4, 5]) + self.assertEqual(out.layout.final_index_layout(filter_ancillas=False), [0, 2, 1, 3, 4, 5]) class TestSabrePreLayout(QiskitTestCase): @@ -523,7 +523,7 @@ def test_integration_with_pass_manager(self): qct_initial_layout = qct.layout.initial_layout self.assertEqual( [qct_initial_layout[q] for q in self.circuit.qubits], - [3, 8, 7, 12, 13, 14, 18, 17, 16, 11, 10, 5, 6, 1, 2, 4], + [17, 16, 11, 12, 7, 6, 5, 1, 2, 3, 8, 9, 14, 13, 19, 18], ) diff --git a/test/python/transpiler/test_sabre_swap.py b/test/python/transpiler/test_sabre_swap.py index 23a54433ed62..fbc70fa362f9 100644 --- a/test/python/transpiler/test_sabre_swap.py +++ b/test/python/transpiler/test_sabre_swap.py @@ -757,11 +757,11 @@ def test_pre_intra_post_if_else(self): efalse_body.swap(3, 4) expected.if_else((creg[0], 0), etrue_body, efalse_body, qreg, creg[[0]]) - expected.swap(1, 2) expected.h(3) - expected.cx(3, 2) + expected.swap(2, 3) + expected.cx(2, 1) expected.barrier() - expected.measure(qreg[[2, 0, 1, 3, 4]], creg) + expected.measure(qreg[[1, 0, 3, 2, 4]], creg) self.assertEqual(dag_to_circuit(cdag), expected) def test_if_expr(self): diff --git a/test/python/transpiler/test_swap_strategy_router.py b/test/python/transpiler/test_swap_strategy_router.py index 0a800bdad642..08e9159ee6d0 100644 --- a/test/python/transpiler/test_swap_strategy_router.py +++ b/test/python/transpiler/test_swap_strategy_router.py @@ -577,9 +577,6 @@ def test_permutation_tracking(self): op = SparsePauliOp.from_list([("IZZI", 1), ("ZIIZ", 2), ("ZIZI", 3)]) circ = QAOAAnsatz(op, reps=2, mixer_operator=mixer) - expected_swap_permutation = [3, 1, 2, 0] - expected_full_permutation = [1, 3, 2, 0] - cmap = CouplingMap(couplinglist=[(0, 1), (1, 2), (2, 3)]) swap_strat = SwapStrategy(cmap, swap_layers=[[(0, 1), (2, 3)], [(1, 2)]]) @@ -600,8 +597,8 @@ def test_permutation_tracking(self): pm.pre_routing = swap_pm full = pm.run(circ.decompose()) - self.assertEqual(swapped.layout.routing_permutation(), expected_swap_permutation) - self.assertEqual(full.layout.routing_permutation(), expected_full_permutation) + self.assertEqual(swapped.layout.routing_permutation(), [3, 1, 2, 0]) + self.assertEqual(full.layout.routing_permutation(), [0, 1, 2, 3]) class TestSwapRouterExceptions(QiskitTestCase): diff --git a/test/python/transpiler/test_transpile_layout.py b/test/python/transpiler/test_transpile_layout.py index 01e06b57fee4..778ed8d467ca 100644 --- a/test/python/transpiler/test_transpile_layout.py +++ b/test/python/transpiler/test_transpile_layout.py @@ -51,29 +51,8 @@ def test_final_index_layout_full_path_with_ancilla(self): qc.cx(0, 2) cmap = CouplingMap.from_line(10, bidirectional=False) tqc = transpile(qc, coupling_map=cmap, initial_layout=[9, 4, 0], seed_transpiler=42) - # tqc: - # q_2 -> 0 ──X───────────────────────────────────────────────── - # │ - # ancilla_0 -> 1 ──X───X───────────────────────────────────────────── - # │ - # ancilla_1 -> 2 ──────X──X────────────────────────────────────────── - # │ ┌───┐ ┌───┐ - # ancilla_2 -> 3 ─────────X─┤ H ├────────────────────────────■──┤ H ├ - # ┌───┐ └───┘ ┌───┐ ┌───┐┌─┴─┐├───┤ - # q_1 -> 4 ┤ H ├─────────────────────■──┤ H ├─X─┤ H ├┤ X ├┤ H ├ - # └───┘ ┌───┐┌─┴─┐├───┤ │ └───┘└───┘└───┘ - # ancilla_3 -> 5 ─────────────────X─┤ H ├┤ X ├┤ H ├─X──────────────── - # │ └───┘└───┘└───┘ - # ancilla_4 -> 6 ─────────────X───X────────────────────────────────── - # │ - # ancilla_5 -> 7 ─────────X───X────────────────────────────────────── - # │ - # ancilla_6 -> 8 ──────X──X────────────────────────────────────────── - # ┌───┐ │ - # q_0 -> 9 ┤ H ├─X───────────────────────────────────────────── - # └───┘ res = tqc.layout.final_index_layout() - self.assertEqual(res, [4, 5, 3]) + self.assertEqual(res, [3, 5, 2]) def test_final_index_layout_full_path_with_ancilla_no_filter(self): qc = QuantumCircuit(3) @@ -82,29 +61,8 @@ def test_final_index_layout_full_path_with_ancilla_no_filter(self): qc.cx(0, 2) cmap = CouplingMap.from_line(10, bidirectional=False) tqc = transpile(qc, coupling_map=cmap, initial_layout=[9, 4, 0], seed_transpiler=42) - # tqc: - # q_2 -> 0 ──X───────────────────────────────────────────────── - # │ - # ancilla_0 -> 1 ──X───X───────────────────────────────────────────── - # │ - # ancilla_1 -> 2 ──────X──X────────────────────────────────────────── - # │ ┌───┐ ┌───┐ - # ancilla_2 -> 3 ─────────X─┤ H ├────────────────────────────■──┤ H ├ - # ┌───┐ └───┘ ┌───┐ ┌───┐┌─┴─┐├───┤ - # q_1 -> 4 ┤ H ├─────────────────────■──┤ H ├─X─┤ H ├┤ X ├┤ H ├ - # └───┘ ┌───┐┌─┴─┐├───┤ │ └───┘└───┘└───┘ - # ancilla_3 -> 5 ─────────────────X─┤ H ├┤ X ├┤ H ├─X──────────────── - # │ └───┘└───┘└───┘ - # ancilla_4 -> 6 ─────────────X───X────────────────────────────────── - # │ - # ancilla_5 -> 7 ─────────X───X────────────────────────────────────── - # │ - # ancilla_6 -> 8 ──────X──X────────────────────────────────────────── - # ┌───┐ │ - # q_0 -> 9 ┤ H ├─X───────────────────────────────────────────── - # └───┘ res = tqc.layout.final_index_layout(filter_ancillas=False) - self.assertEqual(res, [4, 5, 3, 0, 1, 2, 6, 7, 8, 9]) + self.assertEqual(res, [3, 5, 2, 0, 1, 4, 6, 7, 8, 9]) def test_final_virtual_layout_full_path_with_ancilla(self): qc = QuantumCircuit(3) @@ -113,29 +71,8 @@ def test_final_virtual_layout_full_path_with_ancilla(self): qc.cx(0, 2) cmap = CouplingMap.from_line(10, bidirectional=False) tqc = transpile(qc, coupling_map=cmap, initial_layout=[9, 4, 0], seed_transpiler=42) - # tqc: - # q_2 -> 0 ──X───────────────────────────────────────────────── - # │ - # ancilla_0 -> 1 ──X───X───────────────────────────────────────────── - # │ - # ancilla_1 -> 2 ──────X──X────────────────────────────────────────── - # │ ┌───┐ ┌───┐ - # ancilla_2 -> 3 ─────────X─┤ H ├────────────────────────────■──┤ H ├ - # ┌───┐ └───┘ ┌───┐ ┌───┐┌─┴─┐├───┤ - # q_1 -> 4 ┤ H ├─────────────────────■──┤ H ├─X─┤ H ├┤ X ├┤ H ├ - # └───┘ ┌───┐┌─┴─┐├───┤ │ └───┘└───┘└───┘ - # ancilla_3 -> 5 ─────────────────X─┤ H ├┤ X ├┤ H ├─X──────────────── - # │ └───┘└───┘└───┘ - # ancilla_4 -> 6 ─────────────X───X────────────────────────────────── - # │ - # ancilla_5 -> 7 ─────────X───X────────────────────────────────────── - # │ - # ancilla_6 -> 8 ──────X──X────────────────────────────────────────── - # ┌───┐ │ - # q_0 -> 9 ┤ H ├─X───────────────────────────────────────────── - # └───┘ res = tqc.layout.final_virtual_layout() - self.assertEqual(res, Layout({qc.qubits[0]: 4, qc.qubits[1]: 5, qc.qubits[2]: 3})) + self.assertEqual(res, Layout({qc.qubits[0]: 3, qc.qubits[1]: 5, qc.qubits[2]: 2})) def test_final_virtual_layout_full_path_with_ancilla_no_filter(self): qc = QuantumCircuit(3) @@ -144,37 +81,16 @@ def test_final_virtual_layout_full_path_with_ancilla_no_filter(self): qc.cx(0, 2) cmap = CouplingMap.from_line(10, bidirectional=False) tqc = transpile(qc, coupling_map=cmap, initial_layout=[9, 4, 0], seed_transpiler=42) - # tqc: - # q_2 -> 0 ──X───────────────────────────────────────────────── - # │ - # ancilla_0 -> 1 ──X───X───────────────────────────────────────────── - # │ - # ancilla_1 -> 2 ──────X──X────────────────────────────────────────── - # │ ┌───┐ ┌───┐ - # ancilla_2 -> 3 ─────────X─┤ H ├────────────────────────────■──┤ H ├ - # ┌───┐ └───┘ ┌───┐ ┌───┐┌─┴─┐├───┤ - # q_1 -> 4 ┤ H ├─────────────────────■──┤ H ├─X─┤ H ├┤ X ├┤ H ├ - # └───┘ ┌───┐┌─┴─┐├───┤ │ └───┘└───┘└───┘ - # ancilla_3 -> 5 ─────────────────X─┤ H ├┤ X ├┤ H ├─X──────────────── - # │ └───┘└───┘└───┘ - # ancilla_4 -> 6 ─────────────X───X────────────────────────────────── - # │ - # ancilla_5 -> 7 ─────────X───X────────────────────────────────────── - # │ - # ancilla_6 -> 8 ──────X──X────────────────────────────────────────── - # ┌───┐ │ - # q_0 -> 9 ┤ H ├─X───────────────────────────────────────────── - # └───┘ res = tqc.layout.final_virtual_layout(filter_ancillas=False) pos_to_virt = {v: k for k, v in tqc.layout.input_qubit_mapping.items()} expected = Layout( { - pos_to_virt[0]: 4, + pos_to_virt[0]: 3, pos_to_virt[1]: 5, - pos_to_virt[2]: 3, + pos_to_virt[2]: 2, pos_to_virt[3]: 0, pos_to_virt[4]: 1, - pos_to_virt[5]: 2, + pos_to_virt[5]: 4, pos_to_virt[6]: 6, pos_to_virt[7]: 7, pos_to_virt[8]: 8, diff --git a/test/visual/mpl/circuit/test_circuit_matplotlib_drawer.py b/test/visual/mpl/circuit/test_circuit_matplotlib_drawer.py index 0a2aaad0e718..f52338251438 100644 --- a/test/visual/mpl/circuit/test_circuit_matplotlib_drawer.py +++ b/test/visual/mpl/circuit/test_circuit_matplotlib_drawer.py @@ -2325,7 +2325,7 @@ def test_no_qreg_names_after_layout(self): qc.cx(1, 2) qc.cx(2, 0) circuit = transpile( - qc, backend, basis_gates=["rz", "sx", "cx"], layout_method="sabre", seed_transpiler=42 + qc, backend, basis_gates=["rz", "sx", "cx"], layout_method="sabre", seed_transpiler=15 ) fname = "qreg_names_after_layout.png"