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

Use dynamic quantum architecture (DQA) for circuit decomposition/routing #139

Merged
merged 11 commits into from
Nov 1, 2024

Conversation

jkotilahti
Copy link
Member

@jkotilahti jkotilahti commented Oct 23, 2024

  • IQMDeviceMetadata can now be created from a DQA, and creating it from QuantumArchitectureSpecification (static architecture) is no longer supported.

  • IQMDevice/IQMDeviceMetadata can still be created independently of the architecture/calset, so the hardcoded Adonis, Apollo etc. classes are not removed. They are currently used mainly for tests, and could be used for simulation.

  • IQMSampler uses the specified calset (or server default calset if calibration_set_id not specified) to create the IQMDeviceMetadata/IQMDevice.

  • IQMSampler adds the calset id to the circuits it decomposes/routes. The calset id is used to warn the user of mismatches between the calset used for execution and the decomposed/routed circuits.

  • Requires Use dynamic quantum architecture for circuit validation and transpilation iqm-client#140 to be merged first, tests will fail until then. I have tested locally that all tests pass when used together with those changes.

Comment on lines +115 to +125
# connectivity consists of all arity-2 gate loci in the DQA
connectivity = tuple(
get_qid_locus(locus)
for gate_info in architecture.gates.values()
for locus in gate_info.loci
if len(locus) == 2
)
operations: dict[type[cirq.Gate], list[tuple[NamedQid, ...]]] = {
cirq_op: [
tuple(
(
NamedQid(qb, dimension=2)
if qb.startswith(cls.QUBIT_NAME_PREFIX)
else NamedQid(qb, dimension=cls.RESONATOR_DIMENSION)
)
for qb in args
)
for args in qubits
]
for iqm_op, qubits in architecture.operations.items()
for cirq_op in _IQM_CIRQ_OP_MAP[iqm_op]
}
return cls(qubits, connectivity, operations=operations, resonators=resonators)

def to_architecture(self) -> QuantumArchitectureSpecification:
"""Returns the architecture specification object created based on device metadata."""
qubits = tuple(qb.name for qb in self._qubit_set)
resonators = tuple(qb.name for qb in self.resonator_set)
connectivity = tuple(tuple(qb.name for qb in edge) for edge in self.nx_graph.edges())
operations: dict[str, list[tuple[str, ...]]] = {
iqm_op: [tuple(qb.name for qb in args) for args in qubits]
for cirq_op, qubits in self.operations.items()
for iqm_op, cirq_ops in _IQM_CIRQ_OP_MAP.items()
if cirq_op in cirq_ops
cirq_op: [get_qid_locus(locus) for locus in gate_info.loci]
for gate_name, gate_info in architecture.gates.items()
for cirq_op in _IQM_CIRQ_OP_MAP[gate_name]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

operations contains the full locus info for all gates, but it's not used for routing as far as I can tell.
connectivity is used (in the form of IQMDevice._metadata.nx_graph), but it does not represent any single 2q gate type (seems like the router assumes there is just one 2q gate).

Also, connectivity here will contain duplicate loci/edges. When it's converted into a graph the duplicates vanish.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. As discussed, this problem already existed before this PR and is due to Cirq limitations. Probably can't solve it here. We can still look into a solution for it, but probably the PR should not be blocked from being merged because of this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this connectivity work for Deneb-style devices? Where the router should not have the MOVE gate edges. If connectivity will turn into a an nx_graph does it makes sense to make labeled edges where the labels correspond to gates? Or is that something the router cannot work with either?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The connectivity (nx_graph) should be the same as before this PR, assuming we compare an "equivalent" DQA and QuantumArchitectureSpecification. So my understanding is that it should work for Deneb same as before this PR.

I think labeled edges for gates wouldn't be used by the router, because the documentation says that the graph is "The connectivity graph of physical qubits.": https://quantumai.google/reference/python/cirq/RouteCQC

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the connectivity is used to build the nx_graph this is used in route_circuit by removing the resonators from it and then using Cirq's routing pass. After that, the MOVE gates are added. So there is no notion of gates in the route_circuit but the case of MOVE gates is handled through the resonator.

CHANGELOG.rst Show resolved Hide resolved
src/iqm/cirq_iqm/iqm_sampler.py Outdated Show resolved Hide resolved
Comment on lines +115 to +125
# connectivity consists of all arity-2 gate loci in the DQA
connectivity = tuple(
get_qid_locus(locus)
for gate_info in architecture.gates.values()
for locus in gate_info.loci
if len(locus) == 2
)
operations: dict[type[cirq.Gate], list[tuple[NamedQid, ...]]] = {
cirq_op: [
tuple(
(
NamedQid(qb, dimension=2)
if qb.startswith(cls.QUBIT_NAME_PREFIX)
else NamedQid(qb, dimension=cls.RESONATOR_DIMENSION)
)
for qb in args
)
for args in qubits
]
for iqm_op, qubits in architecture.operations.items()
for cirq_op in _IQM_CIRQ_OP_MAP[iqm_op]
}
return cls(qubits, connectivity, operations=operations, resonators=resonators)

def to_architecture(self) -> QuantumArchitectureSpecification:
"""Returns the architecture specification object created based on device metadata."""
qubits = tuple(qb.name for qb in self._qubit_set)
resonators = tuple(qb.name for qb in self.resonator_set)
connectivity = tuple(tuple(qb.name for qb in edge) for edge in self.nx_graph.edges())
operations: dict[str, list[tuple[str, ...]]] = {
iqm_op: [tuple(qb.name for qb in args) for args in qubits]
for cirq_op, qubits in self.operations.items()
for iqm_op, cirq_ops in _IQM_CIRQ_OP_MAP.items()
if cirq_op in cirq_ops
cirq_op: [get_qid_locus(locus) for locus in gate_info.loci]
for gate_name, gate_info in architecture.gates.items()
for cirq_op in _IQM_CIRQ_OP_MAP[gate_name]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this connectivity work for Deneb-style devices? Where the router should not have the MOVE gate edges. If connectivity will turn into a an nx_graph does it makes sense to make labeled edges where the labels correspond to gates? Or is that something the router cannot work with either?

@@ -35,6 +35,7 @@ class IQMDeviceMetadata(devices.DeviceMetadata):
operations: Supported quantum operations of the device, mapping op types to their possible loci.
gateset: Native gateset of the device. If None, a default IQM device gateset will be used.
resonators: computational resonators of the device
architecture: architecture from which values of the other arguments were obtained
"""

QUBIT_NAME_PREFIX: str = 'QB'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this still needed with DQA?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's still needed because it's used in IQMDevice.get_qubit_index and IQMDeviceMetadata.from_qubit_indices.

  • get_qubit_index is not used anywhere in code. But could be useful for some purpose, not sure if there was some requirement to have it?

  • from_qubit_indices makes creating the hardcoded devices like Apollo a bit nicer

Both are probably something we could get rid of if we really want, but I would still keep this and not change these things in this PR.

@jkotilahti jkotilahti requested review from Aerylia and smite October 30, 2024 22:47
@jkotilahti jkotilahti merged commit eff5517 into main Nov 1, 2024
13 checks passed
@jkotilahti jkotilahti deleted the sw-709-dqa-transpilation-target branch November 1, 2024 14:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants