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

Update for pyquil 4.x #300

Merged
merged 16 commits into from
Mar 25, 2024
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 .github/workflows/test_dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ jobs:
run: |
source env/bin/activate
ipython kernel install --name "env" --user
pytest tests/ src/openqaoa-core/tests src/openqaoa-azure/tests src/openqaoa-braket/tests src/openqaoa-qiskit/tests -m 'not (qpu or sim)' --cov -n auto
pytest tests/ src/*/tests -m 'not (qpu or sim)' --cov -n auto
- name: Upload coverage reports to Codecov with GitHub Action
uses: codecov/codecov-action@v3
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test_main_linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ jobs:
run: |
source env/bin/activate
ipython kernel install --name "env" --user
pytest tests/ src/openqaoa-core/tests src/openqaoa-azure/tests src/openqaoa-braket/tests src/openqaoa-qiskit/tests -m 'not (qpu or sim)' --cov --cov-report=xml:coverage.xml
pytest tests/ src/*/tests -m 'not (qpu or sim)' --cov --cov-report=xml:coverage.xml
- name: Upload coverage reports to Codecov with GitHub Action
uses: codecov/codecov-action@v3
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test_main_macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,4 @@ jobs:
run: |
source env/bin/activate
ipython kernel install --user --name "env"
pytest tests/ src/openqaoa-core/tests src/openqaoa-azure/tests src/openqaoa-braket/tests src/openqaoa-qiskit/tests -m 'not (qpu or api or docker_aws or braket_api or sim)'
pytest tests/ src/*/tests -m 'not (qpu or api or docker_aws or braket_api or sim)'
2 changes: 1 addition & 1 deletion .github/workflows/test_main_windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,5 @@ jobs:
run: |
.\env\Scripts\Activate.ps1
ipython kernel install --name "env" --user
pytest tests/ src/openqaoa-core/tests src/openqaoa-azure/tests src/openqaoa-braket/tests src/openqaoa-qiskit/tests -m 'not (qpu or api or docker_aws or braket_api or sim)'
pytest tests/ src/*/tests -m 'not (qpu or api or docker_aws or braket_api or sim)'
Get-ChildItem -Directory | ForEach-Object { pytest $_.FullName -m 'not (qpu or api or docker_aws or braket_api or sim)'}
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -138,4 +138,7 @@ dmypy.json
braket-job*/

# Visual Studio code
.vscode/
.vscode/

