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

braket measurement fix, qiskit, pyquil initial_qubit_mapping fix #211

Merged
merged 18 commits into from
Aug 4, 2023
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
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"):
Q-lds marked this conversation as resolved.
Show resolved Hide resolved
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"
Q-lds marked this conversation as resolved.
Show resolved Hide resolved
)
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

vishal-ph marked this conversation as resolved.
Show resolved Hide resolved
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