Skip to content

Commit

Permalink
feat!: Program and Instruction APIs are backed by quil-rs (#1639)
Browse files Browse the repository at this point in the history
* Foundational support for implementing Program with qcs-sdk-python (#1518)

* tear out members, start replacing with rust API (WIP)

* first pass as integrating with qcs_sdk.quil

* fix low hanging fruit, introduce snapshot testing for passing tests,
annotate others with improvements that need to be made

* update poetry.lock

* more test annotations, fixes, snapshots

* deprecation warnings and cleanup

* Gate tests and snapshots, pre-replacement with quil-rs

* add test for FORKED gate

* back Gate with RSGate

* fix deprecated notice

* test improvements

* more cleanup

* various cleanups

* add more snaps

* clean up program per feedback

* feat!: The `calibrations` method on `Program` now only returns `DefCalibration`s. A `Program`s the `DefMeasureCalibrations` can be retrieved via the new `measure_calibrations` method.

* update instruction handling logic

* deprecate valid protoquil/quilt methods

* add compatibility layer by overriding quil_rs.Gate superclass methods

* remove gate __init__ method

* remove old comments

* revert defcal changes

* safer type checking on conversion methods

* simplify ParameterDesignator Type

* forbidden metaclass shenanigans

* Update pyquil/quil.py

Co-authored-by: Kalan <22137047+kalzoo@users.noreply.github.com>

* use deprecated decorator

* update qcs-sdk-python dependency spec

---------

Co-authored-by: Kalan <22137047+kalzoo@users.noreply.github.com>

* V4 Setters for the Gate class (#1535)

* add and test setters

* use simple enum syntax

* Use quil_rs for Calibrations (#1536)

* setup test suite for DefCalibration

* back DefCalibration with quil_rs.Calibration

* fix metaclass implementation so all instruction types aren't recognized
as the same

* back DefCalibration with quil_rs.Calibration

* setup DefMeasureCalibration tests

* back DefMeasureCalibration with quil_rs.MeasureCalibrationDefinition

* gate calibrations with quil_rs

* more efficient handling of calibrations

* setup Measurement tests

* back Measurement with quil_rs

* use calibration set api for calibrations

* BREAKING CHANGE: DefMeasureCalibration now requires a MemoryReference

* update tests

* cleanup stale todos, match calibration logic

* type hints for tests

* remove redundant guard in match_calibrations

Co-authored-by: Kalan <22137047+kalzoo@users.noreply.github.com>

---------

Co-authored-by: Kalan <22137047+kalzoo@users.noreply.github.com>

* Re-write `get_classical_addresses_from_quil_program` to use `quil-rs` (#1541)

* BREAKING CHANGE: DefFrame and Frame are no longer dataclasses

We've removed the @DataClass decorator from `DefFrame` and `Frame`. `Frame`s properties can now be edited. Most functionality should have been re-implemented, but breakages may be possible, depending on how much of the @DataClass functionality was being leveraged.

* Use quil-rs FrameSet API and compatibility layer (#1543)

* setup Frame and DefFrame test suites

* add eq test

* back Frame with quil_rs FrameDefinition

* back DefFrame with quil_rs.FrameDefinition

* fix flaky DefFrame snapshot tests

* cleanup imports

* "unfreeze" Frame properties

* use FrameSet API and compatibility layer, with tests

* update calibrations property as well

* center_frequency -> CENTER-FREQUENCY

* fix attribute names in DefFrame

* update snapshot

* BREAKING CHANGE: Setting the offsets property on `Declare` will raise a `ValueError` if no shared_region is set.

* setup tests for Declare

* BREAKING CHANGE: Setting the offsets property on ``Declare`` will raise
if no shared_region is set.

* update tests

* add note

* trust truthy/falsy values

* BREAKING CHANGE: A `Program` that uses qubit or label placeholders cannot be pickled

* V4 Program API: Back GateDef with GateDefinition (#1549)

* setup DefGate test suite

* add baseline tests for permutation and pauli gates

* compatibility for paulis, expressions, back DefGate with GateDefinition

* back DefPermutationGate with quil-rs

* back DefGateByPaulis w/ quil-rs

* better support Expressions

* dont try to support Expressions

* cleanup

* update tests

* combine int, float, and complex conversion

* feat: Add DefCircuit

* setup DefWaveform tests

* back DefWaveform with quil-rs

* update snapshot

* clean up redudnant import

* implement DefCircuit using quil-rs

* add DefCircuit|Waveform to py instruction conversion method

* update snapshot after instruction indentation fix

* V4 Instruction API: Pragma, Reset, Fence, Delay (#1551)

* setup Pragma tests

* setup tests for Qubit

* setup tests for Fence

* back Pragma with quil_rs.Pragma

* back Reset, ResetQubit, with quil-rs

* Back Delay(Frames|Qubits) with quil-rs

* update Delay implementation per feedback

* back Fence, FenceAll, with quil-rs

* remove unused snapshots, prints

* update convers to rs/py instruction functions

* better type for numpy numbers

* cleanup, and assert ResetQubit qubit is not None

* BREAKING CHANGE: The `pop` method has been removed from `Program`

* remove to_headers

* BREAKING CHANGE: The `pop` method has been removed from `Program`

* remove to_headers arg

* * BREAKING CHANGE: `TemplateWaveform` and its subclasses are no longer dataclasses. Most important functionality has been replaced so this change should be transparent for most use cases.

* setup tests for Capture

* setup tests for Pulse

* create tests for RawCapture

* add tests for template waveforms

* add compatibility layer for TemplateWaveforms

* back Capture with quil_rs

* back Pulse with quil_rs

* back RawCapture with quil_rs

* BREAKING CHANGE: `TemplateWaveform` and its subclasses are no longer
dataclasses. Most important functionality has been replaced so this
change should be transparent for most use cases.

* deprecation warning for TemplateWaveform and its subclasses, direct to
new WaveformInvocation class

* BREAKING CHANGE: SwapPhase has been renamed to SwapPhases

* setup up tests for set/shift instructions

* setup tests for SwapPhase

* back frame mutation instructions with quil-rs

* back SwapPhase with quil-rs

* formatting

* BREAKING CHANGE: SwapPhase has been renamed to SwapPhases

* V4: Deprecate format parameter (#1566)

* update mypy, fix various lints, deprecate format_parameter

* returns variable length tuple

* a few more lints

* more lints

* cant isinstance check with generics

* V4: The rest of the non control-flow instructions (#1568)

* ClassicalConvert tests

* tests for Classical(Exchange|Load|Move)

* ClassicalStore tests

* test ClassicalComparison classes

* test UnaryClassicalInstructions

* Include implementation and test

* Wait, Halt, Nop test and implementation

* implement ClassicalConvert

* re-implement ClassicalLoad

* re-implement ClassicalStore

* re-implement ClassicalComparison

* re-implement Exchange

* re-implement ClassicalUnary

* back ClassicalMove, ClassicalExchange with quil-rs

* fix recursive implementation of SimpleInstruction.__str__

* fix!: The `get_qubits` method on a `Gate` now returns a list so that
ordering is always guaranteed.

* update snapshots for test_main

* add test annotations for test_noise.py

* account for integer qubit in pragma arguments

* Instruction API for BinaryOperations

* update noise tests

* resolve issues in test_quil.py, or update todo annotation

* update rewrite_arithmetic

* fix parser tests

* annotate test_paulis_with_placeholders

* update test_quantum_computer

* annotate/fix test_quilt.py

* update snapshots

* BREAKING CHANGE: fill_placeholders has been removed as it is no longer
used to expand calibrations

* bump quil version

* fix some tests

* chore! Remove `parser` module (#1618)

* chore!: Remove `parser` module. A `Program` can instead be constructed from a
Quil program string directly. The full list of `AbstractInstruction`s is
available on the `instructions` property.

* fix flaky test

* add parantheses to assertion

* V4 Program API: De-dupe definitions when adding instructions to a Program (#1625)

* wip - de-dupe based on abstract instruction

* normalize incoming instructions ot quil-rs types

* a lil more cleanup

* update docstrings

* bump qcs-sdk-python/quil

* V4 Program API - Placeholders and Control Flow (#1633)

* use to_quil() in out() methods

* simplify inst

* fix test_quilbase tests

* fix other failing tests

* make instructions consistent with v3 implementation

* back Label with quil_rs

* back LabelPlaceholder with quil_rs

* back QubitPlaceholders with quil_rs

* fix off by 1 in test

* checkpoint: update/fix many tests

* checkpoint: all tests passing!

* use renamed method

* some mypy fixes

* replace deprecation with deprecated

* import sphinx decorator

* fix mypy lints and dangling todos

* get docs building

* fix doctests

* update doctests

* simplify pauli from_list

* instrucion->instruction

* use body_instructions property

* update a few old references to instructions

* one more

* add resolve_placeholders_with_custom_resolvers method

* various small fixes

* Remove support for QubitPlaceholders as Pragma arguments

* fix typo

Co-authored-by: Kalan <22137047+kalzoo@users.noreply.github.com>

* Update CHANGELOG.md

Co-authored-by: Kalan <22137047+kalzoo@users.noreply.github.com>

* Update CHANGELOG.md

Co-authored-by: Kalan <22137047+kalzoo@users.noreply.github.com>

* Update CHANGELOG.md

Co-authored-by: Kalan <22137047+kalzoo@users.noreply.github.com>

* Update CHANGELOG.md

Co-authored-by: Kalan <22137047+kalzoo@users.noreply.github.com>

* remove duplicate entry

* ignore sphinx warnings

* grammar

* update qcs-sdk-python

---------

Co-authored-by: Kalan <22137047+kalzoo@users.noreply.github.com>

* satisfy lints

* impl repr

* type hint capitalization

* add HALT back in

* update dev dependencies, quiet down internal depreaction warnings in
test suite

* update CHANGELOG

* more changelog tweaks

* explicitly specify `toml` as a dev dependency

---------

Co-authored-by: Kalan <22137047+kalzoo@users.noreply.github.com>
  • Loading branch information
MarquessV and kalzoo committed Aug 30, 2023
1 parent 721698f commit 4f47c12
Show file tree
Hide file tree
Showing 58 changed files with 6,295 additions and 4,461 deletions.
35 changes: 34 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,27 @@ The 4.0 release of pyQuil migrates its core functionality into Rigetti's latest
- Python 3.7 is no longer supported.
- The environment variable overrides for `quilc` and `QVM` URLs have been renamed to `QCS_APPLICATIONS_QUILC_URL` and `QCS_APPLICATIONS_QVM_URL`, respectively.
- The `QuantumComputer`'s `run` method now takes an optional `memory_map` parameter. This mapping takes memory region names to a list of values to use for a run. This replaces the ability to use `write_memory` on `Program`s.
- `Pragma("DELAY", ...)` will now raise a parser error because it generates invalid Quil. Use the `Delay` instruction instead.
- `Program` and instructions have been re-written using the `quil` package. Much of the API remains the same, with the following exceptions:
- `SwapPhase` has been renamed to `SwapPhases`
- `TemplateWaveform` and its subclasses are no longer `@dataclass`es.
- `DefFrame` and `Frame` are no longer `@dataclass`es.
- The `pop` method has been removed from `Program`.
- A `Program` that uses `QubitPlaceholder`s or `LabelPlaceholder`s can no longer be pickled
- `DefMeasureCalibration` now requires a `MemoryReference`.
- `fill_placeholders` has been removed since it is no longer needed to expand calibrations.
- The `get_qubits` method on `Gate` now returns a `list` so that ordering is guaranteed.
- Setting the `offsets` property on `Declare` will raise a `ValueError` if no `shared_region` is set.
- When converting to Quil, a `Program` automatically places `DECLARE`s at the top of the program.
- The `parser` module has been removed. Parsing now happens by initializing a `Program` with the program string you want to be parsed.
- `PRAGMA` instructions can no longer have a directive that conflicts with a Quil keyword. If you were using directives like `DELAY` or `FENCE`, consider using the respective Quil-T instructions instead.
- `QubitPlaceholders` can no longer be used in `PRAGMA` instructions.
- `DefGate` and the other gate definition instructions will no longer accept names that conflict with Quil keywords.
- `Program#get_qubits()` will raise a `TypeError` if any of the qubits in the program are not a fixed index.
- A `Program`s `LabelPlaceholder`s are no longer resolved automatically when getting its instructions. Use the `resolve_label_placeholders` method to do it explicitly. Note that the `if_then` and `while_do` methods will add `LabelPlaceholder`s to your program.
- There may be some minor differences in how instructions are converted to a Quil string. These differences should only be cosmetic and should not affect the behavior of a program. However, they may break unit tests or other code that rely on specific formatting of programs.
- The `pyquil.quil.get_default_qubit_mapping` function for getting a mapping of `QubitPlaceholders` to resolved indices has been removed. Generating a default mapping is handled automatically by the placeholder resolving methods.
- The `JumpConditional` base class has been removed, use `JumpWhen` and/or `JumpUnless` directly instead.
- The `Program` class automatically sorts `DECLARE` instructions to the top of the Program when converting to Quil.

### Features

Expand All @@ -24,11 +44,24 @@ The 4.0 release of pyQuil migrates its core functionality into Rigetti's latest
- The new `QPUCompilerAPIOptions` class provides can now be used to customize how a program is compiled against a QPU.
- The `diagnostics` module has been introduced with a `get_report` function that will gather information on the currently running pyQuil
installation, perform diagnostics checks, and return a summary.
- `Program` has new methods for resolving Qubit and Label Placeholders in a program.
- `QubitPlaceholders` can now be used in programs that also use fixed or variable qubits.
- `QAMExecutionResult` now has a `raw_readout_data` property that can be used to get the raw form of readout data returned from the executor.
- `WaveformInvocation` has been added as a simpler, more flexible class for invoking waveforms.
- Added two new instruction classes:
- The `Include` class for `INCLUDE` instructions.
- The `DefCircuit` class `DEFCIRCUIT` instructions.
- The `Program.copy` method now performs a deep copy.

### Deprecations

- The `QAMExecutionResult` `readout_data` property has been deprecated to avoid confusion with the new `raw_readout_data` property. Use the `register_map` property instead.
- The `indices` flag on the `get_qubits` method on `Program`s and instruction classes continues to work, but will be removed in future versions. A separate `get_qubit_indices` method has been added to get indices. In future versions, `get_qubits` will only return a list of `QubitDesignator`s.
- The `is_protoquil`, `is_supported_on_qpu` methods on `Program` and the `validate_supported_quil` function will always return `True`. These methods were never reliable as they were implemented as client-side checks that don't necessarily reflect the latest available features on Rigetti compilers or QPUs. It's safe to stop using these functions and rely on the API to tell you if a program isn't supported.
- `percolate_declares` is a no-op and will be removed in future versions. `Program` now “percolates” declares automatically.
- `merge_programs` continues to work, but will be removed in future versions, use `Program` addition instead.
- The `format_parameter` function continues to work, but will be removed in future versions.
- The `WaveformReference` and `TemplateWaveform` classes continue to work, but will be removed in future versions. The new `WaveformInvocation` should be used instead.

## 3.5.4

Expand Down
44 changes: 22 additions & 22 deletions docs/source/advanced_usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -146,15 +146,13 @@ where using ``QubitPlaceholder``\ s comes in.
.. testoutput:: placeholders
:hide:

H {q...}
CNOT {q...} {q...}
H Placeholder(QubitPlaceholder(0x...))
CNOT Placeholder(QubitPlaceholder(0x...)) Placeholder(QubitPlaceholder(0x...))

.. parsed-literal::
H {q4402789176}
CNOT {q4402789176} {q4402789120}
If you try to use this program directly, it will not work
H Placeholder(QubitPlaceholder(0x600002DEB5B0))
CNOT Placeholder(QubitPlaceholder(0x600002DEB5B0)) Placeholder(QubitPlaceholder(0x600002DEABB0))
..
Could not make this a doctest because it would keep failing. ``doctest`` is supposed to match the
Expand Down Expand Up @@ -272,20 +270,21 @@ loop by following these steps:

# Run inner_loop in a loop until flag_register is 0
outer_loop.while_do(flag_register, inner_loop)
outer_loop.resolve_label_placeholders()

print(outer_loop)

.. testoutput:: control-flow

DECLARE flag_register BIT[1]
MOVE flag_register 1
LABEL @START1
JUMP-UNLESS @END2 flag_register
MOVE flag_register[0] 1
LABEL @START_0
JUMP-UNLESS @END_0 flag_register[0]
X 0
H 0
MEASURE 0 flag_register
JUMP @START1
LABEL @END2
MEASURE 0 flag_register[0]
JUMP @START_0
LABEL @END_0

Notice that the ``outer_loop`` program applied a Quil instruction directly to a
classical register. There are several classical commands that can be used in this fashion:
Expand Down Expand Up @@ -323,21 +322,22 @@ method.

# Measure qubit 0 into our readout register
branching_prog += MEASURE(0, ro)
branching_prog.resolve_label_placeholders()

print(branching_prog)

.. testoutput:: control-flow

DECLARE test_register BIT[1]
DECLARE ro BIT[1]
DECLARE test_register BIT[1]
H 1
MEASURE 1 test_register
JUMP-WHEN @THEN1 test_register
JUMP @END2
LABEL @THEN1
MEASURE 1 test_register[0]
JUMP-WHEN @THEN_0 test_register[0]
JUMP @END_0
LABEL @THEN_0
X 0
LABEL @END2
MEASURE 0 ro
LABEL @END_0
MEASURE 0 ro[0]

We can run this program a few times to see what we get in the readout register ``ro``.

Expand Down Expand Up @@ -437,7 +437,7 @@ The following shows an instructive example of all three.

Quil to compute exp[iX] on qubit 0:
H 0
RZ(-2.0) 0
RZ(-2) 0
H 0

``exponential_map`` returns a function allowing you to fill in a multiplicative
Expand All @@ -461,12 +461,12 @@ value for :math:`\alpha`.

1:
H 0
RZ(-2.0) 0
RZ(-2) 0
H 0

2:
H 0
RZ(-4.0) 0
RZ(-4) 0
H 0

To take it one step further, you can use :ref:`parametric_compilation` with ``exponential_map``. For instance:
Expand Down
6 changes: 6 additions & 0 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,12 @@
}
}

suppress_warnings = [
# TODO: Re-enable these warnings once Sphinx resolves this open issue:
# https://github.com/sphinx-doc/sphinx/issues/4961
"ref.python",
]

# fun little hack to always build the rst changelog from the markdown

dirname = os.path.dirname(__file__)
Expand Down
6 changes: 3 additions & 3 deletions docs/source/exercises.rst
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,10 @@ We can see what this program looks like in Quil notation with ``print(qft(0, 1,

SWAP 0 2
H 0
CPHASE(-pi/2) 0 1
CPHASE(-1.5707963267948966) 0 1
H 1
CPHASE(-pi/4) 0 2
CPHASE(-pi/2) 1 2
CPHASE(-0.7853981633974483) 0 2
CPHASE(-1.5707963267948966) 1 2
H 2

Part c: Execute the QFT
Expand Down
8 changes: 4 additions & 4 deletions docs/source/noise.rst
Original file line number Diff line number Diff line change
Expand Up @@ -617,12 +617,12 @@ The Idiomatic pyQuil Program
.. testoutput:: decoherence

H 0
RX(pi/2) 1
RX(1.5707963267948966) 1
CNOT 0 1
RZ(2*pi/3) 1
RZ(2.0943951023931953) 1
CNOT 0 1
H 0
RX(-pi/2) 1
RX(-1.5707963267948966) 1


The Compiled Program
Expand Down Expand Up @@ -1165,10 +1165,10 @@ Pauli-Z moments that indicate the qubit correlations are corrupted (and correcte

.. testoutput:: readout-noise

DECLARE ro BIT[3]
PRAGMA READOUT-POVM 0 "(0.85 0.050000000000000044 0.15000000000000002 0.95)"
PRAGMA READOUT-POVM 1 "(0.8 0.09999999999999998 0.19999999999999996 0.9)"
PRAGMA READOUT-POVM 2 "(0.9 0.15000000000000002 0.09999999999999998 0.85)"
DECLARE ro BIT[3]
H 0
CNOT 0 1
CNOT 1 2
Expand Down
6 changes: 3 additions & 3 deletions docs/source/programs_and_gates.rst
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ matrix representation of the gate. For example, below we define a

.. testoutput:: define-gates

DEFGATE SQRT-X:
DEFGATE SQRT-X AS MATRIX:
0.5+0.5i, 0.5-0.5i
0.5-0.5i, 0.5+0.5i

Expand Down Expand Up @@ -535,7 +535,7 @@ Some gates can be compactly represented as a permutation. For example, ``CCNOT``
[0, 0, 0, 0, 0, 0, 1, 0]
])

ccnot_gate = DefGate("CCNOT", ccnot_matrix)
ccnot_gate = DefGate("MATRIX_CCNOT", ccnot_matrix)

# etc

Expand All @@ -546,7 +546,7 @@ It can equivalently be defined by the permutation
import numpy as np
from pyquil.quilbase import DefPermutationGate

ccnot_gate = DefPermutationGate("CCNOT", [0, 1, 2, 3, 4, 5, 7, 6])
ccnot_gate = DefPermutationGate("PERMUTATION_CCNOT", [0, 1, 2, 3, 4, 5, 7, 6])

# etc

Expand Down
10 changes: 9 additions & 1 deletion docs/source/troubleshooting.rst
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,21 @@ Collect debug information

3. Run your script with debug logging enabled by adding the following to the top of your script:

.. testcode:: python
.. testcode:: debug

import logging
logging.basicConfig(level=logging.DEBUG)

.. note:: For information on how to filter the logs, see the `qcs-sdk-python logging documentation <https://github.com/rigetti/qcs-sdk-rust/tree/main/crates/python#enabling-debug-logging>`_

.. testcode:: debug
:hide:

import logging
# Disable debug logging, otherwise doctests will run with
# debug logging enabled.
logging.basicConfig(level=logging.INFO)

If the problem still isn't clear, then we can help! Please file an issue
on the `GitHub repo <https://github.com/rigetti/pyquil>`_ if it's an issue with pyQuil itself,
or contact us at our `support page <https://rigetti.zendesk.com>`_ for problems with QCS. If applicable,
Expand Down
4 changes: 0 additions & 4 deletions mypy.ini
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,6 @@ no_implicit_reexport = False

plugins = numpy.typing.mypy_plugin

# Ignore errors in all parser-related files
[mypy-pyquil._parser.*]
ignore_errors = True

# Ignore errors in vendored third-party libraries
[mypy-pyquil.external.*]
ignore_errors = True
Expand Down
Loading

0 comments on commit 4f47c12

Please sign in to comment.