debug.txt
debug_copy.txt
10 changes: 5 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
local-install:
pip install ./src/openqaoa-core
pip install ./src/openqaoa-qiskit
# pip install ./src/openqaoa-pyquil
pip install ./src/openqaoa-pyquil
pip install ./src/openqaoa-braket
pip install ./src/openqaoa-azure
pip install .
Expand All @@ -14,7 +14,7 @@ local-install:
dev-install:
pip install -e ./src/openqaoa-core
pip install -e ./src/openqaoa-qiskit
# pip install -e ./src/openqaoa-pyquil
pip install -e ./src/openqaoa-pyquil
pip install -e ./src/openqaoa-braket
pip install -e ./src/openqaoa-azure
pip install -e .
Expand All @@ -23,7 +23,7 @@ dev-install:
dev-install-tests:
pip install -e ./src/openqaoa-core[tests]
pip install -e ./src/openqaoa-qiskit
# pip install -e ./src/openqaoa-pyquil
pip install -e ./src/openqaoa-pyquil
pip install -e ./src/openqaoa-braket
pip install -e ./src/openqaoa-azure
pip install -e .
Expand All @@ -32,7 +32,7 @@ dev-install-tests:
dev-install-docs:
pip install -e ./src/openqaoa-core[docs]
pip install -e ./src/openqaoa-qiskit
# pip install -e ./src/openqaoa-pyquil
pip install -e ./src/openqaoa-pyquil
pip install -e ./src/openqaoa-braket
pip install -e ./src/openqaoa-azure
pip install -e .
Expand All @@ -41,7 +41,7 @@ dev-install-docs:
dev-install-all:
pip install -e ./src/openqaoa-core[all]
pip install -e ./src/openqaoa-qiskit
# pip install -e ./src/openqaoa-pyquil
pip install -e ./src/openqaoa-pyquil
pip install -e ./src/openqaoa-braket
pip install -e ./src/openqaoa-azure
pip install -e .
Expand Down
4 changes: 2 additions & 2 deletions src/openqaoa-core/openqaoa/backends/qaoa_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ def device_class_arg_mapper(
noisy: bool = None,
compiler_timeout: float = None,
execution_timeout: float = None,
client_configuration: QCSClientConfiguration = None,
client_configuration: QCSClient = None,
endpoint_id: str = None,
engagement_manager: EngagementManager = None,
# engagement_manager: EngagementManager = None,
folder_name: str = None,
s3_bucket_name: str = None,
aws_region: str = None,
Expand Down
2 changes: 1 addition & 1 deletion src/openqaoa-pyquil/openqaoa_pyquil/backend_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"execution_timeout",
"client_configuration",
"endpoint_id",
"engagement_manager",
# "engagement_manager",
]
}
backend_args = {
Expand Down
21 changes: 11 additions & 10 deletions src/openqaoa-pyquil/openqaoa_pyquil/backends/devices.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from typing import List
from qcs_api_client.client import QCSClientConfiguration
from pyquil.api._engagement_manager import EngagementManager
# from qcs_api_client.client import QCSClientConfiguration
from pyquil.api import QCSClient
# from pyquil.api._engagement_manager import EngagementManager
from pyquil import get_qc

from openqaoa.backends.devices_core import DeviceBase
Expand All @@ -25,9 +26,9 @@ def __init__(
noisy: bool = None,
compiler_timeout: float = 20.0,
execution_timeout: float = 20.0,
client_configuration: QCSClientConfiguration = None,
client_configuration: QCSClient = None,
endpoint_id: str = None,
engagement_manager: EngagementManager = None,
# engagement_manager: EngagementManager = None,
):
"""
Parameters
Expand Down Expand Up @@ -56,15 +57,15 @@ def __init__(
Time limit for compilation requests, in seconds.
execution_timeout: float
Time limit for execution requests, in seconds.
client_configuration: QCSClientConfiguration
client_configuration: QCSClient
Optional client configuration. If none is provided, a default one
will be loaded.
endpoint_id: str
Optional quantum processor endpoint ID, as used in the
`QCS API Docs`_.
engagement_manager: EngagementManager
Optional engagement manager. If none is provided, a default one will
be created.
# engagement_manager: EngagementManager
# Optional engagement manager. If none is provided, a default one will
# be created.
"""

self.device_name = device_name
Expand All @@ -75,7 +76,7 @@ def __init__(
self.execution_timeout = execution_timeout
self.client_configuration = client_configuration
self.endpoint_id = endpoint_id
self.engagement_manager = engagement_manager
# self.engagement_manager = engagement_manager

self.quantum_computer = get_qc(
name=self.device_name,
Expand All @@ -85,7 +86,7 @@ def __init__(
execution_timeout=self.execution_timeout,
client_configuration=self.client_configuration,
endpoint_id=self.endpoint_id,
engagement_manager=self.engagement_manager,
# engagement_manager=self.engagement_manager,
)
self.n_qubits = len(self.quantum_computer.qubits())

Expand Down
101 changes: 70 additions & 31 deletions src/openqaoa-pyquil/openqaoa_pyquil/backends/qaoa_pyquil_qpu.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import numpy as np
from copy import deepcopy
from pyquil import Program, gates, quilbase
from typing import List, Optional
from typing import List, Optional, Tuple
import warnings

from .devices import DevicePyquil
Expand All @@ -16,7 +16,7 @@
from openqaoa.qaoa_components.variational_parameters.variational_baseparams import (
QAOAVariationalBaseParams,
)
from openqaoa.qaoa_components.ansatz_constructor.gatemap import RZZGateMap, SWAPGateMap
from openqaoa.qaoa_components.ansatz_constructor.gatemap import RZZGateMap, SWAPGateMap, GateMap
from openqaoa.qaoa_components.ansatz_constructor.rotationangle import RotationAngle
from openqaoa.utilities import generate_uuid

Expand Down Expand Up @@ -44,7 +44,7 @@ def check_edge_connectivity(executable: Program, device: DevicePyquil):

instrs = [instr for instr in executable if type(instr) == quilbase.Gate]
pair_instrs = [
list(instr.get_qubits()) for instr in instrs if len(instr.get_qubits()) == 2
list(instr.get_qubit_indices()) for instr in instrs if len(instr.get_qubit_indices()) == 2
]

for term in pair_instrs:
Expand Down Expand Up @@ -137,7 +137,7 @@ def __init__(
self.qubit_mapping = dict(zip(self.qureg, self.initial_qubit_mapping))

if self.prepend_state:
assert self.n_qubits >= len(prepend_state.get_qubits()), (
assert self.n_qubits >= len(prepend_state.get_qubit_indices()), (
"Cannot attach a bigger circuit " "to the QAOA routine"
)

Expand All @@ -153,7 +153,58 @@ def __init__(

# check_edge_connectivity(self.prog_exe, device)

def qaoa_circuit(self, params: QAOAVariationalBaseParams) -> Program:
def obtain_angles_for_pauli_list(
self, input_gate_list: List[GateMap], params: QAOAVariationalBaseParams
) -> List[Tuple[float, str]]:
"""
This method uses the pauli gate list information to obtain the pauli angles
from the VariationalBaseParams object. The floats in the list are in the order
of the input GateMaps list.
Parameters
----------
input_gate_list: `List[GateMap]`
The GateMap list including rotation gates
params: `QAOAVariationalBaseParams`
The variational parameters(angles) to be assigned to the circuit gates
Returns
-------
angles_list: `List[Tuple[float, str]]`
The list of angles and their names in the order of gates in the `GateMap` list
"""
angle_list = []

for each_gate in input_gate_list:
gate_label_layer = each_gate.gate_label.layer
gate_label_seq = each_gate.gate_label.sequence

if each_gate.gate_label.n_qubits == 2:
if each_gate.gate_label.type.value == "MIXER":
angle_list.append(
(params.mixer_2q_angles[gate_label_layer, gate_label_seq],
f"twoq_mixer_seq{gate_label_seq}_layer{gate_label_layer}")
)
elif each_gate.gate_label.type.value == "COST":
angle_list.append(
(params.cost_2q_angles[gate_label_layer, gate_label_seq],
f"twoq_cost_seq{gate_label_seq}_layer{gate_label_layer}")
)
elif each_gate.gate_label.n_qubits == 1:
if each_gate.gate_label.type.value == "MIXER":
angle_list.append(
(params.mixer_1q_angles[gate_label_layer, gate_label_seq],
f"oneq_mixer_seq{gate_label_seq}_layer{gate_label_layer}")
)
elif each_gate.gate_label.type.value == "COST":
angle_list.append(
(params.cost_1q_angles[gate_label_layer, gate_label_seq],
f"oneq_cost_seq{gate_label_seq}_layer{gate_label_layer}")
)

return angle_list

def qaoa_circuit(self, params: QAOAVariationalBaseParams) -> Tuple[Program, dict]:
"""
Injects angles into created executable parametric circuit.
Expand All @@ -165,6 +216,8 @@ def qaoa_circuit(self, params: QAOAVariationalBaseParams) -> Program:
-------
`pyquil.Program`
A pyquil.Program (executable) object.
dict
A dictionary of the memory map for the program.
"""
parametric_circuit = deepcopy(self.parametric_circuit)
# declare the read-out register
Expand All @@ -183,26 +236,13 @@ def qaoa_circuit(self, params: QAOAVariationalBaseParams) -> Program:
parametric_circuit += gates.MEASURE(self.qubit_mapping[qubit], cbit)
parametric_circuit.wrap_in_numshots_loop(self.n_shots)

native = self.device.quantum_computer.compiler.quil_to_native_quil(
parametric_circuit
)
angle_values_and_names= self.obtain_angles_for_pauli_list(self.abstract_circuit, params)

memory_map = {value_name[1] : [value_name[0]] for value_name in angle_values_and_names}

prog_exe = self.device.quantum_computer.compile(parametric_circuit)

prog_exe = self.device.quantum_computer.compiler.native_quil_to_executable(
native
)

angles_list = np.array(
self.obtain_angles_for_pauli_list(self.abstract_circuit, params),
dtype=float,
)
angle_declarations = list(parametric_circuit.declarations.keys())

angle_declarations.remove("ro")

for i, param_name in enumerate(angle_declarations):
prog_exe.write_memory(region_name=param_name, value=angles_list[i])

return prog_exe
return prog_exe, memory_map

@property
def parametric_qaoa_circuit(self) -> Program:
Expand Down Expand Up @@ -264,7 +304,7 @@ def parametric_qaoa_circuit(self) -> Program:
if each_gate.gate_label.n_qubits == 1
else "two" + gatelabel_pyquil[1:]
)
angle_param = parametric_circuit.declare(gatelabel_pyquil, "REAL", 1)
angle_param = parametric_circuit.declare(gatelabel_pyquil.lower(), "REAL", 1)
each_gate.angle_value = angle_param
if isinstance(each_gate, RZZGateMap) or isinstance(each_gate, SWAPGateMap):
decomposition = each_gate.decomposition("standard2")
Expand Down Expand Up @@ -311,20 +351,19 @@ def get_counts(self, params: QAOAVariationalBaseParams, n_shots=None) -> dict:
A dictionary with the bitstring as the key and the number of counts as its value.
"""

executable_program = self.qaoa_circuit(params)

# if n_shots is given change the number of shots
executable_program, memory_map = self.qaoa_circuit(params)

if n_shots is not None:
executable_program.wrap_in_numshots_loop(n_shots)

result = self.device.quantum_computer.run(executable_program)
result = self.device.quantum_computer.run(executable_program, memory_map=memory_map)
# we create an uuid for the job
self.job_id = generate_uuid()

# TODO: check the endian (big or little) ordering of measurement outcomes
meas_list = [
"".join(str(bit) for bit in bitstring)
for bitstring in result.readout_data["ro"]
for bitstring in result.get_register_map().get("ro")
]

# Expose counts
Expand Down
2 changes: 1 addition & 1 deletion src/openqaoa-pyquil/requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
pyquil>=3.1.0,<4.0.0
pyquil
9 changes: 6 additions & 3 deletions src/openqaoa-pyquil/tests/test_circuit_routing_pyquil.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,12 @@ def routing_function_test1(device, problem_to_solve):
)
device_pyquil.quantum_computer.qam.random_seed = seed

for i in range(len(p_lst)):
# for i in range(len(p_lst)):
for i in [0,1,2,3,4]:
p = p_lst[i]
args = args_lst[i]
cost_hamil = cost_hamil_lst[i]

# With routing
mixer_hamil = X_mixer_hamiltonian(n_qubits=2)
qaoa_descriptor = QAOADescriptor(
Expand All @@ -130,6 +131,7 @@ def routing_function_test1(device, problem_to_solve):
)

variate_params.update_from_raw(args)

backend_obj_pyquil = QAOAPyQuilQPUBackend(
qaoa_descriptor=qaoa_descriptor,
device=device_pyquil,
Expand All @@ -149,6 +151,7 @@ def routing_function_test1(device, problem_to_solve):
)

variate_params.update_from_raw(args)

backend_obj_pyquil = QAOAPyQuilQPUBackend(
qaoa_descriptor=qaoa_descriptor,
device=device_pyquil,
Expand Down Expand Up @@ -487,7 +490,7 @@ def routing_function_test1(device, problem_to_solve):
),
]

device_name_lst = ["2q-qvm", "3q-qvm", "Aspen-M-3"]
device_name_lst = ["2q-qvm", "3q-qvm", "9q-qvm"]

shots = 2
seed = 1
Expand Down
Loading
Loading