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

[UnitaryHack] Enable qiskit transpilation discontinous qubit indices #108

48 changes: 48 additions & 0 deletions qiskit_braket_provider/providers/adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,54 @@ def aws_device_to_target(device: AwsDevice) -> Target:
instruction_props[(dst, src)] = None
# building coupling map for device with connectivity graph
else:
if isinstance(properties, RigettiDeviceCapabilities):

def convert_continuous_qubit_indices(
connectivity_graph: dict,
) -> dict:
"""Aspen qubit indices are discontinuous (label between x0 and x7, x being
the number of the octagon) while the Qiskit transpiler creates and/or
handles coupling maps with continuous indices. This function converts the
discontinous connectivity graph from Aspen to a continuous one.

Args:
connectivity_graph (dict): connectivity graph from Aspen. For example
4 qubit system, the connectivity graph will be:
{"0": ["1", "2", "7"], "1": ["0","2","7"], "2": ["0","1","7"],
"7": ["0","1","2"]}

Returns:
dict: Connectivity graph with continuous indices. For example for an
input connectivity graph with discontinuous indices (qubit 0, 1, 2 and
then qubit 7) as shown here:
{"0": ["1", "2", "7"], "1": ["0","2","7"], "2": ["0","1","7"],
"7": ["0","1","2"]}
the qubit index 7 will be mapped to qubit index 3 for the qiskit
transpilation step. Thereby the resultant continous qubit indices
output will be:
{"0": ["1", "2", "3"], "1": ["0","2","3"], "2": ["0","1","3"],
"3": ["0","1","2"]}
"""
# Creates list of existing qubit indices which are discontinuous.
indices = [int(key) for key in connectivity_graph.keys()]
indices.sort()
# Creates a list of continuous indices for number of qubits.
map_list = list(range(len(indices)))
# Creates a dictionary to remap the discountinous indices to continuous.
mapper = dict(zip(indices, map_list))
# Performs the remapping from the discontinous to the continuous indices.
continous_connectivity_graph = {
mapper[int(k)]: [mapper[int(v)] for v in val]
for k, val in connectivity_graph.items()
}
return continous_connectivity_graph

connectivity.connectivityGraph = (
convert_continuous_qubit_indices(
connectivity.connectivityGraph
)
)

for src, connections in connectivity.connectivityGraph.items():
for dst in connections:
instruction_props[(int(src), int(dst))] = None
Expand Down
31 changes: 31 additions & 0 deletions tests/providers/mocks.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
"""Mocks for testing."""

from collections import Counter
import copy
from typing import Dict

import uuid
import numpy as np
Expand All @@ -12,6 +14,7 @@


RIGETTI_ARN = "arn:aws:braket:::device/qpu/rigetti/Aspen-10"
RIGETTI_ASPEN_ARN = "arn:aws:braket:::device/qpu/rigetti/Aspen-M-3"
SV1_ARN = "arn:aws:braket:::device/quantum-simulator/amazon/sv1"
TN1_ARN = "arn:aws:braket:::device/quantum-simulator/amazon/tn1"
RIGETTI_REGION = "us-west-1"
Expand Down Expand Up @@ -64,6 +67,34 @@
"deviceCapabilities": RIGETTI_MOCK_GATE_MODEL_QPU_CAPABILITIES.json(),
}

RIGETTI_MOCK_M_3_QPU_CAPABILITIES_JSON: Dict = copy.deepcopy(
RIGETTI_MOCK_GATE_MODEL_QPU_CAPABILITIES_JSON
)
RIGETTI_MOCK_M_3_QPU_CAPABILITIES_JSON["action"]["braket.ir.openqasm.program"][
"supportedOperations"
] = ["RX", "RZ", "CP", "CZ", "XY"]
RIGETTI_MOCK_M_3_QPU_CAPABILITIES_JSON["paradigm"]["qubitCount"] = 4
RIGETTI_MOCK_M_3_QPU_CAPABILITIES_JSON["paradigm"]["connectivity"][
"connectivityGraph"
] = {
"0": ["1", "2", "7"],
"1": ["0", "2", "7"],
"2": ["0", "1", "7"],
"7": ["0", "1", "2"],
}
RIGETTI_MOCK_M_3_QPU_CAPABILITIES = RigettiDeviceCapabilities.parse_obj(
RIGETTI_MOCK_M_3_QPU_CAPABILITIES_JSON
)

