Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Rust-based OpenQASM 2 converter #9784

Merged
merged 28 commits into from
Apr 12, 2023

Commits on Mar 13, 2023

  1. 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.
    jakelishman committed Mar 13, 2023
    Configuration menu
    Copy the full SHA
    fccd043 View commit details
    Browse the repository at this point in the history

Commits on Mar 14, 2023

  1. 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.
    jakelishman committed Mar 14, 2023
    Configuration menu
    Copy the full SHA
    5723864 View commit details
    Browse the repository at this point in the history

Commits on Mar 15, 2023

  1. Remove unused import

    jakelishman committed Mar 15, 2023
    Configuration menu
    Copy the full SHA
    ea9d7b8 View commit details
    Browse the repository at this point in the history
  2. Configuration menu
    Copy the full SHA
    d730709 View commit details
    Browse the repository at this point in the history

Commits on Mar 17, 2023

  1. Tweak documentation

    jakelishman committed Mar 17, 2023
    Configuration menu
    Copy the full SHA
    02b3934 View commit details
    Browse the repository at this point in the history
  2. More specific PyO3 usage

    jakelishman committed Mar 17, 2023
    Configuration menu
    Copy the full SHA
    203c7bb View commit details
    Browse the repository at this point in the history
  3. Configuration menu
    Copy the full SHA
    f74c872 View commit details
    Browse the repository at this point in the history
  4. Configuration menu
    Copy the full SHA
    2fffb06 View commit details
    Browse the repository at this point in the history
  5. Format

    jakelishman committed Mar 17, 2023
    Configuration menu
    Copy the full SHA
    dedb720 View commit details
    Browse the repository at this point in the history

Commits on Mar 18, 2023

  1. Freeze dataclass

    jakelishman committed Mar 18, 2023
    Configuration menu
    Copy the full SHA
    b9b1276 View commit details
    Browse the repository at this point in the history
  2. 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.
    jakelishman committed Mar 18, 2023
    Configuration menu
    Copy the full SHA
    a95e8e4 View commit details
    Browse the repository at this point in the history

Commits on Mar 30, 2023

  1. Documentation tweaks

    jakelishman committed Mar 30, 2023
    Configuration menu
    Copy the full SHA
    6048257 View commit details
    Browse the repository at this point in the history
  2. Configuration menu
    Copy the full SHA
    9c28c1e View commit details
    Browse the repository at this point in the history
  3. Fix comments in lexer

    jakelishman committed Mar 30, 2023
    Configuration menu
    Copy the full SHA
    2eb339a View commit details
    Browse the repository at this point in the history
  4. Configuration menu
    Copy the full SHA
    d5d7115 View commit details
    Browse the repository at this point in the history
  5. Configuration menu
    Copy the full SHA
    3c0db61 View commit details
    Browse the repository at this point in the history
  6. Fixup release note

    jakelishman committed Mar 30, 2023
    Configuration menu
    Copy the full SHA
    46a62ea View commit details
    Browse the repository at this point in the history
  7. Fix handling of u0 gate

    jakelishman committed Mar 30, 2023
    Configuration menu
    Copy the full SHA
    fdc6a9d View commit details
    Browse the repository at this point in the history
  8. Configuration menu
    Copy the full SHA
    e9ffd41 View commit details
    Browse the repository at this point in the history
  9. Credit reviewers

    Co-authored-by: Luciano Bello <[email protected]>
    Co-authored-by: Kevin Hartman <[email protected]>
    Co-authored-by: Eric Arellano <[email protected]>
    4 people committed Mar 30, 2023
    Configuration menu
    Copy the full SHA
    af56d2b View commit details
    Browse the repository at this point in the history

Commits on Apr 3, 2023

  1. Configuration menu
    Copy the full SHA
    aebb86e View commit details
    Browse the repository at this point in the history

Commits on Apr 4, 2023

  1. 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.
    jakelishman committed Apr 4, 2023
    Configuration menu
    Copy the full SHA
    0816bfb View commit details
    Browse the repository at this point in the history
  2. Configuration menu
    Copy the full SHA
    1072db2 View commit details
    Browse the repository at this point in the history
  3. Credit Sasha

    Co-authored-by: Alexander Ivrii <[email protected]>
    jakelishman and alexanderivrii committed Apr 4, 2023
    Configuration menu
    Copy the full SHA
    eaa0aab View commit details
    Browse the repository at this point in the history

Commits on Apr 12, 2023

  1. Configuration menu
    Copy the full SHA
    2c54a1a View commit details
    Browse the repository at this point in the history
  2. Credit Matthew

    Co-authored-by: Matthew Treinish <[email protected]>
    jakelishman and mtreinish committed Apr 12, 2023
    Configuration menu
    Copy the full SHA
    bdd373e View commit details
    Browse the repository at this point in the history
  3. 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.
    jakelishman committed Apr 12, 2023
    Configuration menu
    Copy the full SHA
    5f74f1e View commit details
    Browse the repository at this point in the history
  4. Update PyO3 version

    jakelishman committed Apr 12, 2023
    Configuration menu
    Copy the full SHA
    f6f980b View commit details
    Browse the repository at this point in the history