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

Update to pyquil 4 #87

Merged
merged 9 commits into from
Jul 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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