MOCK_RIGETTI_GATE_MODEL_M_3_QPU = {
"deviceName": "Aspen-M-3",
"deviceType": "QPU",
"providerName": "provider1",
"deviceStatus": "ONLINE",
"deviceArn": RIGETTI_ASPEN_ARN,
"deviceCapabilities": RIGETTI_MOCK_M_3_QPU_CAPABILITIES.json(),
}

MOCK_GATE_MODEL_SIMULATOR_CAPABILITIES_JSON = {
"braketSchemaHeader": {
"name": "braket.device_schema.simulators.gate_model_simulator_device_capabilities",
Expand Down
38 changes: 35 additions & 3 deletions tests/providers/test_braket_provider.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
"""Tests for AWS Braket provider."""
import unittest
from unittest import TestCase
from unittest.mock import Mock
from unittest.mock import Mock, patch

from braket.aws import AwsDeviceType
from qiskit import transpile
from qiskit import circuit as qiskit_circuit
from qiskit.circuit.random import random_circuit

from qiskit.compiler import transpile
from qiskit_braket_provider.providers import AWSBraketProvider
from qiskit_braket_provider.providers.braket_backend import (
BraketBackend,
Expand All @@ -15,6 +15,8 @@
from tests.providers.mocks import (
MOCK_GATE_MODEL_SIMULATOR_SV,
MOCK_GATE_MODEL_SIMULATOR_TN,
MOCK_RIGETTI_GATE_MODEL_M_3_QPU,
RIGETTI_MOCK_M_3_QPU_CAPABILITIES,
SIMULATOR_REGION,
)

Expand Down Expand Up @@ -69,3 +71,33 @@ def test_real_device_circuit_execution(self):
)
result = state_vector_backend.run(transpiled_circuit, shots=10)
self.assertTrue(result)

@patch("braket.aws.aws_device.AwsDevice.get_devices")
def test_discontinous_qubit_indices_qiskit_transpilation(self, mock_get_devices):
"""Tests circuit transpilation with discontinous qubit indices."""

mock_m_3_device = Mock()
mock_m_3_device.name = MOCK_RIGETTI_GATE_MODEL_M_3_QPU["deviceName"]
mock_m_3_device.arn = MOCK_RIGETTI_GATE_MODEL_M_3_QPU["deviceArn"]
mock_m_3_device.provider = MOCK_RIGETTI_GATE_MODEL_M_3_QPU["providerName"]
mock_m_3_device.status = MOCK_RIGETTI_GATE_MODEL_M_3_QPU["deviceStatus"]
mock_m_3_device.device_type = MOCK_RIGETTI_GATE_MODEL_M_3_QPU["deviceType"]
mock_m_3_device.device_capabilities = MOCK_RIGETTI_GATE_MODEL_M_3_QPU[
"deviceCapabilities"
]
mock_m_3_device_properties = RIGETTI_MOCK_M_3_QPU_CAPABILITIES
mock_m_3_device_properties.service = Mock()
mock_m_3_device_properties.service.updatedAt = "2023-06-02T17:00:00+00:00"
mock_m_3_device.properties = mock_m_3_device_properties
mock_get_devices.return_value = [mock_m_3_device]

provider = AWSBraketProvider()
device = provider.get_backend("Aspen-M-3")

circ = qiskit_circuit.QuantumCircuit(3)
circ.h(0)
circ.cx(0, 1)
circ.cx(1, 2)

result = transpile(circ, device)
self.assertTrue(result)
Loading