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 7 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 src/openqaoa-braket/openqaoa_braket/backends/devices.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,4 @@ def _check_provider_connection(self) -> bool:
return False

def connectivity(self) -> List[List[int]]:
return self.backend_device.topology_graph.edges
return list(self.backend_device.topology_graph.edges)
vishal-ph marked this conversation as resolved.
Show resolved Hide resolved
23 changes: 14 additions & 9 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,8 +142,7 @@ 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()
parametric_circuit += Probability.probability(target=self.problem_reg)

angles_list = self.obtain_angles_for_pauli_list(self.abstract_circuit, params)
memory_map = dict(
Expand Down Expand Up @@ -252,11 +255,13 @@ 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 None:
final_counts = counts
else:
final_counts = permute_counts_dictionary(
counts, self.final_mapping[: self.problem_qubits]
)
self.measurement_outcomes = final_counts
return final_counts

Expand Down
147 changes: 142 additions & 5 deletions 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 @@ -83,7 +83,7 @@ def test_circuit_angle_assignment_qpu_backend(self):
main_circuit.rx(0, -2 * betas[1])
main_circuit.rx(1, -2 * betas[1])
main_circuit.rx(2, -2 * betas[1])
main_circuit.probability()
main_circuit.probability(target=aws_backend.problem_reg)

self.assertEqual(main_circuit, qpu_circuit)

Expand Down Expand Up @@ -145,7 +145,7 @@ def test_circuit_angle_assignment_qpu_backend_w_hadamard(self):
main_circuit.rx(0, -2 * betas[1])
main_circuit.rx(1, -2 * betas[1])
main_circuit.rx(2, -2 * betas[1])
main_circuit.probability()
main_circuit.probability(target=aws_backend.problem_reg)

self.assertEqual(main_circuit, qpu_circuit)

Expand Down Expand Up @@ -204,7 +204,7 @@ def test_prepend_circuit(self):
main_circuit.rx(0, -2 * betas[0])
main_circuit.rx(1, -2 * betas[0])
main_circuit.rx(2, -2 * betas[0])
main_circuit.probability()
main_circuit.probability(target=aws_backend.problem_reg)

self.assertEqual(main_circuit, qpu_circuit)

Expand Down Expand Up @@ -264,7 +264,7 @@ def test_append_circuit(self):
main_circuit.x(0)
main_circuit.x(1)
main_circuit.x(2)
main_circuit.probability()
main_circuit.probability(target=aws_backend.problem_reg)

self.assertEqual(main_circuit, qpu_circuit)

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,13 @@ 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"
)
else:
vishal-ph marked this conversation as resolved.
Show resolved Hide resolved
pass

# 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 @@ -87,6 +87,13 @@ 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"
)
else:
vishal-ph marked this conversation as resolved.
Show resolved Hide resolved
pass

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