Skip to content

Commit

Permalink
Merge pull request #211 from entropicalabs/dev_braket_measurement
Browse files Browse the repository at this point in the history
braket measurement fix, qiskit, pyquil initial_qubit_mapping fix
  • Loading branch information
vishal-ph authored Aug 4, 2023
2 parents b6a9e1a + 5468a55 commit bfb0bbf
Show file tree
Hide file tree
Showing 7 changed files with 189 additions and 14 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# The dockerfile for OpenQAOA braket jobs
FROM 292282985366.dkr.ecr.us-east-1.amazonaws.com/Braket-Base:1.0.0-cpu-py39-ubuntu22.04
FROM 292282985366.dkr.ecr.us-east-1.amazonaws.com/amazon-braket-base-jobs:1.0-cpu-py39-ubuntu22.04

RUN mkdir -p /openqaoa

Expand Down
22 changes: 19 additions & 3 deletions src/openqaoa-braket/openqaoa_braket/backends/devices.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ def __init__(

self.provider_connected = None
self.qpu_connected = None
self._connectivity = None

def check_connection(self) -> bool:
self.provider_connected = self._check_provider_connection()
Expand Down Expand Up @@ -144,7 +145,22 @@ def _check_provider_connection(self) -> bool:
)
return False

@property
def connectivity(self) -> List[List[int]]:
aws_connectivity = self.backend_device.topology_graph.edges
connectivity_list = [list(edge) for edge in aws_connectivity]
return connectivity_list
aws_device_properties = self.backend_device.properties
if hasattr(aws_device_properties, "topology_graph"):
aws_device_topology = aws_device_properties.topology_gprah
if aws_device_topology is not None:
self._connectivity = [
list(edge) for edge in aws_device_topology.edges
]
# else:
# return None
return self._connectivity

@connectivity.setter
def connectivity(self, value: List[List[int]]):
if isinstance(value, list):
self._connectivity = value
else:
raise TypeError("Connectivity must be a list of lists")
22 changes: 14 additions & 8 deletions src/openqaoa-braket/openqaoa_braket/backends/qaoa_braket_qpu.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from openqaoa.qaoa_components.variational_parameters.variational_baseparams import (
QAOAVariationalBaseParams,
)
from openqaoa.utilities import permute_counts_dictionary


class QAOAAWSQPUBackend(
Expand Down Expand Up @@ -85,9 +86,12 @@ def __init__(
else list(range(self.n_qubits))
)
else:
warnings.warn(
"Ignoring the initial_qubit_mapping since the routing algorithm chose one"
)
if isinstance(initial_qubit_mapping, list):
warnings.warn(
"Ignoring the initial_qubit_mapping since the routing algorithm chose one"
)
else:
pass
self.disable_qubit_rewiring = disable_qubit_rewiring

if self.prepend_state:
Expand Down Expand Up @@ -138,7 +142,6 @@ def qaoa_circuit(self, params: QAOAVariationalBaseParams) -> Circuit:
if self.append_state:
parametric_circuit += self.append_state

# TODO: needs to be fixed --> measurement operations on problem qubits
parametric_circuit += Probability.probability()

angles_list = self.obtain_angles_for_pauli_list(self.abstract_circuit, params)
Expand Down Expand Up @@ -252,11 +255,14 @@ def get_counts(self, params: QAOAVariationalBaseParams, n_shots=None) -> dict:
"An Error Occurred with the Task(s) sent to AWS."
)

final_counts = counts
# if self.final_mapping is not None:
# final_counts = permute_counts_dictionary(final_counts,
# self.final_mapping)
# # Expose counts
if self.final_mapping is not None:
counts = permute_counts_dictionary(counts, self.final_mapping)

final_counts = {key[: self.problem_qubits]: 0 for key in counts.keys()}
for key, value in counts.items():
final_counts[key[: self.problem_qubits]] += value

self.measurement_outcomes = final_counts
return final_counts

Expand Down
139 changes: 138 additions & 1 deletion src/openqaoa-braket/tests/test_qpu_braket.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import unittest
from unittest.mock import Mock
from unittest.mock import Mock, MagicMock
import numpy as np
import pytest

Expand Down Expand Up @@ -439,6 +439,143 @@ def test_remote_integration_qpu_run(self):
)
braket_backend.expectation(variate_params)

# Test to be improved, to be run when OQ starts supporting LocalSimulators from braket
# @pytest.mark.sim
# def test_braket_measurement_instructions(self):
# """
# When using the routing functionality within OpenQAOA, the
# final order of qubits is changed. This function tests for
# the functionality in the braket backend to reset the order
# of qubits in the measurement instructions.

