Skip to content

Commit

Permalink
Merge branch 'main' of github.com:Qiskit/qiskit into cargo-test-dag
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinhartman committed Oct 2, 2024
2 parents 65a90d3 + fee9f77 commit 00c9158
Show file tree
Hide file tree
Showing 115 changed files with 3,405 additions and 1,618 deletions.
2 changes: 1 addition & 1 deletion .azure/lint_docs_qpy-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,6 @@ jobs:
pushd test/qpy_compat
./run_tests.sh
popd
mkdir qpy_files || :
mkdir -p qpy_files
mv test/qpy_compat/qpy_* qpy_files/.
displayName: 'Run QPY backwards compat tests'
1 change: 1 addition & 0 deletions .github/workflows/wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ jobs:
uses: pypa/cibuildwheel@v2.19.2
env:
CIBW_ARCHS_LINUX: aarch64
CIBW_TEST_COMMAND: cp -r {project}/test . && QISKIT_PARALLEL=FALSE stestr --test-path test/python run --abbreviate -n test.python.compiler.test_transpiler
- uses: actions/upload-artifact@v4
with:
name: wheels-${{ matrix.os }}-aarch64
Expand Down
187 changes: 128 additions & 59 deletions .mailmap

Large diffs are not rendered by default.

41 changes: 23 additions & 18 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ from system-wide packages. This way, we avoid inadvertently becoming dependent o
particular system configuration. For developers, this also makes it easy to maintain multiple
environments (e.g. one per supported Python version, for older versions of Qiskit, etc.).



### Set up a Python venv

