Skip to content

Commit

Permalink
Use Rust SDK from compilation to result collection (#1472)
Browse files Browse the repository at this point in the history
* Add a LocalCompiler that uses the Rust QCS SDK

* Collect memory descriptors

* quil_to_native_quil takes a quantum processor (not a string ID)

* Num shots no worky

* Return actual program from compilation

* Clean up after Mark

* WIP recalc table and patch values

* use build_patch_values qcs binding

* Fix memory value collection

Collection would overwrite entries when a declared block of memory
had a length > 1. We now append to a growing list, which should
end with a length equal to the declared length in Quil.

* Use qcs-sdk for results

Required a changed to how buffers are interpreted, due to the
change from byte strings to actual lists in the response from the
sdk.

* Start the new migration guide

Just a list of changes for now. Not super comprehensive, but want
to ensure we don't lose track of important changes we should
eventually call out.

* Add qcs-sdk-python to poetry dependencies

* retry checks now that linux wheel is available for qcs_sdk

* retry checks now that linux wheel is available for qcs_sdk

* Rework async

* Pass compiler ISA rather than QCS ISA

* use qcs-sdk-rust@0.2.0rc0

* fix: Ensure adding programs doesn't mutate the first (#1477)

Closes #1476

As noted in #1476, adding programs (like `p1 + p2`) currently mutates
the first program (i.e. `p1` would change). This PR ensures that
calibrations et. al. are copied rather than just assigned, and adds a
new test case to `unit/test_program.py` to ensure against regression:

```shell
$ poetry run pytest test/unit/test_program.py --verbose
==================================== test session starts =====================================
platform darwin -- Python 3.9.13, pytest-6.2.4, py-1.10.0, pluggy-0.13.1 -- /Users/genos/rc/repos/pyquil/.venv/bin/python
cachedir: .pytest_cache
rootdir: /Users/genos/rc/repos/pyquil
plugins: cov-2.12.1, freezegun-0.4.2, rerunfailures-9.1.1, xdist-2.3.0, mock-3.6.1, timeout-1.4.2, forked-1.3.0
collected 5 items

test/unit/test_program.py::test_measure_qubits PASSED                                  [ 20%]
test/unit/test_program.py::test_parameterized_single_qubit_measurement_basis PASSED    [ 40%]
test/unit/test_program.py::test_parameterized_single_qubit_state_preparation PASSED    [ 60%]
test/unit/test_program.py::test_parameterized_readout_symmetrization PASSED            [ 80%]
test/unit/test_program.py::test_adding_does_not_mutate PASSED                          [100%]
```

* fix: report non-503 http status errors when creating engagements (#1479)

* fix: report non-503 http status errors when creating engagements

* chore: update docs

* chore: prepare release 3.3.1

* chore: poetry update (#1481)

* chore: poetry update

* chore: update respx dependency

* chore: update black and mypy

* chore: update tests to match client changes

* chore: pin numpy dep to fix type issues

* chore: fix lint errors

* chore: remove cast

* chore: instll mypy types

* chore: add types to dependencies

* chore: add type deps to lockfile

* chore: fix tests mocks

* chore: try update sphinx

* chore: revert error tolerance and change language to english

* chore: fix sphinx issues

* chore: revert sphinx update

* chore: relax numpy version and fix type errors

* chore: prepare release 3.3.2

* Fix: response parsing

* Update: support execution against gateway

* Fix incorrect validation

* fixes

* Bump SDK version

* Remove test script

* Bump major version to v4

* Remove debug print

* Update migration guide

* Fix lockfile

* bump qcs-sdk-python version to 0.3.0

* use qcs-sdk 0.3.1

* update test qcs_settings.toml, make it accessible to rust sdk

* share test qcs config between unit and e2e tests, bump scipy, add
asyncio-nest as dev dependency

* add coveralls as dev dep

* attempt at simplifying deps

* nest-asyncio needs to be a dev dep

* test new qcs-sdk-rust fix

* fix types warnings from `make check-types`   (#1482)

* fix: types

* chore: use type-only reference

* chore: mr cleanup

* chore: update qcs-sdk-python version

Co-authored-by: marquessv <marquessavaldez@gmail.com>

* skip test with extra HALT instruction

Co-authored-by: Mark Skilbeck <mark.skilbeck@rigetti.com>
Co-authored-by: marquessv <marquessavaldez@gmail.com>
Co-authored-by: Graham <genos@users.noreply.github.com>
Co-authored-by: jselig-rigetti <97701976+jselig-rigetti@users.noreply.github.com>
Co-authored-by: notmgsk <notmgsk@users.noreply.github.com>
  • Loading branch information
6 people authored Oct 27, 2022
1 parent c09b1ec commit 429e17c
Show file tree
Hide file tree
Showing 40 changed files with 1,505 additions and 1,290 deletions.
3 changes: 3 additions & 0 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ variables:
IMAGE: rigetti/forest
QCS_SETTINGS_APPLICATIONS_PYQUIL_QVM_URL: "http://qvm:5000"
QCS_SETTINGS_APPLICATIONS_PYQUIL_QUILC_URL: "tcp://quilc:5555"
# For qcs-sdk-rust - Consider using these exclusively in pyQuil v4 release
QCS_SETTINGS_APPLICATIONS_QVM_URL: "http://qvm:5000"
QCS_SETTINGS_APPLICATIONS_QUILC_URL: "tcp://quilc:5555"

# Docker images to spin up along with the various CI jobs
services:
Expand Down
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@

- The v2 compatibility layer.

## 3.3.2

## 3.3.1

### Fixes

- report non-503 http status errors when creating engagements (#1479)
- Ensure adding programs doesn't mutate the first (#1477)

## 3.3.0

### Features
Expand Down
96 changes: 3 additions & 93 deletions docs/source/migration.rst
Original file line number Diff line number Diff line change
@@ -1,97 +1,7 @@
.. _migration:

Migrating from pyQuil v2 to v3
Migrating from pyQuil v3 to v4
==============================

To begin migrating your pyQuil v2 code, we recommend first reading the :doc:`changes` and making adjustments according
to the code affected. Most users should only need to make minimal changes.

If you've supplied ``PyquilConfig`` objects to functions (or used the ``QVM_URL`` and ``QUILC_URL`` environment variables)
to override configuration, see :ref:`pyquil_configuration`.

Authentication
--------------

pyQuil v3 relies on an updated authentication model. To get started, install the new `QCS CLI
<https://docs.rigetti.com/>`_ and
log in with it before using pyQuil v3 with QCS and live QPUs.


Parameters & Memory
-------------------

In order to give the user more control over and visibility into program execution, especially in
parallel, objects such as ``QuantumComputer``, ``QAM``, ``QPU``, and ``QVM`` are no longer stateful
with respect to individual programs. These objects are now safe to
share among different threads, so you can execute and retrieve results in parallel for even better
performance. (See :doc:`advanced_usage` for more information).

However, this required three small but important changes:

1. ``write_memory`` is no longer a method on ``QAM`` but rather on ``Program`` and ``EncryptedProgram``.
2. ``qc.run()`` no longer accepts a ``memory_map`` argument. All memory values must be set directly on the ``Program`` or ``EncryptedProgram`` using ``write_memory``.
3. ``QAM.load()``, ``QAM.wait()``, and ``QAM.reset()`` no longer exist, because the ``QAM`` no longer "stores" program state.

This means that you should now execute your programs using one of these options:

.. code:: python
qc = get_qc("Aspen-X")
program = Program()
theta = program.declare('theta', 'REAL')
program += RZ(theta, 0)
exe = qc.compile(program)
# Previously, we would have called ``qc.qam.write_memory`` instead
exe.write_memory(region_name='theta', value=np.pi)
# Option 1
result = qc.run(exe)
# Option 2
result = qc.qam.run(exe)
# Option 3
job = qc.qam.execute(exe)
result = qc.qam.get_result(job)
# Run our program 10 times, enqueuing all the programs before retrieving results for any of them
jobs = [qc.qam.execute(exe) for _ in range(10)]
results = [qc.qam.get_result(job) for job in jobs]
Additionally, ``QuantumComputer.run()`` and ``QAM.run()`` now both return ``QAMExecutionResult``, rather
than the bitstrings which were read out following execution. So, to retrieve the bitstrings from region ``ro``
like you would have in pyQuil v2, query the readout data:

.. code:: python
result = qc.run(exe)
bitstrings = result.readout_data.get('ro')
Note that there is no "memory" in the result shape -- yet. Readout data is inherently collected and returned
differently than memory values are, and that nuance is no longer masked in pyQuil v3. All of the results
that, in pyQuil v2, you would have expected to retrieve using ``QAM.read_memory()`` are now present in
``QAMExecutionResult.readout_data``.

The notable exception to this is ``PyQVM``, which remains stateful, and whose memory you can still inspect using
``PyQVM.read_memory()``.


Compatibility Utilities
-----------------------

We understand that the changes above regarding parameters might cause difficulty in migration,
especially for large projects and lengthy scripts. So, to ease the migration path, we've added
the following utility classes which allow you to upgrade your pyQuil projects without having to
change any code.

.. code:: python
from pyquil.compatibility.v2 import get_qc
from pyquil.compatibility.v2.api import QuantumComputer, QAM, QVM, QPU
You can use these imported objects similarly how you use their counterparts in pyQuil v2.
Once you've verified that your scripts still work with v3, we recommend that you gradually convert
them to use the new versions of each object. This compatibility layer won't see any new
development, and without fully upgrading you'd miss out on all the new features to come in the
future.
Internally, `asyncio` is now used for compilation, execution, and result collection. If using pyQuil in an existing `asyncio` context,
it may be necessary to use [nest-asyncio](https://pypi.org/project/nest-asyncio/) to allow nesting of async contexts.
6 changes: 5 additions & 1 deletion mypy.ini
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ ignore_missing_imports = True
# Enable options equivalent to the --strict command line arg
warn_unused_configs = True
disallow_subclassing_any = True
disallow_any_generics = True

# numpy expects generic arguments for `numpy.ndarray` that default
# to `typing.Any` and we use those defaults all over the place.
disallow_any_generics = False

disallow_untyped_calls = True
disallow_untyped_defs = True
disallow_incomplete_defs = True
Expand Down
Loading

0 comments on commit 429e17c

Please sign in to comment.