Skip to content

Commit

Permalink
Remove circuit validation when sending a circuit with IQMClient (#136)
Browse files Browse the repository at this point in the history
* Added basic support for MOVE operations

* File cleanup

* Validate move gate with correct arguments

* Added move gate validation

* initial implementation of transpiler tests

* Improved testing and operation validation to check against what is calibrated rather than assuming all operation in the gateset areallowed

* wip add transpiler

* Improved test coverage

* Version bumb for iqm-client

* Version bumb iqm-client

* Version bump iqm-client

* Added qubit subset option for routing.

* Exposed transpile method to users directly

* Updated documentation

* Added compiler option support to the IQM Sampler

* Update to iqm-client==18.0

* Fix formatting

* Fix automatic Merge resolver

* Added reviewer feedback

* Removed circuit validation in create_run_request

* update changelog

* update changelog

* Removed duplicate code

* removed duplicate code

* Adding pylint disable that isn't recognised locally

* Remove duplicated test code

* Added some test documentation

* Updates for compatibility with iqm-client

---------

Co-authored-by: Arianne Meijer <arianne.meijer@meetiqm.com>
  • Loading branch information
Aerylia and Arianne Meijer authored Oct 17, 2024
1 parent a5a82df commit 860ae07
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 13 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@
Changelog
=========

Version 14.6
============

* Bugfix COMP-1491: Fixed issue where `cirq_iqm` would ignore the MOVE gate validation options in CircuitCompilationOptions. `#136 <https://github.com/iqm-finland/cirq-on-iqm/pull/136>`_
* Removed `cirq_iqm` circuit validation when submitting to an IQM device because `iqm-client` already validates the circuit.
* Added `isort` formatting to `tox -e format`.

Version 14.5
============

Expand Down
16 changes: 6 additions & 10 deletions src/iqm/cirq_iqm/iqm_sampler.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@

from iqm.cirq_iqm.devices.iqm_device import IQMDevice, IQMDeviceMetadata
from iqm.cirq_iqm.serialize import serialize_circuit
from iqm.iqm_client import Circuit, CircuitCompilationOptions, IQMClient, JobAbortionError, RunRequest
from iqm.iqm_client import CircuitCompilationOptions, IQMClient, JobAbortionError, RunRequest


class IQMSampler(cirq.work.Sampler):
Expand Down Expand Up @@ -143,7 +143,10 @@ def create_run_request(
if isinstance(programs, cirq.Circuit):
programs, _ = self._resolve_parameters(programs, params)

serialized_circuits = self._validate_and_serialize_circuits(programs)
serialized_circuits = [serialize_circuit(circuit) for circuit in programs]

if not self._client:
raise RuntimeError('Cannot submit circuits since session to IQM client has been closed.')

return self._client.create_run_request(
serialized_circuits,
Expand Down Expand Up @@ -188,7 +191,7 @@ def _send_circuits(

return ( # pylint: disable=not-an-iterable,no-member
[{k: np.array(v) for k, v in measurements.items()} for measurements in results.measurements],
ResultMetadata(job_id, results.metadata.calibration_set_id, results.metadata.request),
ResultMetadata(job_id, results.metadata.calibration_set_id, run_request),
)

@staticmethod
Expand All @@ -199,13 +202,6 @@ def _resolve_parameters(
circuits = [cirq.protocols.resolve_parameters(program, res) for res in resolvers] if resolvers else [program]
return circuits, resolvers

def _validate_and_serialize_circuits(self, circuits: list[cirq.Circuit]) -> list[Circuit]:
if not self._client:
raise RuntimeError('Cannot submit circuits since session to IQM client has been closed.')
for circuit in circuits:
self._device.validate_circuit(circuit)
return [serialize_circuit(circuit) for circuit in circuits]


@dataclass
class ResultMetadata:
Expand Down
22 changes: 19 additions & 3 deletions tests/test_iqm_sampler.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import uuid

import cirq
from mockito import ANY, expect, mock, verify, verifyNoUnwantedInteractions, when
from mockito import ANY, expect, mock, unstub, verify, verifyNoUnwantedInteractions, when
import numpy as np
import pytest
import sympy # type: ignore
Expand All @@ -28,6 +28,7 @@
from iqm.iqm_client import (
Circuit,
CircuitCompilationOptions,
CircuitValidationError,
HeraldingMode,
Instruction,
IQMClient,
Expand Down Expand Up @@ -99,7 +100,11 @@ def run_request():

@pytest.mark.usefixtures('unstub')
def test_run_sweep_raises_with_non_physical_names(adonis_sampler, circuit_non_physical):
with pytest.raises(ValueError, match='Qubit not on device'):
when(adonis_sampler._client).get_quantum_architecture().thenReturn(
adonis_sampler._device.metadata.to_architecture()
)
# Note that validation is done in iqm_client, so this is now an integration test.
with pytest.raises(CircuitValidationError, match='Qubit Alice is not allowed as locus for measure'):
adonis_sampler.run_sweep(circuit_non_physical, None)


Expand Down Expand Up @@ -245,6 +250,10 @@ def test_run_sweep_executes_circuit_with_heralding_mode_zeros(
'options': CircuitCompilationOptions(heralding_mode=HeraldingMode.ZEROS)
}
assert sampler._compiler_options.heralding_mode == HeraldingMode.ZEROS
kwargs = create_run_request_default_kwargs | {
'options': CircuitCompilationOptions(heralding_mode=HeraldingMode.ZEROS)
}
assert sampler._compiler_options.heralding_mode == HeraldingMode.ZEROS
when(client).create_run_request(ANY, **kwargs).thenReturn(run_request)
when(client).submit_run_request(run_request).thenReturn(job_id)
when(client).wait_for_results(job_id).thenReturn(run_result)
Expand Down Expand Up @@ -329,9 +338,16 @@ def test_run_sweep_abort_job_failed(

@pytest.mark.usefixtures('unstub')
def test_run_iqm_batch_raises_with_non_physical_names(adonis_sampler, circuit_non_physical):
with pytest.raises(ValueError, match='Qubit not on device'):
when(adonis_sampler._client).get_quantum_architecture().thenReturn(
adonis_sampler._device.metadata.to_architecture()
)
# Note that validation is done in iqm_client, so this is now an integration test.
with pytest.raises(CircuitValidationError, match='Qubit Alice is not allowed as locus for measure'):
adonis_sampler.run_iqm_batch([circuit_non_physical])

verifyNoUnwantedInteractions()
unstub()


@pytest.mark.usefixtures('unstub')
def test_run(adonis_sampler, iqm_metadata, create_run_request_default_kwargs, job_id):
Expand Down
2 changes: 2 additions & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@ skip_install = True
changedir = {toxinidir}
deps =
black ~= 23.12
isort ~= 5.13
commands =
black src tests
isort src tests

[testenv:docs]
description =
Expand Down

0 comments on commit 860ae07

Please sign in to comment.