All Python versions supported by Qiskit include built-in virtual environment module
Expand Down Expand Up @@ -107,17 +105,17 @@ pip install -e .
Qiskit is primarily written in Python but there are some core routines
that are written in the [Rust](https://www.rust-lang.org/) programming
language to improve the runtime performance. For the released versions of
qiskit we publish precompiled binaries on the
Qiskit we publish precompiled binaries on the
[Python Package Index](https://pypi.org/) for all the supported platforms
which only requires a functional Python environment to install. However, when
building and installing from source you will need a rust compiler installed. You can do this very easily
building and installing from source you will need a Rust compiler installed. You can do this very easily
using rustup: https://rustup.rs/ which provides a single tool to install and
configure the latest version of the rust compiler.
[Other installation methods](https://forge.rust-lang.org/infra/other-installation-methods.html)
exist too. For Windows users, besides rustup, you will also need install
the Visual C++ build tools so that Rust can link against the system c/c++
libraries. You can see more details on this in the
[rustup documentation](https://rust-lang.github.io/rustup/installation/windows.html).
[rustup documentation](https://rust-lang.github.io/rustup/installation/windows-msvc.html).

If you use Rustup, it will automatically install the correct Rust version
currently used by the project.
Expand Down Expand Up @@ -145,7 +143,7 @@ Python gate objects when accessing them from a `QuantumCircuit` or `DAGCircuit`.
This makes a tradeoff between runtime performance for Python access and memory
overhead. Caching gates will result in better runtime for users of Python at
the cost of increased memory consumption. If you're working with any custom
transpiler passes written in python or are otherwise using a workflow that
transpiler passes written in Python or are otherwise using a workflow that
repeatedly accesses the `operation` attribute of a `CircuitInstruction` or `op`
attribute of `DAGOpNode` enabling caching is recommended.

Expand Down Expand Up @@ -187,8 +185,8 @@ please ensure that:
which will run these checks and report any issues.

If your code fails the local style checks (specifically the black
code formatting check) you can use `tox -eblack` to automatically
fix update the code formatting.
or Rust code formatting check) you can use `tox -eblack` and
`cargo fmt` to automatically fix the code formatting.
2. The documentation has been updated accordingly. In particular, if a
function or class has been modified during the PR, please update the
*docstring* accordingly.
Expand Down Expand Up @@ -396,11 +394,6 @@ it has been tagged:

reno report --version 0.9.0

At release time ``reno report`` is used to generate the release notes for the
release and the output will be submitted as a pull request to the documentation
repository's [release notes file](
https://github.com/Qiskit/qiskit/blob/master/docs/release_notes.rst)

#### Building release notes locally

Building The release notes are part of the standard qiskit documentation
Expand Down Expand Up @@ -440,21 +433,21 @@ you can do this faster with the `-n`/`--no-discover` option. For example:

to run a module:
```
tox -epy310 -- -n test.python.test_examples
tox -epy310 -- -n test.python.compiler.test_transpiler
```
or to run the same module by path:

```
tox -epy310 -- -n test/python/test_examples.py
tox -epy310 -- -n test/python/compiler/test_transpiler.py
```
to run a class:

```
tox -epy310 -- -n test.python.test_examples.TestPythonExamples
tox -epy310 -- -n test.python.compiler.test_transpiler.TestTranspile
```
to run a method:
```
tox -epy310 -- -n test.python.test_examples.TestPythonExamples.test_all_examples
tox -epy310 -- -n test.python.compiler.test_transpiler.TestTranspile.test_transpile_non_adjacent_layout
```

Alternatively there is a makefile provided to run tests, however this
Expand Down Expand Up @@ -592,6 +585,9 @@ mod tests {
}
```

For more detailed guidance on how to write Rust tests, you can refer to the Rust
documentation's [guide on writing tests](https://doc.rust-lang.org/book/ch11-01-writing-tests.html).

Rust tests are run separately from the Python tests. The easiest way to run
them is via ``tox``, which creates an isolated venv and pre-installs ``qiskit``
prior to running ``cargo test``:
Expand Down Expand Up @@ -706,6 +702,15 @@ rather than via `tox`. If you have installed the development packages in your py
`pip install -r requirements-dev.txt`, then `ruff` and `black` will be available and can be run from
the command line. See [`tox.ini`](tox.ini) for how `tox` invokes them.

### Rust style and lint

For formatting and lint checking Rust code, you'll need to use different tools than you would for Python. Qiskit uses [rustfmt](https://github.com/rust-lang/rustfmt) for
code formatting. You can simply run `cargo fmt` (if you installed Rust with the
default settings using `rustup`), and it will update the code formatting automatically to
conform to the style guidelines. This is very similar to running `tox -eblack` for Python code. For lint checking, Qiskit uses [clippy](https://github.com/rust-lang/rust-clippy) which can be invoked via `cargo clippy`.

Rust lint and formatting checks are included in the the `tox -elint` command. For CI to pass you will need both checks to pass without any warnings or errors. Note that this command checks the code but won't apply any modifications, if you need to update formatting, you'll need to run `cargo fmt`.


## Building API docs locally

Expand Down Expand Up @@ -787,7 +792,7 @@ developers to test the release ahead of time. When the pre-release is tagged the
automation will publish the pre-release to PyPI (but only get installed on user request),
create the `stable/*` branch, and generate a pre-release changelog/release page. At
this point the `main` opens up for development of the next release. The `stable/*`
branches should only receive changes in the form of bug fixes at this point. If there
branches should only receive changes in the form of bug fixes at this point. If there
is a need additional release candidates can be published from `stable/*` and when the
release is ready a full release will be tagged and published from `stable/*`.

Expand Down
19 changes: 11 additions & 8 deletions Cargo.lock

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

12 changes: 5 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,27 +28,25 @@ env:
# Ignoring generated ones with .py extension.
lint:
pylint -rn qiskit test tools
tools/verify_headers.py qiskit test tools examples
pylint -rn --disable='invalid-name, missing-module-docstring, redefined-outer-name' examples/python/*.py
tools/verify_headers.py qiskit test tools
tools/find_optional_imports.py
tools/find_stray_release_notes.py

# Only pylint on files that have changed from origin/main. Also parallelize (disables cyclic-import check)
lint-incr:
-git fetch -q https://github.com/Qiskit/qiskit-terra.git :lint_incr_latest
tools/pylint_incr.py -j4 -rn -sn --paths :/qiskit/*.py :/test/*.py :/tools/*.py
tools/pylint_incr.py -j4 -rn -sn --disable='invalid-name, missing-module-docstring, redefined-outer-name' --paths ':(glob,top)examples/python/*.py'
tools/verify_headers.py qiskit test tools examples
tools/verify_headers.py qiskit test tools
tools/find_optional_imports.py

ruff:
ruff qiskit test tools examples setup.py
ruff qiskit test tools setup.py

style:
black --check qiskit test tools examples setup.py
black --check qiskit test tools setup.py

black:
black qiskit test tools examples setup.py
black qiskit test tools setup.py

# Use the -s (starting directory) flag for "unittest discover" is necessary,
# otherwise the QuantumCircuit header will be modified during the discovery.
Expand Down
7 changes: 5 additions & 2 deletions crates/accelerate/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ num-traits = "0.2"
num-complex.workspace = true
rustworkx-core.workspace = true
num-bigint.workspace = true
faer = "0.19.3"
faer = "0.19.4"
itertools.workspace = true
qiskit-circuit.workspace = true
thiserror.workspace = true
ndarray_einsum_beta = "0.7"
once_cell = "1.20.0"
once_cell = "1.20.1"

[dependencies.smallvec]
workspace = true
Expand Down Expand Up @@ -61,3 +61,6 @@ features = ["macro"]

[dev-dependencies]
pyo3 = { workspace = true, features = ["auto-initialize"] }

[features]
cache_pygates = ["qiskit-circuit/cache_pygates"]
118 changes: 118 additions & 0 deletions crates/accelerate/src/barrier_before_final_measurement.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// This code is part of Qiskit.
//
// (C) Copyright IBM 2024
//
// This code is licensed under the Apache License, Version 2.0. You may
// obtain a copy of this license in the LICENSE.txt file in the root directory
// of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
//
// Any modifications or derivative works of this code must retain this
// copyright notice, and modified files need to carry a notice indicating
// that they have been altered from the originals.

use hashbrown::HashSet;
use pyo3::prelude::*;
use rustworkx_core::petgraph::stable_graph::NodeIndex;

use qiskit_circuit::circuit_instruction::ExtraInstructionAttributes;
use qiskit_circuit::dag_circuit::{DAGCircuit, NodeType};
use qiskit_circuit::imports::BARRIER;
use qiskit_circuit::operations::{Operation, PyInstruction};
use qiskit_circuit::packed_instruction::{PackedInstruction, PackedOperation};
use qiskit_circuit::Qubit;

static FINAL_OP_NAMES: [&str; 2] = ["measure", "barrier"];

#[pyfunction]
pub fn barrier_before_final_measurements(
py: Python,
dag: &mut DAGCircuit,
label: Option<String>,
) -> PyResult<()> {
let final_ops: HashSet<NodeIndex> = dag
.op_nodes(true)
.filter(|node| {
let NodeType::Operation(ref inst) = dag.dag()[*node] else {
unreachable!();
};
if !FINAL_OP_NAMES.contains(&inst.op.name()) {
return false;
}
let is_final_op = dag.bfs_successors(*node).all(|(_, child_successors)| {
!child_successors.iter().any(|suc| match dag.dag()[*suc] {
NodeType::Operation(ref suc_inst) => {
!FINAL_OP_NAMES.contains(&suc_inst.op.name())
}
_ => false,
})
});
is_final_op
})
.collect();
if final_ops.is_empty() {
return Ok(());
}
let ordered_node_indices: Vec<NodeIndex> = dag
.topological_op_nodes()?
.filter(|node| final_ops.contains(node))
.collect();
let final_packed_ops: Vec<PackedInstruction> = ordered_node_indices
.into_iter()
.map(|node| {
let NodeType::Operation(ref inst) = dag.dag()[node] else {
unreachable!()
};
let res = inst.clone();
dag.remove_op_node(node);
res
})
.collect();
let new_barrier = BARRIER
.get_bound(py)
.call1((dag.num_qubits(), label.as_deref()))?;

let new_barrier_py_inst = PyInstruction {
qubits: dag.num_qubits() as u32,
clbits: 0,
params: 0,
op_name: "barrier".to_string(),
control_flow: false,
#[cfg(feature = "cache_pygates")]
instruction: new_barrier.clone().unbind(),
#[cfg(not(feature = "cache_pygates"))]
instruction: new_barrier.unbind(),
};
let qargs: Vec<Qubit> = (0..dag.num_qubits() as u32).map(Qubit).collect();
#[cfg(feature = "cache_pygates")]
{
dag.apply_operation_back(
py,
PackedOperation::from_instruction(Box::new(new_barrier_py_inst)),
qargs.as_slice(),
&[],
None,
ExtraInstructionAttributes::new(label, None, None, None),
Some(new_barrier.unbind()),
)?;
}
#[cfg(not(feature = "cache_pygates"))]
{
dag.apply_operation_back(
py,
PackedOperation::from_instruction(Box::new(new_barrier_py_inst)),
qargs.as_slice(),
&[],
None,
ExtraInstructionAttributes::new(label, None, None, None),
)?;
}
for inst in final_packed_ops {
dag.push_back(py, inst)?;
}
Ok(())
}

pub fn barrier_before_final_measurements_mod(m: &Bound<PyModule>) -> PyResult<()> {
m.add_wrapped(wrap_pyfunction!(barrier_before_final_measurements))?;
Ok(())
}
Loading

0 comments on commit 00c9158

Please sign in to comment.