Skip to content

Commit

Permalink
Merge branch 'main' into split_2q_swap_unitaries
Browse files Browse the repository at this point in the history
  • Loading branch information
gadial authored Jan 21, 2025
2 parents 1d7b4f6 + a7df171 commit ea5e164
Show file tree
Hide file tree
Showing 257 changed files with 3,698 additions and 2,238 deletions.
57 changes: 8 additions & 49 deletions .github/workflows/wheels-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,6 @@ on:
default: "default"
required: false

wheels-32bit:
description: >-
The action to take for Tier 1 wheels.
Choose from 'default', 'build' or 'skip'.
This builds multiple artifacts, which all match 'wheels-32bit-*'.
type: string
default: "default"
required: false

wheels-linux-s390x:
description: >-
The action to take for Linux s390x wheels.
Expand Down Expand Up @@ -69,7 +60,7 @@ on:
python-version:
description: "The Python version to use to host the build runner."
type: string
default: "3.10"
default: "3.13"
required: false

pgo:
Expand All @@ -90,7 +81,7 @@ jobs:
os:
- ubuntu-latest
# Used for the x86_64 builds.
- macos-12
- macos-13
# Used for the ARM builds.
- macos-14
- windows-latest
Expand Down Expand Up @@ -121,44 +112,18 @@ jobs:
cat >>"$GITHUB_ENV" <<EOF
CIBW_BEFORE_BUILD=bash ./tools/build_pgo.sh $PGO_WORK_DIR $PGO_OUT_PATH
CIBW_ENVIRONMENT=RUSTUP_TOOLCHAIN=stable RUSTFLAGS='-Cprofile-use=$PGO_OUT_PATH -Cllvm-args=-pgo-warn-missing-function'
CIBW_ENVIRONMENT_MACOS=MACOSX_DEPLOYMENT_TARGET='10.12' RUSTUP_TOOLCHAIN=stable RUSTFLAGS='-Cprofile-use=$PGO_OUT_PATH -Cllvm-args=-pgo-warn-missing-function'
CIBW_ENVIRONMENT_LINUX=RUSTUP_TOOLCHAIN=stable RUSTFLAGS='-Cprofile-use=$PGO_OUT_PATH -Cllvm-args=-pgo-warn-missing-function' PATH="\$PATH:\$HOME/.cargo/bin" CARGO_NET_GIT_FETCH_WITH_CLI="true"
EOF
env:
PGO_WORK_DIR: ${{ github.workspace }}/pgo-data
PGO_OUT_PATH: ${{ github.workspace }}/merged.profdata
- uses: pypa/cibuildwheel@v2.21.3
- uses: pypa/cibuildwheel@v2.22.0
- uses: actions/upload-artifact@v4
with:
path: ./wheelhouse/*.whl
name: ${{ inputs.artifact-prefix }}wheels-tier-1-${{ matrix.os }}

wheels-32bit:
name: "Wheels / 32bit"
if: (inputs.wheels-32bit == 'default' && inputs.default-action || inputs.wheels-32bit) == 'build'
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- windows-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ inputs.python-version }}
- uses: dtolnay/rust-toolchain@stable
with:
components: llvm-tools-preview
- name: Build wheels
uses: pypa/cibuildwheel@v2.21.3
env:
CIBW_SKIP: 'pp* cp36-* cp37-* cp38-* *musllinux* *amd64 *x86_64'
- uses: actions/upload-artifact@v4
with:
path: ./wheelhouse/*.whl
name: ${{ inputs.artifact-prefix }}wheels-32bit-${{ matrix.os }}

wheels-linux-s390x:
name: "Wheels / Linux s390x"
if: (inputs.wheels-linux-s390x == 'default' && inputs.default-action || inputs.wheels-linux-s390x) == 'build'
Expand All @@ -173,7 +138,7 @@ jobs:
- uses: docker/setup-qemu-action@v3
with:
platforms: all
- uses: pypa/cibuildwheel@v2.21.3
- uses: pypa/cibuildwheel@v2.22.0
env:
CIBW_ARCHS_LINUX: s390x
CIBW_TEST_SKIP: "cp*"
Expand All @@ -196,7 +161,7 @@ jobs:
- uses: docker/setup-qemu-action@v3
with:
platforms: all
- uses: pypa/cibuildwheel@v2.21.3
- uses: pypa/cibuildwheel@v2.22.0
env:
CIBW_ARCHS_LINUX: ppc64le
CIBW_TEST_SKIP: "cp*"
Expand All @@ -208,20 +173,14 @@ jobs:
wheels-linux-aarch64:
name: "Wheels / Linux AArch64"
if: (inputs.wheels-linux-aarch64 == 'default' && inputs.default-action || inputs.wheels-linux-aarch64) == 'build'
runs-on: ubuntu-latest
runs-on: ubuntu-24.04-arm
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ inputs.python-version }}
- uses: dtolnay/rust-toolchain@stable
- uses: docker/setup-qemu-action@v3
with:
platforms: all
- uses: pypa/cibuildwheel@v2.21.3
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: pypa/cibuildwheel@v2.22.0
- uses: actions/upload-artifact@v4
with:
path: ./wheelhouse/*.whl
Expand Down
2 changes: 0 additions & 2 deletions .github/workflows/wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ jobs:
artifact-prefix: "deploy-core-"
default-action: "skip"
wheels-tier-1: "build"
wheels-32bit: "build"
sdist: "build"
upload-core:
name: Deploy core
Expand All @@ -39,7 +38,6 @@ jobs:
artifact-prefix: "deploy-others-"
default-action: "build"
wheels-tier-1: "skip"
wheels-32bit: "skip"
sdist: "skip"
upload-others:
name: Deploy other
Expand Down
14 changes: 7 additions & 7 deletions Cargo.lock

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

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ license = "Apache-2.0"
#
# Each crate can add on specific features freely as it inherits.
[workspace.dependencies]
bytemuck = "1.20"
indexmap.version = "2.6.0"
bytemuck = "1.21"
indexmap.version = "2.7.1"
hashbrown.version = "0.14.5"
num-bigint = "0.4"
num-complex = "0.4"
Expand Down
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,15 @@ lint:
tools/verify_headers.py qiskit test tools
tools/find_optional_imports.py
tools/find_stray_release_notes.py
tools/verify_images.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/verify_headers.py qiskit test tools
tools/find_optional_imports.py
tools/verify_images.py

ruff:
ruff qiskit test tools setup.py
Expand Down
32 changes: 16 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,40 +40,40 @@ To install from source, follow the instructions in the [documentation](https://d
Now that Qiskit is installed, it's time to begin working with Qiskit. The essential parts of a quantum program are:
1. Define and build a quantum circuit that represents the quantum state
2. Define the classical output by measurements or a set of observable operators
3. Depending on the output, use the primitive function `sampler` to sample outcomes or the `estimator` to estimate values.
3. Depending on the output, use the Sampler primitive to sample outcomes or the Estimator primitive to estimate expectation values.

Create an example quantum circuit using the `QuantumCircuit` class:

```python
import numpy as np
from qiskit import QuantumCircuit

# 1. A quantum circuit for preparing the quantum state |000> + i |111>
qc_example = QuantumCircuit(3)
qc_example.h(0) # generate superpostion
qc_example.p(np.pi/2,0) # add quantum phase
qc_example.cx(0,1) # 0th-qubit-Controlled-NOT gate on 1st qubit
qc_example.cx(0,2) # 0th-qubit-Controlled-NOT gate on 2nd qubit
# 1. A quantum circuit for preparing the quantum state |000> + i |111> / √2
qc = QuantumCircuit(3)
qc.h(0) # generate superposition
qc.p(np.pi / 2, 0) # add quantum phase
qc.cx(0, 1) # 0th-qubit-Controlled-NOT gate on 1st qubit
qc.cx(0, 2) # 0th-qubit-Controlled-NOT gate on 2nd qubit
```

This simple example makes an entangled state known as a [GHZ state](https://en.wikipedia.org/wiki/Greenberger%E2%80%93Horne%E2%80%93Zeilinger_state) $(|000\rangle + i|111\rangle)/\sqrt{2}$. It uses the standard quantum gates: Hadamard gate (`h`), Phase gate (`p`), and CNOT gate (`cx`).
This simple example creates an entangled state known as a [GHZ state](https://en.wikipedia.org/wiki/Greenberger%E2%80%93Horne%E2%80%93Zeilinger_state) $(|000\rangle + i|111\rangle)/\sqrt{2}$. It uses the standard quantum gates: Hadamard gate (`h`), Phase gate (`p`), and CNOT gate (`cx`).

Once you've made your first quantum circuit, choose which primitive function you will use. Starting with `sampler`,
Once you've made your first quantum circuit, choose which primitive you will use. Starting with the Sampler,
we use `measure_all(inplace=False)` to get a copy of the circuit in which all the qubits are measured:

```python
# 2. Add the classical output in the form of measurement of all qubits
qc_measured = qc_example.measure_all(inplace=False)
qc_measured = qc.measure_all(inplace=False)

# 3. Execute using the Sampler primitive
from qiskit.primitives import StatevectorSampler
sampler = StatevectorSampler()
job = sampler.run([qc_measured], shots=1000)
result = job.result()
print(f" > Counts: {result[0].meas.get_counts()}")
print(f" > Counts: {result[0].data["meas"].get_counts()}")
```
Running this will give an outcome similar to `{'000': 497, '111': 503}` which is `000` 50% of the time and `111` 50% of the time up to statistical fluctuations.
To illustrate the power of Estimator, we now use the quantum information toolbox to create the operator $XXY+XYX+YXX-YYY$ and pass it to the `run()` function, along with our quantum circuit. Note the Estimator requires a circuit _**without**_ measurement, so we use the `qc_example` circuit we created earlier.
To illustrate the power of the Estimator, we now use the quantum information toolbox to create the operator $XXY+XYX+YXX-YYY$ and pass it to the `run()` function, along with our quantum circuit. Note that the Estimator requires a circuit _**without**_ measurements, so we use the `qc` circuit we created earlier.

```python
# 2. Define the observable to be measured
Expand All @@ -83,7 +83,7 @@ operator = SparsePauliOp.from_list([("XXY", 1), ("XYX", 1), ("YXX", 1), ("YYY",
# 3. Execute using the Estimator primitive
from qiskit.primitives import StatevectorEstimator
estimator = StatevectorEstimator()
job = estimator.run([(qc_example, operator)], precision=1e-3)
job = estimator.run([(qc, operator)], precision=1e-3)
result = job.result()
print(f" > Expectation values: {result[0].data.evs}")
```
Expand All @@ -96,17 +96,17 @@ The power of quantum computing cannot be simulated on classical computers and yo
However, running a quantum circuit on hardware requires rewriting to the basis gates and connectivity of the quantum hardware.
The tool that does this is the [transpiler](https://docs.quantum.ibm.com/api/qiskit/transpiler), and Qiskit includes transpiler passes for synthesis, optimization, mapping, and scheduling.
However, it also includes a default compiler, which works very well in most examples.
The following code will map the example circuit to the `basis_gates = ['cz', 'sx', 'rz']` and a linear chain of qubits $0 \rightarrow 1 \rightarrow 2$ with the `coupling_map =[[0, 1], [1, 2]]`.
The following code will map the example circuit to the `basis_gates = ["cz", "sx", "rz"]` and a linear chain of qubits $0 \rightarrow 1 \rightarrow 2$ with the `coupling_map = [[0, 1], [1, 2]]`.

```python
from qiskit import transpile
qc_transpiled = transpile(qc_example, basis_gates = ['cz', 'sx', 'rz'], coupling_map =[[0, 1], [1, 2]] , optimization_level=3)
qc_transpiled = transpile(qc, basis_gates=["cz", "sx", "rz"], coupling_map=[[0, 1], [1, 2]], optimization_level=3)
```

### Executing your code on real quantum hardware

Qiskit provides an abstraction layer that lets users run quantum circuits on hardware from any vendor that provides a compatible interface.
The best way to use Qiskit is with a runtime environment that provides optimized implementations of `sampler` and `estimator` for a given hardware platform. This runtime may involve using pre- and post-processing, such as optimized transpiler passes with error suppression, error mitigation, and, eventually, error correction built in. A runtime implements `qiskit.primitives.BaseSamplerV2` and `qiskit.primitives.BaseEstimatorV2` interfaces. For example,
The best way to use Qiskit is with a runtime environment that provides optimized implementations of Sampler and Estimator for a given hardware platform. This runtime may involve using pre- and post-processing, such as optimized transpiler passes with error suppression, error mitigation, and, eventually, error correction built in. A runtime implements `qiskit.primitives.BaseSamplerV2` and `qiskit.primitives.BaseEstimatorV2` interfaces. For example,
some packages that provide implementations of a runtime primitive implementation are:

* https://github.com/Qiskit/qiskit-ibm-runtime
Expand Down
27 changes: 12 additions & 15 deletions crates/accelerate/src/barrier_before_final_measurement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,24 +30,21 @@ pub fn barrier_before_final_measurements(
dag: &mut DAGCircuit,
label: Option<String>,
) -> PyResult<()> {
let is_exactly_final = |inst: &PackedInstruction| FINAL_OP_NAMES.contains(&inst.op.name());
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;
.filter_map(|(node, inst)| {
if !is_exactly_final(inst) {
return None;
}
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,
dag.bfs_successors(node)
.all(|(_, child_successors)| {
child_successors.iter().all(|suc| match dag[*suc] {
NodeType::Operation(ref suc_inst) => is_exactly_final(suc_inst),
_ => true,
})
})
});
is_final_op
.then_some(node)
})
.collect();
if final_ops.is_empty() {
Expand All @@ -60,7 +57,7 @@ pub fn barrier_before_final_measurements(
let final_packed_ops: Vec<PackedInstruction> = ordered_node_indices
.into_iter()
.map(|node| {
let NodeType::Operation(ref inst) = dag.dag()[node] else {
let NodeType::Operation(ref inst) = dag[node] else {
unreachable!()
};
let res = inst.clone();
Expand Down
Loading

0 comments on commit ea5e164

Please sign in to comment.