Commit Graph

11 Commits

Author SHA1 Message Date
Matthew Treinish f409015bd7
Bump pyo3 and rust numpy version to 0.19.0 (#10186)
* Bump pyo3 and rust numpy version to 0.19.0

PyO3 0.19.0 and rust-numpy 0.19.0 were just released. This commit
updates the version used in qiskit to these latest releases. At the same
time this updates usage of text signature for classes that was
deprecated in the PyO3 0.19.0 release. While not fatal for normal builds
this would have failed clippy in CI because we treat warnings as errors.

* Apply suggestions from code review
2023-05-31 21:25:39 +00:00
Kevin J. Sung 06a5b9e00e
define __getstate__ and __setstate__ for OneQubitGateErrorMap (#10092)
* define __getstate__ and __setstate__ for OneQubitGateErrorMap

* add test

* fix test docstrings

* add assert in test

* add release note
2023-05-10 12:12:26 +00:00
Matthew Treinish 0e44c5e380
Fix interaction graph vf2 scoring to include 1q component (#10084)
* Fix interaction graph vf2 scoring to include 1q component

In #9148 a bug was introduced into the vf2 scoring code. In that PR the
vf2 passes were changed to treat standalone qubits as a special case to
improve the algorithmic efficiency of the pass. However, that PR
broke the scoring algorithm so that it was no longer factoring in the 1q
component of the interaction graph when scoring a layout. This meant
that when scoring a potential layout only the 2q error rates were been
factored into the score and the pass was potentially selecting worse
performing qubits. This commit fixes this error and ensures the scoring
is looking at all the error rates.

* Update qiskit/transpiler/passes/layout/vf2_utils.py
2023-05-08 14:52:10 +00:00
Matthew Treinish 908adb3432
Bump main branch version post 0.24.0rc1 tag (#10005)
Now that the first release candidate for the 0.24.0 release has been
tagged, the stable branch for the 0.24 series has been created and we
can start developing the 0.25.0 release on main. This commit bumps all
the version strings from 0.24.0 to 0.25.0 (and the backport branch for
mergify to 0.24) accordingly to differentiate the main branch from
0.24.*.
2023-04-20 21:58:50 +00:00
dependabot[bot] ccf78ae592
Bump pyo3 from 0.18.2 to 0.18.3 (#9964)
Bumps [pyo3](https://github.com/pyo3/pyo3) from 0.18.2 to 0.18.3.
- [Release notes](https://github.com/pyo3/pyo3/releases)
- [Changelog](https://github.com/PyO3/pyo3/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pyo3/pyo3/compare/v0.18.2...v0.18.3)

---
updated-dependencies:
- dependency-name: pyo3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-14 12:54:29 +00:00
Jake Lishman dec20b0139
Wrap io::Error in QASM2ParseError on failed file read (#9958)
Previously, if Python thought the target file for `qasm2.load` existed,
but Rust was unable to open it, the result `io:Error` would be
propagated up to Python space verbatim, and these situations usually
have confusing error messages.  This could happen, for example, if the
target was a directory on Windows.
2023-04-13 14:57:40 +00:00
Jake Lishman 73602b06d2
Add Rust-based OpenQASM 2 converter (#9784)
* Add Rust-based OpenQASM 2 converter

This is a vendored version of qiskit-qasm2
(https://pypi.org/project/qiskit-qasm2), with this initial commit being
equivalent (barring some naming / documentation / testing conversions to
match Qiskit's style) to version 0.5.3 of that package.

This adds a new translation layer from OpenQASM 2 to Qiskit, which is
around an order of magnitude faster than the existing version in Python,
while being more type safe (in terms of disallowing invalid OpenQASM 2
programs rather than attempting to construction `QuantumCircuit`s that
are not correct) and more extensible.

The core logic is a hand-written lexer and parser combination written in
Rust, which emits a bytecode stream across the PyO3 boundary to a small
Python interpreter loop.  The main bulk of the parsing logic is a simple
LL(1) recursive-descent algorithm, which delegates to more specific
recursive Pratt-based algorithm for handling classical expressions.

Many of the design decisions made (including why the lexer is written by
hand) are because the project originally started life as a way for me to
learn about implementations of the different parts of a parser stack;
this is the principal reason there are very few external crates used.
There are a few inefficiencies in this implementation, for example:

- the string interner in the lexer allocates twice for each stored
  string (but zero times for a lookup).  It may be possible to
  completely eliminate allocations when parsing a string (or a file if
  it's read into memory as a whole), but realistically there's only a
  fairly small number of different tokens seen in most OpenQASM 2
  programs, so it shouldn't be too big a deal.

- the hand-off from Rust to Python transfers small objects frequently.
  It might be more efficient to have a secondary buffered iterator in
  Python space, transferring more bytecode instructions at a time and
  letting Python resolve them.  This form could also be made
  asynchronous, since for the most part, the Rust components only need
  to acquire the CPython GIL at the API boundary.

- there are too many points within the lexer that can return a failure
  result that needs unwrapping at every site.  Since there are no tokens
  that can span multiple lines, it should be possible to refactor so
  that almost all of the byte-getter and -peeker routines cannot return
  error statuses, at the cost of the main lexer loop becoming
  responsible for advancing the line buffer, and moving the non-ASCII
  error handling into each token constructor.

I'll probably keep playing with some of those in the `qiskit-qasm2`
package itself when I have free time, but at some point I needed to draw
the line and vendor the package.  It's still ~10x faster than the
existing one:

    In [1]: import qiskit.qasm2
       ...: prog = """
       ...:     OPENQASM 2.0;
       ...:     include "qelib1.inc";
       ...:     qreg q[2];
       ...: """
       ...: prog += "rz(pi * 2) q[0];\ncx q[0], q[1];\n"*100_000
       ...: %timeit qiskit.qasm2.loads(prog)
       ...: %timeit qiskit.QuantumCircuit.from_qasm_str(prog)
    2.26 s ± 39.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
    22.5 s ± 106 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

`cx`-heavy programs like this one are actually the ones that the new
parser is (comparatively) slowest on, because the construction time of
`CXGate` is higher than most gates, and this dominates the execution
time for the Rust-based parser.

* Work around docs failure on Sphinx 5.3, Python 3.9

The version of Sphinx that we're constrained to use in the docs build
can't handle the `Unpack` operator, so as a temporary measure we can
just relax the type hint a little.

* Remove unused import

* Tweak documentation

* More specific PyO3 usage

* Use PathBuf directly for paths

* Format

* Freeze dataclass

* Use type-safe id types

This should have no impact on runtime or on memory usage, since each of
the new types has the same bit width and alignment as the `usize` values
they replace.

* Documentation tweaks

* Fix comments in lexer

* Fix lexing version number with separating comments

* Add test of pathological formatting

* Fixup release note

* Fix handling of u0 gate

* Credit reviewers

Co-authored-by: Luciano Bello <bel@zurich.ibm.com>
Co-authored-by: Kevin Hartman <kevin@hart.mn>
Co-authored-by: Eric Arellano <14852634+Eric-Arellano@users.noreply.github.com>

* Add test of invalid gate-body statements

* Refactor custom built-in gate definitions

The previous system was quite confusing, and required all accesses to
the global symbol table to know that the `Gate` symbol could be present
but overridable.  This led to confusing logic, various bugs and
unnecessary constraints, such as it previously being (erroneously)
possible to provide re-definitions for any "built-in" gate.

Instead, we keep a separate store of instructions that may be redefined.
This allows the logic to be centralised to only to the place responsible
for performing those overrides, and remains accessible for error-message
builders to query in order to provide better diagnostics.

* Credit Sasha

Co-authored-by: Alexander Ivrii <alexi@il.ibm.com>

* Credit Matthew

Co-authored-by: Matthew Treinish <mtreinish@kortar.org>

* Remove dependency on `lazy_static`

For a hashset of only 6 elements that is only checked once, there's not
really any point to pull in an extra dependency or use a hash set at
all.

* Update PyO3 version

---------

Co-authored-by: Luciano Bello <bel@zurich.ibm.com>
Co-authored-by: Kevin Hartman <kevin@hart.mn>
Co-authored-by: Eric Arellano <14852634+Eric-Arellano@users.noreply.github.com>
Co-authored-by: Alexander Ivrii <alexi@il.ibm.com>
Co-authored-by: Matthew Treinish <mtreinish@kortar.org>
2023-04-12 16:00:54 +00:00
dependabot[bot] aacbc665d8
Bump pyo3 from 0.18.1 to 0.18.2 (#9854)
Bumps [pyo3](https://github.com/pyo3/pyo3) from 0.18.1 to 0.18.2.
- [Release notes](https://github.com/pyo3/pyo3/releases)
- [Changelog](https://github.com/PyO3/pyo3/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pyo3/pyo3/compare/v0.18.1...v0.18.2)

---
updated-dependencies:
- dependency-name: pyo3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-27 19:13:15 +00:00
Jake Lishman 5a9d04156c
Remove useless `into_iter()` on `Range` (#9806)
Clippy has started complaining about this on the stable branch, and it's
probably correct to do so.
2023-03-16 18:50:07 +00:00
Matthew Treinish bbd023b5e1
Leverage Rust circuit sequence construction for `OneQubitEulerDecomposer` (#9583)
* Leverage Rust circuit sequence construction for OneQubitEulerDecomposer

This commit is a follow-up to #9578 which added a rust implementation
of the second half of the single qubit euler decomposition routines and
leveraged them for the Optimize1qGatesDecomposition transpiler pass.
With that PR the Optimize1qGatesDecomposition no longer was dependent on
the OneQubitEulerDecomposer class. This commit continues from that PR
and updates the OneQubitEulerDecomposer to leverage the same Rust
implementation internally. Calling a decomposer object will internally
call the rust function to generate a circuit sequence and then return
either a QuantumCircuit or DAGCircuit (depending on the options).
Similarly all the angle computation is done directly in Rust.

* Add missing atol clamping to mod_2pi

The python version of the OneQubitEulerDecomposer class had atol
clamping on it's output from mod_2pi, when this function was ported to
rust this was not included. At the time it was because nothing set the
atol parameter when calling mod_2pi (the angle calculation in #9185 did
not have atol and the expansion to construct circuits for
Optimize1qGatesDecomposition always used the default value). However,
now that we're expanding OneQubitEulerDecomposer to internally do all
the calculations in rust we need to support an adjustable atol which
includes the missing endpoint clamping in mod_2pi. This commit adds this
missing functionality to the function.

* Add docstring to mod_2pi rust function

* Remove mod_2pi python function
2023-03-16 18:44:44 +00:00
Jake Lishman c6cd0d577b
Add structure for multiple Rust crates (#9742)
* Add structure for multiplie Rust extension crates

This is a precursor to adding an entirely separate and self-contained
crate to handle parsing of OpenQASM 2 (not 3 - this is kind of like a
trial run for that).  It could conceivably still live within
`qiskit._accelerate`, but having separate crates helps us enforce more
sane API barriers, and has improvements in the incremental build time
when working on only one of the Rust extensions.

The intent after this commit is still to have `qiskit._accelerate` as an
easy catch-all for accelerators for Python.  Developers should not need
to be concerned with defining a new crate for every new feature, and for
the most part `_accelerate` is still logically interoperative within
itself (for example, `NLayout` is used all over).  This is just laying
out the groundwork so more complex crate additions _can_ also be made.

Some of the niceties to do with Cargo workspaces only became stabilised
in Rust 1.64.  In particular, inheritance from the workspace root for
things like the package version, Rust version, and dependencies only
came in then.  For now, the `workspace.packages` key in the root
`Cargo.toml` is ignored with a small warning during the build, but I've
put it in place mostly to keep track of what we can change once the MSRV
becomes 1.64 or greater (likely not til at least Terra 0.26).

* Add README.md to crates/accelerate

* Correct licence metadata
2023-03-07 23:12:39 +00:00