# The goal is compare the output of a routed circuit to that of
# a non-routed circuit on the SV1 simulator to test the correctness
# of the output.
# """
# routing_function = MagicMock(
# return_value=(
# [
# [5, 7],
# [0, 4],
# [2, 6],
# [1, 6],
# [3, 7],
# [1, 3],
# [0, 5],
# [2, 4],
# [1, 6],
# [1, 3],
# [2, 6],
# [2, 4],
# [0, 4],
# [2, 6],
# [3, 7],
# [5, 7],
# [1, 3],
# [0, 5],
# [5, 7],
# [0, 4],
# [0, 4],
# [2, 4],
# [5, 7],
# [0, 5],
# [3, 7],
# [1, 6],
# [1, 3],
# [2, 6],
# [2, 4],
# [2, 6],
# [3, 7],
# [1, 3],
# [1, 6],
# [1, 3],
# [2, 6],
# [0, 5],
# [5, 7],
# [0, 4],
# [5, 7],
# [0, 4],
# [0, 5],
# ],
# [
# False,
# False,
# False,
# False,
# False,
# False,
# False,
# False,
# True,
# False,
# False,
# True,
# False,
# False,
# True,
# False,
# False,
# True,
# False,
# False,
# True,
# False,
# True,
# False,
# False,
# True,
# False,
# False,
# True,
# False,
# True,
# False,
# True,
# False,
# False,
# True,
# False,
# False,
# True,
# True,
# False,
# ],
# {1: 0, 5: 1, 3: 2, 6: 3, 2: 4, 0: 5, 4: 6, 7: 7},
# [3, 6, 7, 4, 0, 2, 1, 5],
# )
# )
# n_shots = 100
# # generate a random set of 8 integers
# set_of_numbers = [9, 4, 4, 7, 3, 1, 1, 9]
# qubo = NumberPartition(set_of_numbers).qubo

# mixer_hamil = X_mixer_hamiltonian(n_qubits=8)
# aws_device = DeviceAWS("arn:aws:braket:::device/quantum-simulator/amazon/sv1")

# qaoa_descriptor_routed = QAOADescriptor(
# qubo.hamiltonian, mixer_hamil, p=1, routing_function=routing_function
# )
# variate_params = create_qaoa_variational_params(
# qaoa_descriptor_routed, "standard", "rand"
# )
# braket_backend_routed = QAOAAWSQPUBackend(
# qaoa_descriptor_routed, aws_device, n_shots, None, None, True, 1.0
# )

# qaoa_descriptor = QAOADescriptor(qubo.hamiltonian, mixer_hamil, p=1)
# braket_backend = QAOAAWSQPUBackend(
# qaoa_descriptor, aws_device, n_shots, None, None, True, 1.0
# )

# list_angles = [[1.0, 0.0]]#, [0.8, 0.2], [0.6, 0.4], [0.4, 0.6]]
# for angles in list_angles:
# variate_params.update_from_raw(angles)
# # Run the circuit without routing
# non_routed_exp = braket_backend.expectation(variate_params)
# # Run the circuit with routing
# routed_exp = braket_backend_routed.expectation(variate_params)
# self.assertAlmostEqual(non_routed_exp, routed_exp, places=2)


if __name__ == "__main__":
unittest.main()
8 changes: 7 additions & 1 deletion src/openqaoa-core/openqaoa/utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -1719,7 +1719,8 @@ def is_valid_uuid(uuid_to_test: str) -> bool:


def permute_counts_dictionary(
counts_dictionary: dict, permutation_order: List[int]
counts_dictionary: dict,
permutation_order: List[int],
) -> dict:
"""Permutes the order of the qubits in the counts dictionary to the
original order if SWAP gates were used leading to modified qubit layout.
Expand All @@ -1735,6 +1736,11 @@ def permute_counts_dictionary(
`dict`
The permuted counts dictionary with qubits in the original place
"""
counts_dict_nqubits = len(list(counts_dictionary.keys())[0])
assert len(permutation_order) == counts_dict_nqubits, (
"The number of qubits in the permutation order should be equal"
"to the number of qubits in the counts dictionary."
)

# Create a mapping of original positions to final positions
# original order always goes from 0 -> n-1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,11 @@ def __init__(
if initial_qubit_mapping is not None
else list(range(self.n_qubits))
)
else:
if isinstance(initial_qubit_mapping, list):
warnings.warn(
"Ignoring the initial_qubit_mapping since the routing algorithm chose one"
)

# self.qureg_placeholders = QubitPlaceholder.register(self.n_qubits)
self.qubit_mapping = dict(zip(self.qureg, self.initial_qubit_mapping))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ def __init__(
if initial_qubit_mapping is not None
else list(range(self.n_qubits))
)
else:
if isinstance(initial_qubit_mapping, list):
warnings.warn(
"Ignoring the initial_qubit_mapping since the routing algorithm chose one"
)

if self.prepend_state:
assert self.n_qubits >= len(prepend_state.qubits), (
Expand Down

0 comments on commit bfb0bbf

Please sign in to comment.