diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index a33d025affc7..d7c2b8c3f783 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -12,7 +12,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-11, windows-latest, macos-14] + os: [ubuntu-latest, macos-12, windows-latest, macos-14] steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 @@ -47,7 +47,7 @@ jobs: strategy: fail-fast: false matrix: - os: [macos-11] + os: [macos-12] steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e433855fb26e..53043ffaa289 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -162,7 +162,7 @@ the code. It also lets the community know what you're working on, and if you need help, you can reference the issue when discussing it with other community and team members. -* For documentation issues relating to pages in the Start, Build, Transpile, Verify, Run, and Migration guides sections of [docs.quantum.ibm.com](https://docs.quantum.ibm.com/), please open an issue in the [Qiskit/documentation repo](https://github.com/Qiskit/documentation/issues/new/choose) rather than the Qiskit/qiskit repo. In other words, any page that DOES NOT have `/api/` in the url should be addressed in the Qiskit/documentation repo. (Exception: the [Migration guide](https://docs.quantum.ibm.com/api/migration-guides) urls contain `/api/` but are managed in the Qiskit/documentation repo.) +* For documentation issues relating to pages in the Start, Build, Transpile, Verify, Run, and Migration guides sections of [docs.quantum.ibm.com](https://docs.quantum.ibm.com/), please open an issue in the [Qiskit/documentation repo](https://github.com/Qiskit/documentation/issues/new/choose) rather than the Qiskit/qiskit repo. In other words, any page that DOES NOT have `/api/` in the url should be addressed in the Qiskit/documentation repo. * For issues relating to API reference pages (any page that contains `/api/` in the url), please open an issue in the repo specific to that API reference, for example [Qiskit/qiskit](https://github.com/Qiskit/qiskit/issues/new/choose), [Qiskit/qiskit-aer](https://github.com/Qiskit/qiskit-aer/issues/new/choose), or [Qiskit/qiskit-ibm-runtime](https://github.com/Qiskit/qiskit-ibm-runtime/issues/new/choose). If you've written some code but need help finishing it, want to get initial diff --git a/Cargo.lock b/Cargo.lock index 022b46f9a2a1..4858af1971e9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -550,9 +550,9 @@ checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "indexmap" -version = "2.2.6" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0" dependencies = [ "equivalent", "hashbrown 0.14.5", diff --git a/Cargo.toml b/Cargo.toml index 1e8a7185f449..a505a4e7c22b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,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" +indexmap.version = "2.3.0" hashbrown.version = "0.14.0" num-bigint = "0.4" num-complex = "0.4" diff --git a/DEPRECATION.md b/DEPRECATION.md index bc413bd311ff..d9e2f16f6473 100644 --- a/DEPRECATION.md +++ b/DEPRECATION.md @@ -1,7 +1,7 @@ # Deprecation Policy Starting from the 1.0.0 release, Qiskit follows semantic versioning, with a yearly release cycle for major releases. -[Full details of the scheduling are hosted with the external public documentation](https://docs.quantum.ibm.com/start/install#release-schedule). +[Full details of the scheduling are hosted with the external public documentation](https://docs.quantum.ibm.com/open-source/qiskit-sdk-version-strategy). This document is primarily intended for developers of Qiskit themselves. @@ -42,7 +42,7 @@ Similarly, while it is permissible where necessary for behavior to change with n ## What is the public interface? > [!NOTE] -> This section should be in sync with [the release schedule documentation of Qiskit](https://docs.quantum.ibm.com/start/install#release-schedule). +> This section should be in sync with [the release schedule documentation of Qiskit](https://docs.quantum.ibm.com/open-source/qiskit-sdk-version-strategy). > Please [open an issue against Qiskit](https://github.com/Qiskit/qiskit/issues/new/choose) if there are discrepancies so we can clarify them. For the purposes of semantic versioning, the Qiskit public API comprises all *publicly documented* packages, modules, classes, functions, methods, and attributes. diff --git a/README.md b/README.md index babf5756f5de..9238bf88fa41 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ For more details on how to use Qiskit, refer to the documentation located here: ## Installation > [!WARNING] -> Do not try to upgrade an existing Qiskit 0.* environment to Qiskit 1.0 in-place. [Read more](https://docs.quantum.ibm.com/api/migration-guides/qiskit-1.0-installation). +> Do not try to upgrade an existing Qiskit 0.* environment to Qiskit 1.0 in-place. [Read more](https://docs.quantum.ibm.com/migration-guides/qiskit-1.0-installation). We encourage installing Qiskit via ``pip``: @@ -33,7 +33,7 @@ pip install qiskit Pip will handle all dependencies automatically and you will always install the latest (and well-tested) version. -To install from source, follow the instructions in the [documentation](https://docs.quantum.ibm.com/start/install-qiskit-source). +To install from source, follow the instructions in the [documentation](https://docs.quantum.ibm.com/guides/install-qiskit-source). ## Create your first quantum program in Qiskit diff --git a/SECURITY.md b/SECURITY.md index 45e6a9d6f516..cf6d93238b1e 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -10,7 +10,7 @@ For example, if the most recent release is 1.0.1, then the current major release The 1.0.x series will be supported with bug fixes, until the release of 1.1.0, which will include new features. The last version of the previous major release, 0.46.x, is supported with bugfixes only until six months after the final release of 1.0.0. -We provide more detail on [the release and support schedule of Qiskit in our documentation](https://docs.quantum.ibm.com/start/install#release-schedule). +We provide more detail on [the release and support schedule of Qiskit in our documentation](https://docs.quantum.ibm.com/open-source/qiskit-sdk-version-strategy). ## Reporting a Vulnerability diff --git a/crates/accelerate/src/convert_2q_block_matrix.rs b/crates/accelerate/src/convert_2q_block_matrix.rs index 12146dd9d080..e9f6e343b6bd 100644 --- a/crates/accelerate/src/convert_2q_block_matrix.rs +++ b/crates/accelerate/src/convert_2q_block_matrix.rs @@ -145,7 +145,6 @@ pub fn collect_2q_blocks_filter(node: &Bound) -> Option { } } -#[pymodule] pub fn convert_2q_block_matrix(m: &Bound) -> PyResult<()> { m.add_wrapped(wrap_pyfunction!(blocks_to_matrix))?; m.add_wrapped(wrap_pyfunction!(collect_2q_blocks_filter))?; diff --git a/crates/accelerate/src/dense_layout.rs b/crates/accelerate/src/dense_layout.rs index 9529742d7e62..a7466748417a 100644 --- a/crates/accelerate/src/dense_layout.rs +++ b/crates/accelerate/src/dense_layout.rs @@ -244,7 +244,6 @@ pub fn best_subset_inner( [rows, cols, best_map] } -#[pymodule] pub fn dense_layout(m: &Bound) -> PyResult<()> { m.add_wrapped(wrap_pyfunction!(best_subset))?; Ok(()) diff --git a/crates/accelerate/src/error_map.rs b/crates/accelerate/src/error_map.rs index 8dbd2e4290a5..b61733ae1512 100644 --- a/crates/accelerate/src/error_map.rs +++ b/crates/accelerate/src/error_map.rs @@ -111,7 +111,6 @@ impl ErrorMap { } } -#[pymodule] pub fn error_map(m: &Bound) -> PyResult<()> { m.add_class::()?; Ok(()) diff --git a/crates/accelerate/src/euler_one_qubit_decomposer.rs b/crates/accelerate/src/euler_one_qubit_decomposer.rs index 7bbb6871db0a..7463777af624 100644 --- a/crates/accelerate/src/euler_one_qubit_decomposer.rs +++ b/crates/accelerate/src/euler_one_qubit_decomposer.rs @@ -1059,7 +1059,6 @@ pub fn collect_1q_runs_filter(node: &Bound) -> bool { } } -#[pymodule] pub fn euler_one_qubit_decomposer(m: &Bound) -> PyResult<()> { m.add_wrapped(wrap_pyfunction!(params_zyz))?; m.add_wrapped(wrap_pyfunction!(params_xyx))?; diff --git a/crates/accelerate/src/isometry.rs b/crates/accelerate/src/isometry.rs index ceaba2946b3a..a54116b2b2f9 100644 --- a/crates/accelerate/src/isometry.rs +++ b/crates/accelerate/src/isometry.rs @@ -345,7 +345,6 @@ fn b(k: usize, s: usize) -> usize { k - (a(k, s) * 2_usize.pow(s as u32)) } -#[pymodule] pub fn isometry(m: &Bound) -> PyResult<()> { m.add_wrapped(wrap_pyfunction!(diag_is_identity_up_to_global_phase))?; m.add_wrapped(wrap_pyfunction!(find_squs_for_disentangling))?; diff --git a/crates/accelerate/src/nlayout.rs b/crates/accelerate/src/nlayout.rs index b3709d2804bb..e0235e5c954a 100644 --- a/crates/accelerate/src/nlayout.rs +++ b/crates/accelerate/src/nlayout.rs @@ -216,7 +216,6 @@ impl NLayout { } } -#[pymodule] pub fn nlayout(m: &Bound) -> PyResult<()> { m.add_class::()?; Ok(()) diff --git a/crates/accelerate/src/optimize_1q_gates.rs b/crates/accelerate/src/optimize_1q_gates.rs index a683604c19e0..64924a339136 100644 --- a/crates/accelerate/src/optimize_1q_gates.rs +++ b/crates/accelerate/src/optimize_1q_gates.rs @@ -90,7 +90,6 @@ pub fn compose_u3_rust( out_angles } -#[pymodule] pub fn optimize_1q_gates(m: &Bound) -> PyResult<()> { m.add_wrapped(wrap_pyfunction!(compose_u3_rust))?; Ok(()) diff --git a/crates/accelerate/src/pauli_exp_val.rs b/crates/accelerate/src/pauli_exp_val.rs index 8ee4b019b3e0..bf9569b485e1 100644 --- a/crates/accelerate/src/pauli_exp_val.rs +++ b/crates/accelerate/src/pauli_exp_val.rs @@ -193,7 +193,6 @@ pub fn density_expval_pauli_with_x( } } -#[pymodule] pub fn pauli_expval(m: &Bound) -> PyResult<()> { m.add_wrapped(wrap_pyfunction!(expval_pauli_no_x))?; m.add_wrapped(wrap_pyfunction!(expval_pauli_with_x))?; diff --git a/crates/accelerate/src/results/mod.rs b/crates/accelerate/src/results/mod.rs index 36282a749e66..6d5a79363977 100644 --- a/crates/accelerate/src/results/mod.rs +++ b/crates/accelerate/src/results/mod.rs @@ -16,7 +16,6 @@ pub mod marginalization; use pyo3::prelude::*; use pyo3::wrap_pyfunction; -#[pymodule] pub fn results(m: &Bound) -> PyResult<()> { m.add_wrapped(wrap_pyfunction!(marginalization::marginal_counts))?; m.add_wrapped(wrap_pyfunction!(marginalization::marginal_distribution))?; diff --git a/crates/accelerate/src/sabre/mod.rs b/crates/accelerate/src/sabre/mod.rs index 287fdd743dfa..77057b69c272 100644 --- a/crates/accelerate/src/sabre/mod.rs +++ b/crates/accelerate/src/sabre/mod.rs @@ -106,7 +106,6 @@ impl BlockResult { } } -#[pymodule] pub fn sabre(m: &Bound) -> PyResult<()> { m.add_wrapped(wrap_pyfunction!(route::sabre_routing))?; m.add_wrapped(wrap_pyfunction!(layout::sabre_layout_and_routing))?; diff --git a/crates/accelerate/src/sampled_exp_val.rs b/crates/accelerate/src/sampled_exp_val.rs index 0b8836a94165..3424c12dcdfb 100644 --- a/crates/accelerate/src/sampled_exp_val.rs +++ b/crates/accelerate/src/sampled_exp_val.rs @@ -87,7 +87,6 @@ pub fn sampled_expval_complex( Ok(out.re) } -#[pymodule] pub fn sampled_exp_val(m: &Bound) -> PyResult<()> { m.add_wrapped(wrap_pyfunction!(sampled_expval_float))?; m.add_wrapped(wrap_pyfunction!(sampled_expval_complex))?; diff --git a/crates/accelerate/src/sparse_pauli_op.rs b/crates/accelerate/src/sparse_pauli_op.rs index 8a51d8ee781c..73c4ab7a73d5 100644 --- a/crates/accelerate/src/sparse_pauli_op.rs +++ b/crates/accelerate/src/sparse_pauli_op.rs @@ -819,7 +819,6 @@ impl_to_matrix_sparse!( u64 ); -#[pymodule] pub fn sparse_pauli_op(m: &Bound) -> PyResult<()> { m.add_wrapped(wrap_pyfunction!(unordered_unique))?; m.add_wrapped(wrap_pyfunction!(decompose_dense))?; diff --git a/crates/accelerate/src/star_prerouting.rs b/crates/accelerate/src/star_prerouting.rs index fd2156ad2011..dc777a844767 100644 --- a/crates/accelerate/src/star_prerouting.rs +++ b/crates/accelerate/src/star_prerouting.rs @@ -207,7 +207,6 @@ fn apply_swap( } } -#[pymodule] pub fn star_prerouting(m: &Bound) -> PyResult<()> { m.add_wrapped(wrap_pyfunction!(star_preroute))?; Ok(()) diff --git a/crates/accelerate/src/stochastic_swap.rs b/crates/accelerate/src/stochastic_swap.rs index d4e3890b9ccb..5260c85b3d42 100644 --- a/crates/accelerate/src/stochastic_swap.rs +++ b/crates/accelerate/src/stochastic_swap.rs @@ -335,7 +335,6 @@ pub fn swap_trials( Ok((best_edges, best_layout, best_depth)) } -#[pymodule] pub fn stochastic_swap(m: &Bound) -> PyResult<()> { m.add_wrapped(wrap_pyfunction!(swap_trials))?; m.add_class::()?; diff --git a/crates/accelerate/src/synthesis/clifford/mod.rs b/crates/accelerate/src/synthesis/clifford/mod.rs index ac178b566700..4828a5666734 100644 --- a/crates/accelerate/src/synthesis/clifford/mod.rs +++ b/crates/accelerate/src/synthesis/clifford/mod.rs @@ -57,7 +57,6 @@ fn synth_clifford_bm(py: Python, clifford: PyReadonlyArray2) -> PyResult) -> PyResult<()> { m.add_function(wrap_pyfunction!(synth_clifford_greedy, m)?)?; m.add_function(wrap_pyfunction!(synth_clifford_bm, m)?)?; diff --git a/crates/accelerate/src/synthesis/linear/mod.rs b/crates/accelerate/src/synthesis/linear/mod.rs index 49dfeefd3869..08a0b1e104b3 100644 --- a/crates/accelerate/src/synthesis/linear/mod.rs +++ b/crates/accelerate/src/synthesis/linear/mod.rs @@ -175,7 +175,6 @@ fn check_invertible_binary_matrix(py: Python, mat: PyReadonlyArray2) -> Py Ok(out.to_object(py)) } -#[pymodule] pub fn linear(m: &Bound) -> PyResult<()> { m.add_wrapped(wrap_pyfunction!(gauss_elimination_with_perm))?; m.add_wrapped(wrap_pyfunction!(gauss_elimination))?; diff --git a/crates/accelerate/src/synthesis/mod.rs b/crates/accelerate/src/synthesis/mod.rs index 1b9908ef80cf..fae05c6739cc 100644 --- a/crates/accelerate/src/synthesis/mod.rs +++ b/crates/accelerate/src/synthesis/mod.rs @@ -15,12 +15,19 @@ pub mod linear; mod permutation; use pyo3::prelude::*; -use pyo3::wrap_pymodule; -#[pymodule] pub fn synthesis(m: &Bound) -> PyResult<()> { - m.add_wrapped(wrap_pymodule!(linear::linear))?; - m.add_wrapped(wrap_pymodule!(permutation::permutation))?; - m.add_wrapped(wrap_pymodule!(clifford::clifford))?; + let linear_mod = PyModule::new_bound(m.py(), "linear")?; + linear::linear(&linear_mod)?; + m.add_submodule(&linear_mod)?; + + let permutation_mod = PyModule::new_bound(m.py(), "permutation")?; + permutation::permutation(&permutation_mod)?; + m.add_submodule(&permutation_mod)?; + + let clifford_mod = PyModule::new_bound(m.py(), "clifford")?; + clifford::clifford(&clifford_mod)?; + m.add_submodule(&clifford_mod)?; + Ok(()) } diff --git a/crates/accelerate/src/synthesis/permutation/mod.rs b/crates/accelerate/src/synthesis/permutation/mod.rs index fccb0cfb972e..55dc3efe4a87 100644 --- a/crates/accelerate/src/synthesis/permutation/mod.rs +++ b/crates/accelerate/src/synthesis/permutation/mod.rs @@ -114,7 +114,6 @@ pub fn _synth_permutation_depth_lnn_kms( ) } -#[pymodule] pub fn permutation(m: &Bound) -> PyResult<()> { m.add_function(wrap_pyfunction!(_validate_permutation, m)?)?; m.add_function(wrap_pyfunction!(_inverse_pattern, m)?)?; diff --git a/crates/accelerate/src/target_transpiler/mod.rs b/crates/accelerate/src/target_transpiler/mod.rs index b5c56dc6d091..bb0ec166c07e 100644 --- a/crates/accelerate/src/target_transpiler/mod.rs +++ b/crates/accelerate/src/target_transpiler/mod.rs @@ -1254,8 +1254,7 @@ where obj_bound.is_instance(other_obj.bind(py)) } -#[pymodule] -pub fn target(_py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> { +pub fn target(m: &Bound) -> PyResult<()> { m.add_class::()?; m.add_class::()?; Ok(()) diff --git a/crates/accelerate/src/two_qubit_decompose.rs b/crates/accelerate/src/two_qubit_decompose.rs index dfee4c5b0bff..b423b1d65267 100644 --- a/crates/accelerate/src/two_qubit_decompose.rs +++ b/crates/accelerate/src/two_qubit_decompose.rs @@ -2254,7 +2254,6 @@ pub fn local_equivalence(weyl: PyReadonlyArray1) -> PyResult<[f64; 3]> { Ok([g0_equiv + 0., g1_equiv + 0., g2_equiv + 0.]) } -#[pymodule] pub fn two_qubit_decompose(m: &Bound) -> PyResult<()> { m.add_wrapped(wrap_pyfunction!(_num_basis_gates))?; m.add_wrapped(wrap_pyfunction!(two_qubit_decompose_up_to_diagonal))?; diff --git a/crates/accelerate/src/uc_gate.rs b/crates/accelerate/src/uc_gate.rs index 21fd7fa04656..ec79f4d4d2ba 100644 --- a/crates/accelerate/src/uc_gate.rs +++ b/crates/accelerate/src/uc_gate.rs @@ -156,7 +156,6 @@ pub fn dec_ucg_help( ) } -#[pymodule] pub fn uc_gate(m: &Bound) -> PyResult<()> { m.add_wrapped(wrap_pyfunction!(dec_ucg_help))?; Ok(()) diff --git a/crates/accelerate/src/utils.rs b/crates/accelerate/src/utils.rs index 6df00f7f8b76..598256192f83 100644 --- a/crates/accelerate/src/utils.rs +++ b/crates/accelerate/src/utils.rs @@ -41,7 +41,6 @@ pub fn eigenvalues(py: Python, unitary: PyReadonlyArray2>) -> PyObj .into() } -#[pymodule] pub fn utils(m: &Bound) -> PyResult<()> { m.add_wrapped(wrap_pyfunction!(eigenvalues))?; Ok(()) diff --git a/crates/accelerate/src/vf2_layout.rs b/crates/accelerate/src/vf2_layout.rs index e84b2bfbfb8c..476197397aff 100644 --- a/crates/accelerate/src/vf2_layout.rs +++ b/crates/accelerate/src/vf2_layout.rs @@ -106,7 +106,6 @@ pub fn score_layout( Ok(1. - fidelity) } -#[pymodule] pub fn vf2_layout(m: &Bound) -> PyResult<()> { m.add_wrapped(wrap_pyfunction!(score_layout))?; m.add_class::()?; diff --git a/crates/circuit/src/circuit_data.rs b/crates/circuit/src/circuit_data.rs index c05feb518926..d6ada1865f8b 100644 --- a/crates/circuit/src/circuit_data.rs +++ b/crates/circuit/src/circuit_data.rs @@ -834,19 +834,19 @@ impl CircuitData { Ok(()) } - /// Assign all the circuit parameters, given a sequence-like input of `Param` instances. - fn assign_parameters_sequence(&mut self, sequence: Bound) -> PyResult<()> { - if sequence.len()? != self.param_table.num_parameters() { - return Err(PyValueError::new_err(concat!( - "Mismatching number of values and parameters. For partial binding ", - "please pass a dictionary of {parameter: value} pairs." - ))); - } - let mut old_table = std::mem::take(&mut self.param_table); + /// Assign all the circuit parameters, given an iterable input of `Param` instances. + fn assign_parameters_iterable(&mut self, sequence: Bound) -> PyResult<()> { if let Ok(readonly) = sequence.extract::>() { // Fast path for Numpy arrays; in this case we can easily handle them without copying // the data across into a Rust-space `Vec` first. let array = readonly.as_array(); + if array.len() != self.param_table.num_parameters() { + return Err(PyValueError::new_err(concat!( + "Mismatching number of values and parameters. For partial binding ", + "please pass a dictionary of {parameter: value} pairs." + ))); + } + let mut old_table = std::mem::take(&mut self.param_table); self.assign_parameters_inner( sequence.py(), array @@ -855,13 +855,23 @@ impl CircuitData { .map(|(value, (param_ob, uses))| (param_ob, Param::Float(*value), uses)), ) } else { - let values = sequence.extract::>()?; + let values = sequence + .iter()? + .map(|ob| Param::extract_no_coerce(&ob?)) + .collect::>>()?; + if values.len() != self.param_table.num_parameters() { + return Err(PyValueError::new_err(concat!( + "Mismatching number of values and parameters. For partial binding ", + "please pass a dictionary of {parameter: value} pairs." + ))); + } + let mut old_table = std::mem::take(&mut self.param_table); self.assign_parameters_inner( sequence.py(), values .into_iter() .zip(old_table.drain_ordered()) - .map(|(value, (param_ob, uses))| (param_ob, value.0, uses)), + .map(|(value, (param_ob, uses))| (param_ob, value, uses)), ) } } diff --git a/crates/circuit/src/lib.rs b/crates/circuit/src/lib.rs index 8a13aab33cea..739bf998a611 100644 --- a/crates/circuit/src/lib.rs +++ b/crates/circuit/src/lib.rs @@ -56,8 +56,7 @@ impl From for BitType { } } -#[pymodule] -pub fn circuit(m: Bound) -> PyResult<()> { +pub fn circuit(m: &Bound) -> PyResult<()> { m.add_class::()?; m.add_class::()?; m.add_class::()?; diff --git a/crates/pyext/src/lib.rs b/crates/pyext/src/lib.rs index f9711641a938..04b0c0609347 100644 --- a/crates/pyext/src/lib.rs +++ b/crates/pyext/src/lib.rs @@ -11,7 +11,6 @@ // that they have been altered from the originals. use pyo3::prelude::*; -use pyo3::wrap_pymodule; use qiskit_accelerate::{ convert_2q_block_matrix::convert_2q_block_matrix, dense_layout::dense_layout, @@ -24,30 +23,41 @@ use qiskit_accelerate::{ vf2_layout::vf2_layout, }; +#[inline(always)] +#[doc(hidden)] +fn add_submodule(m: &Bound, constructor: F, name: &str) -> PyResult<()> +where + F: FnOnce(&Bound) -> PyResult<()>, +{ + let new_mod = PyModule::new_bound(m.py(), name)?; + constructor(&new_mod)?; + m.add_submodule(&new_mod) +} + #[pymodule] fn _accelerate(m: &Bound) -> PyResult<()> { - m.add_wrapped(wrap_pymodule!(qiskit_circuit::circuit))?; - m.add_wrapped(wrap_pymodule!(qiskit_qasm2::qasm2))?; - m.add_wrapped(wrap_pymodule!(qiskit_qasm3::qasm3))?; - m.add_wrapped(wrap_pymodule!(convert_2q_block_matrix))?; - m.add_wrapped(wrap_pymodule!(dense_layout))?; - m.add_wrapped(wrap_pymodule!(error_map))?; - m.add_wrapped(wrap_pymodule!(euler_one_qubit_decomposer))?; - m.add_wrapped(wrap_pymodule!(isometry))?; - m.add_wrapped(wrap_pymodule!(nlayout))?; - m.add_wrapped(wrap_pymodule!(optimize_1q_gates))?; - m.add_wrapped(wrap_pymodule!(pauli_expval))?; - m.add_wrapped(wrap_pymodule!(synthesis))?; - m.add_wrapped(wrap_pymodule!(results))?; - m.add_wrapped(wrap_pymodule!(sabre))?; - m.add_wrapped(wrap_pymodule!(sampled_exp_val))?; - m.add_wrapped(wrap_pymodule!(sparse_pauli_op))?; - m.add_wrapped(wrap_pymodule!(star_prerouting))?; - m.add_wrapped(wrap_pymodule!(stochastic_swap))?; - m.add_wrapped(wrap_pymodule!(target))?; - m.add_wrapped(wrap_pymodule!(two_qubit_decompose))?; - m.add_wrapped(wrap_pymodule!(uc_gate))?; - m.add_wrapped(wrap_pymodule!(utils))?; - m.add_wrapped(wrap_pymodule!(vf2_layout))?; + add_submodule(m, qiskit_circuit::circuit, "circuit")?; + add_submodule(m, qiskit_qasm2::qasm2, "qasm2")?; + add_submodule(m, qiskit_qasm3::qasm3, "qasm3")?; + add_submodule(m, convert_2q_block_matrix, "convert_2q_block_matrix")?; + add_submodule(m, dense_layout, "dense_layout")?; + add_submodule(m, error_map, "error_map")?; + add_submodule(m, euler_one_qubit_decomposer, "euler_one_qubit_decomposer")?; + add_submodule(m, isometry, "isometry")?; + add_submodule(m, nlayout, "nlayout")?; + add_submodule(m, optimize_1q_gates, "optimize_1q_gates")?; + add_submodule(m, pauli_expval, "pauli_expval")?; + add_submodule(m, synthesis, "synthesis")?; + add_submodule(m, results, "results")?; + add_submodule(m, sabre, "sabre")?; + add_submodule(m, sampled_exp_val, "sampled_exp_val")?; + add_submodule(m, sparse_pauli_op, "sparse_pauli_op")?; + add_submodule(m, star_prerouting, "star_prerouting")?; + add_submodule(m, stochastic_swap, "stochastic_swap")?; + add_submodule(m, target, "target")?; + add_submodule(m, two_qubit_decompose, "two_qubit_decompose")?; + add_submodule(m, uc_gate, "uc_gate")?; + add_submodule(m, utils, "utils")?; + add_submodule(m, vf2_layout, "vf2_layout")?; Ok(()) } diff --git a/crates/qasm2/src/lib.rs b/crates/qasm2/src/lib.rs index 7129b17f7fdf..beac72674e99 100644 --- a/crates/qasm2/src/lib.rs +++ b/crates/qasm2/src/lib.rs @@ -123,7 +123,6 @@ fn bytecode_from_file( /// An interface to the Rust components of the parser stack, and the types it uses to represent the /// output. The principal entry points for Python are :func:`bytecode_from_string` and /// :func:`bytecode_from_file`, which produce iterables of :class:`Bytecode` objects. -#[pymodule] pub fn qasm2(module: &Bound) -> PyResult<()> { module.add_class::()?; module.add_class::()?; diff --git a/crates/qasm3/src/lib.rs b/crates/qasm3/src/lib.rs index 9a651a5c12e2..bca862406f39 100644 --- a/crates/qasm3/src/lib.rs +++ b/crates/qasm3/src/lib.rs @@ -153,7 +153,6 @@ pub fn load( /// Internal module supplying the OpenQASM 3 import capabilities. The entries in it should largely /// be re-exposed directly to public Python space. -#[pymodule] pub fn qasm3(module: &Bound) -> PyResult<()> { module.add_function(wrap_pyfunction!(loads, module)?)?; module.add_function(wrap_pyfunction!(load, module)?)?; diff --git a/qiskit/circuit/quantumcircuit.py b/qiskit/circuit/quantumcircuit.py index ad6353373358..9413141fb757 100644 --- a/qiskit/circuit/quantumcircuit.py +++ b/qiskit/circuit/quantumcircuit.py @@ -4188,7 +4188,7 @@ def _unsorted_parameters(self) -> set[Parameter]: @overload def assign_parameters( self, - parameters: Union[Mapping[Parameter, ParameterValueType], Sequence[ParameterValueType]], + parameters: Union[Mapping[Parameter, ParameterValueType], Iterable[ParameterValueType]], inplace: Literal[False] = ..., *, flat_input: bool = ..., @@ -4198,7 +4198,7 @@ def assign_parameters( @overload def assign_parameters( self, - parameters: Union[Mapping[Parameter, ParameterValueType], Sequence[ParameterValueType]], + parameters: Union[Mapping[Parameter, ParameterValueType], Iterable[ParameterValueType]], inplace: Literal[True] = ..., *, flat_input: bool = ..., @@ -4207,7 +4207,7 @@ def assign_parameters( def assign_parameters( # pylint: disable=missing-raises-doc self, - parameters: Union[Mapping[Parameter, ParameterValueType], Sequence[ParameterValueType]], + parameters: Union[Mapping[Parameter, ParameterValueType], Iterable[ParameterValueType]], inplace: bool = False, *, flat_input: bool = False, @@ -4317,7 +4317,7 @@ def assign_parameters( # pylint: disable=missing-raises-doc target._data.assign_parameters_mapping(parameter_binds) else: parameter_binds = _ParameterBindsSequence(target._data.parameters, parameters) - target._data.assign_parameters_sequence(parameters) + target._data.assign_parameters_iterable(parameters) # Finally, assign the parameters inside any of the calibrations. We don't track these in # the `ParameterTable`, so we manually reconstruct things. diff --git a/qiskit/providers/models/__init__.py b/qiskit/providers/models/__init__.py index 58fafed92986..d9e63e3eb75c 100644 --- a/qiskit/providers/models/__init__.py +++ b/qiskit/providers/models/__init__.py @@ -54,10 +54,10 @@ warnings.warn( - "qiskit.providers.models is deprecated since Qiskit 1.2 and will be removed in Qiskit 2.0." - "With the removal of Qobj, there is no need for these schema-conformant objects. If you still need" - "to use them, it could be because you are using a BackendV1, which is also deprecated in favor" - "of BackendV2", + "qiskit.providers.models is deprecated since Qiskit 1.2 and will be removed in Qiskit 2.0. " + "With the removal of Qobj, there is no need for these schema-conformant objects. If you still need " + "to use them, it could be because you are using a BackendV1, which is also deprecated in favor " + "of BackendV2.", DeprecationWarning, 2, ) diff --git a/qiskit/qpy/__init__.py b/qiskit/qpy/__init__.py index e072536fef47..42c7466d4497 100644 --- a/qiskit/qpy/__init__.py +++ b/qiskit/qpy/__init__.py @@ -774,7 +774,7 @@ With the support of :class:`.~ScheduleBlock`, now :class:`~.QuantumCircuit` can be serialized together with :attr:`~.QuantumCircuit.calibrations`, or -`Pulse Gates `_. +`Pulse Gates `_. In QPY version 5 and above, :ref:`qpy_circuit_calibrations` payload is packed after the :ref:`qpy_instructions` block. diff --git a/qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py b/qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py index 91d8d82decae..10d76f8719af 100644 --- a/qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py +++ b/qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py @@ -937,7 +937,7 @@ def to_matrix(self, sparse: bool = False, force_serial: bool = False) -> np.ndar array (the default). force_serial: if ``True``, use an unthreaded implementation, regardless of the state of the `Qiskit threading-control environment variables - `__. + `__. By default, this will use threaded parallelism over the available CPUs. Returns: diff --git a/qiskit/transpiler/passes/scheduling/alignments/pulse_gate_validation.py b/qiskit/transpiler/passes/scheduling/alignments/pulse_gate_validation.py index 955f712214a3..a39b81092fbf 100644 --- a/qiskit/transpiler/passes/scheduling/alignments/pulse_gate_validation.py +++ b/qiskit/transpiler/passes/scheduling/alignments/pulse_gate_validation.py @@ -31,7 +31,7 @@ class ValidatePulseGates(AnalysisPass): In Qiskit SDK, we can define the pulse-level implementation of custom quantum gate instructions, as a `pulse gate - `__, + `__, thus user gates should satisfy all waveform memory constraints imposed by the backend. This pass validates all attached calibration entries and raises ``TranspilerError`` to diff --git a/releasenotes/notes/1.0/platform-support-f7f693aaf5dec044.yaml b/releasenotes/notes/1.0/platform-support-f7f693aaf5dec044.yaml index e15bb711959b..8531da575fc8 100644 --- a/releasenotes/notes/1.0/platform-support-f7f693aaf5dec044.yaml +++ b/releasenotes/notes/1.0/platform-support-f7f693aaf5dec044.yaml @@ -13,7 +13,7 @@ upgrade: - | Support for 32 bit platforms, i686 Linux and 32 bit Windows, on Python < 3.10 has been downgraded from Tier 2 to Tier 3, as documented in - the `platform support page `_. This is a consequence of making + the `platform support page `_. This is a consequence of making ``symengine`` required for all users, as there is a lack of pre-compiled packages available for these platforms, so users will need to build Symengine from source. diff --git a/releasenotes/notes/1.0/psutil-dependancy-removed-bf5366f516d92378.yaml b/releasenotes/notes/1.0/psutil-dependancy-removed-bf5366f516d92378.yaml index 1781157d3baf..679955c3c1b0 100644 --- a/releasenotes/notes/1.0/psutil-dependancy-removed-bf5366f516d92378.yaml +++ b/releasenotes/notes/1.0/psutil-dependancy-removed-bf5366f516d92378.yaml @@ -11,5 +11,5 @@ upgrade: number of processes used you can use the new ``num_processes`` argument to those functions, or the ``QISKIT_NUM_PROCS`` environment variable or ``num_processes`` field in a user configuration file (see the `local configuration guide - `__ + `__ for more details) if you need to adjust the number of processes that Qiskit potentially uses. diff --git a/test/python/circuit/test_parameters.py b/test/python/circuit/test_parameters.py index 2261d903a63c..c10e274be791 100644 --- a/test/python/circuit/test_parameters.py +++ b/test/python/circuit/test_parameters.py @@ -347,6 +347,20 @@ def test_assign_parameters_by_name(self): qc.assign_parameters({a: 1, b: 2, c: 3}), qc.assign_parameters({"a": 1, "b": 2, "c": 3}) ) + def test_assign_parameters_by_iterable(self): + """Assignment works with weird iterables.""" + a, b, c = Parameter("a"), Parameter("b"), Parameter("c") + qc = QuantumCircuit(1) + qc.rz(a, 0) + qc.rz(b + c, 0) + + binds = [1.25, 2.5, 0.125] + expected = qc.assign_parameters(dict(zip(qc.parameters, binds))) + self.assertEqual(qc.assign_parameters(iter(binds)), expected) + self.assertEqual(qc.assign_parameters(dict.fromkeys(binds).keys()), expected) + self.assertEqual(qc.assign_parameters(dict(zip(qc.parameters, binds)).values()), expected) + self.assertEqual(qc.assign_parameters(bind for bind in binds), expected) + def test_bind_parameters_custom_definition_global_phase(self): """Test that a custom gate with a parametrized `global_phase` is assigned correctly.""" x = Parameter("x")