Skip to content

Commit

Permalink
Merge remote-tracking branch 'stable/1.3' into 'stable/1.4'
Browse files Browse the repository at this point in the history
With the release of Qiskit 1.3.3 the stable/1.3 branch should be
finished changing at this point. Before we prepare a 1.4.0 release we
need to make sure all the backported changes to 1.3 are included in 1.4.
This commit merges the contents of the 1.3 branch into the 1.4 branch.

The only conflicts were mainly on version numbers because the commits in
stable/1.3 including bumping the version strings on new bugfix releases.
The one real conflict was in the preset_passmanagers where some of the
constructor functions were in filter_warnings context managers and in
stable/1.3 the arguments passed to those functions changed.

This commit should be merged as a merge commit to preserve the git
history. This will require manual intervention at merge time.

Conflicts:
    Cargo.lock
    Cargo.toml
    docs/conf.py
    qiskit/VERSION.txt
    qiskit/transpiler/preset_passmanagers/builtin_plugins.py
  • Loading branch information
mtreinish committed Feb 20, 2025
2 parents 71eb989 + c99dd51 commit 08d6cec
Show file tree
Hide file tree
Showing 172 changed files with 3,029 additions and 1,181 deletions.
11 changes: 3 additions & 8 deletions .github/workflows/wheels-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,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,6 +121,7 @@ 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:
Expand Down Expand Up @@ -208,20 +209,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: actions/upload-artifact@v4
with:
path: ./wheelhouse/*.whl
Expand Down
12 changes: 6 additions & 6 deletions DEPRECATION.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Deprecation Policy

Starting from the 1.0.0 release, Qiskit follows semantic versioning, with a yearly release cycle for major releases.
Starting from the 1.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/open-source/qiskit-sdk-version-strategy).

This document is primarily intended for developers of Qiskit themselves.
Expand Down Expand Up @@ -150,11 +150,11 @@ and add the deprecation to that function's docstring so that it shows up in the
```python
from qiskit.utils.deprecation import deprecate_arg, deprecate_func

@deprecate_func(since="0.24.0", additional_msg="No replacement is provided.")
@deprecate_func(since="1.2", additional_msg="No replacement is provided.")
def deprecated_func():
pass

@deprecate_arg("bad_arg", new_alias="new_name", since="0.24.0")
@deprecate_arg("bad_arg", new_alias="new_name", since="1.2")
def another_func(bad_arg: str, new_name: str):
pass
```
Expand All @@ -178,7 +178,7 @@ import warnings
def deprecated_function():
warnings.warn(
"The function qiskit.deprecated_function() is deprecated since "
"Qiskit 0.44.0, and will be removed 3 months or more later. "
"Qiskit 1.2, and will be removed in 2.0 or a later major release."
"Instead, you should use qiskit.other_function().",
category=DeprecationWarning,
stacklevel=2,
Expand Down Expand Up @@ -235,9 +235,9 @@ def deprecated_function():
"""
Short description of the deprecated function.
.. deprecated:: 0.44.0
.. deprecated:: 1.2
The function qiskit.deprecated_function() is deprecated since
Qiskit 0.44.0, and will be removed 3 months or more later.
Qiskit 1.2, and will be removed in 2.0 or a later major release.
Instead, you should use qiskit.other_function().
<rest of the docstring>
Expand Down
39 changes: 18 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[![License](https://img.shields.io/github/license/Qiskit/qiskit.svg?)](https://opensource.org/licenses/Apache-2.0) <!--- long-description-skip-begin -->
[![Current Release](https://img.shields.io/github/release/Qiskit/qiskit.svg?logo=Qiskit)](https://github.com/Qiskit/qiskit/releases)
[![Extended Support Release](https://img.shields.io/github/v/release/Qiskit/qiskit?sort=semver&filter=0.*&logo=Qiskit&label=extended%20support)](https://github.com/Qiskit/qiskit/releases?q=tag%3A0)
<!-- [![Extended Support Release](https://img.shields.io/github/v/release/Qiskit/qiskit?sort=semver&filter=0.*&logo=Qiskit&label=extended%20support)](https://github.com/Qiskit/qiskit/releases?q=tag%3A0) -->
[![Downloads](https://img.shields.io/pypi/dm/qiskit.svg)](https://pypi.org/project/qiskit/)
[![Coverage Status](https://coveralls.io/repos/github/Qiskit/qiskit/badge.svg?branch=main)](https://coveralls.io/github/Qiskit/qiskit?branch=main)
![PyPI - Python Version](https://img.shields.io/pypi/pyversions/qiskit)
Expand All @@ -22,9 +22,6 @@ 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/migration-guides/qiskit-1.0-installation).
We encourage installing Qiskit via ``pip``:

```bash
Expand All @@ -40,30 +37,30 @@ 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
Expand All @@ -73,7 +70,7 @@ result = job.result()
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 +80,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 +93,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 Expand Up @@ -146,9 +143,9 @@ to the project at different levels. If you use Qiskit, please cite as per the in

The changelog for a particular release is dynamically generated and gets
written to the release page on Github for each release. For example, you can
find the page for the `0.46.0` release here:
find the page for the `1.2.0` release here:

<https://github.com/Qiskit/qiskit/releases/tag/0.46.0>
<https://github.com/Qiskit/qiskit/releases/tag/1.2.0>

The changelog for the current release can be found in the releases tab:
[![Releases](https://img.shields.io/github/release/Qiskit/qiskit.svg?style=flat&label=)](https://github.com/Qiskit/qiskit/releases)
Expand Down
36 changes: 18 additions & 18 deletions crates/accelerate/src/circuit_library/pauli_evolution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,22 +192,22 @@ fn multi_qubit_evolution(
/// followed by a CX-chain and then a single Pauli-Z rotation on the last qubit. Then the CX-chain
/// is uncomputed and the inverse basis transformation applied. E.g. for the evolution under the
/// Pauli string XIYZ we have the circuit
/// ┌───┐┌───────┐┌───┐
/// 0: ─────────────┤ X ├┤ Rz(2) ├┤ X ├──────────
/// ──────┐┌───┐└─┬─┘└───────┘└─┬─┘┌───┐┌────┐
/// 1: ┤ √Xdg ├┤ X ├──■─────────────■──┤ X ├┤ √X ├
/// ──────┘└─┬─┘ └─┬─┘└────┘
/// 2: ─────────────────────────────────┼────────
/// ┌───┐ │ │ ┌───┐
/// 3: ─┤ H ├────■───────────────────────■──┤ H ├─
/// ───┘ └───
///
/// ───┐ ┌───┐┌───────┐┌───┐┌───┐
/// 0: ┤ H ├──────┤ X ├┤ Rz(2) ├┤ X ├┤ H ├────────
/// └───┘ └─┬─┘└───────┘└─┬─┘└───┘
/// 1: ─────────────┼─────────────┼───────────────
/// ────┐┌───┐ │ │ ┌───┐┌──────
/// 2: ┤ √X ├┤ X ├──■─────────────■──┤ X ├┤ √Xdg ├
/// ────┘└─┬─┘ └─┬─┘└──────
/// 3: ────────■───────────────────────■──────────
///
/// Args:
/// num_qubits: The number of qubits in the Hamiltonian.
/// sparse_paulis: The Paulis to implement. Given in a sparse-list format with elements
/// ``(pauli_string, qubit_indices, coefficient)``. An element of the form
/// ``("IXYZ", [0,1,2,3], 0.2)``, for example, is interpreted in terms of qubit indices as
/// I_q0 X_q1 Y_q2 Z_q3 and will use a RZ rotation angle of 0.4.
/// ``(pauli_string, qubit_indices, rz_rotation_angle)``. An element of the form
/// ``("XIYZ", [0,1,2,3], 2)``, for example, is interpreted in terms of qubit indices as
/// X_q0 I_q1 Y_q2 Z_q3 and will use a RZ rotation angle of 2.
/// insert_barriers: If ``true``, insert a barrier in between the evolution of individual
/// Pauli terms.
/// do_fountain: If ``true``, implement the CX propagation as "fountain" shape, where each
Expand Down Expand Up @@ -244,7 +244,7 @@ pub fn py_pauli_evolution(
}

paulis.push(pauli);
times.push(time); // note we do not multiply by 2 here, this is done Python side!
times.push(time); // note we do not multiply by 2 here, this is already done Python side!
indices.push(tuple.get_item(1)?.extract::<Vec<u32>>()?)
}

Expand All @@ -266,12 +266,12 @@ pub fn py_pauli_evolution(
},
);

// When handling all-identity Paulis above, we added the time as global phase.
// However, the all-identity Paulis should add a negative phase, as they implement
// exp(-i t I). We apply the negative sign here, to only do a single (-1) multiplication,
// instead of doing it every time we find an all-identity Pauli.
// When handling all-identity Paulis above, we added the RZ rotation angle as global phase,
// meaning that we have implemented of exp(i 2t I). However, what we want it to implement
// exp(-i t I). To only use a single multiplication, we apply a factor of -0.5 here.
// This is faster, in particular as long as the parameter expressions are in Python.
if modified_phase {
global_phase = multiply_param(&global_phase, -1.0, py);
global_phase = multiply_param(&global_phase, -0.5, py);
}

CircuitData::from_packed_operations(py, num_qubits as u32, 0, evos, global_phase)
Expand Down
Loading

0 comments on commit 08d6cec

Please sign in to comment.