Skip to content

Commit

Permalink
Update to pyquil 4 (#87)
Browse files Browse the repository at this point in the history
  • Loading branch information
cqc-alec committed Jul 22, 2024
1 parent 44bcc02 commit 6345a79
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 17 deletions.
5 changes: 2 additions & 3 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ on:
jobs:
lint:

runs-on: ubuntu-22.04
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
Expand All @@ -24,5 +24,4 @@ jobs:
run: |
black --check .
- name: Run pylint
run: |
pylint */
run: pylint */
8 changes: 5 additions & 3 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
Changelog
~~~~~~~~~

0.36.0 (unreleased)
-------------------
Unreleased
----------

* Updated pytket version requirement to 1.30.
* Update pytket version requirement to 1.30.
* Update pyquil version requirement to 4.13.
* Remove upper bounds on dependency versions.

0.35.0 (April 2024)
-------------------
Expand Down
25 changes: 19 additions & 6 deletions pytket/extensions/pyquil/backends/forest.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,8 @@ def process_circuits(
).apply(circuit)

p, bits = tk_to_pyquil(c0, return_used_bits=True)
bit_indices = [c0.bits.index(bit) for bit in bits]

p.wrap_in_numshots_loop(n_shots)
ex = self._qc.compiler.native_quil_to_executable(p)
qam = self._qc.qam
Expand All @@ -237,11 +239,14 @@ def process_circuits(
if measures == 0:
self._cache[handle] = {
"handle": pyquil_handle,
"c_bits": sorted(bits),
"bit_indices": sorted(bit_indices),
"result": self.empty_result(circuit, n_shots=n_shots),
}
else:
self._cache[handle] = {"handle": pyquil_handle, "c_bits": sorted(bits)}
self._cache[handle] = {
"handle": pyquil_handle,
"bit_indices": sorted(bit_indices),
}
handle_list.append(handle)
return handle_list

Expand Down Expand Up @@ -283,12 +288,13 @@ def get_result(self, handle: ResultHandle, **kwargs: KwargTypes) -> BackendResul
raw_shots = self._qc.qam.get_result(pyquil_handle).readout_data["ro"]
if raw_shots is None:
raise ValueError("Could not read job results in memory")
# Measurement results are returned even for unmeasured bits, so we
# have to filter the shots table:
raw_shots = raw_shots[:, self._cache[handle]["bit_indices"]]
shots = OutcomeArray.from_readouts(raw_shots.tolist())
ppcirc_rep = json.loads(cast(str, handle[1]))
ppcirc = Circuit.from_dict(ppcirc_rep) if ppcirc_rep is not None else None
res = BackendResult(
shots=shots, c_bits=self._cache[handle]["c_bits"], ppcirc=ppcirc
)
res = BackendResult(shots=shots, ppcirc=ppcirc)
self._cache[handle].update({"result": res})
return res

Expand Down Expand Up @@ -319,7 +325,14 @@ def _get_backend_info(cls, qc: QuantumComputer) -> BackendInfo:
def available_devices(cls, **kwargs: Any) -> List[BackendInfo]:
"""
See :py:meth:`pytket.backends.Backend.available_devices`.
Supported kwargs: `qpus` (default true), `qvms` (default false).
Supported kwargs:
- `qpus` (bool, default True): whether to include QPUs in the list
- `qvms` (bool, default False): whether to include QVMs in the list
- `timeout` (float, default 10.0) time limit for request, in seconds
- `client_configuration` (optional qcs_sdk.QCSClient, defaut None):
optional client configuration; if None, a default one will be loaded.
"""
if "qvms" not in kwargs:
kwargs["qvms"] = False
Expand Down
10 changes: 8 additions & 2 deletions pytket/extensions/pyquil/pyquil_convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,12 @@ def param_from_pyquil(p: Union[float, Expression]) -> Expr:
def to_sympy(e: Any) -> Union[float, int, Expr, Symbol]:
if isinstance(e, (float, int)):
return e
elif isinstance(e, complex):
if abs(e.imag) >= 1e-12:
raise NotImplementedError(
"Quil expression could not be converted to a parameter: " + str(e)
)
return e.real
elif isinstance(e, MemoryReference):
return Symbol(e.name)
elif isinstance(e, Function_):
Expand Down Expand Up @@ -177,11 +183,11 @@ def pyquil_to_tk(prog: Program) -> Circuit:
raise NotImplementedError(
"Operation not supported by tket: " + str(i)
) from error
qubits = [qmap[q.index] for q in i.qubits]
qubits = [qmap[cast(Qubit_, q).index] for q in i.qubits]
params: list[Union[Expr, float]] = [param_from_pyquil(p) for p in i.params] # type: ignore
tkc.add_gate(optype, params, qubits)
elif isinstance(i, Measurement):
qubit = qmap[i.qubit.index]
qubit = qmap[cast(Qubit_, i.qubit).index]
reg = cregmap[i.classical_reg.name] # type: ignore
bit = reg[i.classical_reg.offset] # type: ignore
tkc.Measure(qubit, bit)
Expand Down
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@
include_package_data=True,
install_requires=[
"pytket >= 1.30.0",
"pyquil ~= 3.5",
"typing-extensions ~= 4.2",
"pyquil >= 4.13.0",
"typing-extensions >= 4.12.2",
],
classifiers=[
"Environment :: Console",
Expand Down
1 change: 1 addition & 0 deletions tests/qvm_backend_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,7 @@ def test_process_characterisation(qvm: None, quilc: None) -> None:
@pytest.mark.skipif(
skip_qvm_tests, reason="Can only run Rigetti QVM if docker is installed"
)
@pytest.mark.xfail(reason="https://github.com/CQCL/pytket-pyquil/issues/93")
def test_retrieve_available_devices() -> None:
backend_infos = ForestBackend.available_devices()
assert len(backend_infos) > 0
Expand Down
2 changes: 1 addition & 1 deletion tests/test-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
pytest
pytest-timeout ~= 2.3.1
pytest-timeout
hypothesis
requests_mock
docker

0 comments on commit 6345a79

Please sign in to comment.