diff --git a/.github/workflows/test_dev.yml b/.github/workflows/test_dev.yml index da339fd64..f2c7b3d84 100644 --- a/.github/workflows/test_dev.yml +++ b/.github/workflows/test_dev.yml @@ -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: diff --git a/.github/workflows/test_main_linux.yml b/.github/workflows/test_main_linux.yml index 158947692..65b39c541 100644 --- a/.github/workflows/test_main_linux.yml +++ b/.github/workflows/test_main_linux.yml @@ -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 diff --git a/.github/workflows/test_main_macos.yml b/.github/workflows/test_main_macos.yml index c60dd7d9b..f1a3fc0fd 100644 --- a/.github/workflows/test_main_macos.yml +++ b/.github/workflows/test_main_macos.yml @@ -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)' diff --git a/.github/workflows/test_main_windows.yml b/.github/workflows/test_main_windows.yml index 061e1929e..7f38e2dce 100644 --- a/.github/workflows/test_main_windows.yml +++ b/.github/workflows/test_main_windows.yml @@ -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)'} diff --git a/.gitignore b/.gitignore index 67a886bb8..cfd0ed33f 100644 --- a/.gitignore +++ b/.gitignore @@ -138,4 +138,7 @@ dmypy.json braket-job*/ # Visual Studio code -.vscode/ \ No newline at end of file +.vscode/ + +debug.txt +debug_copy.txt \ No newline at end of file diff --git a/Makefile b/Makefile index 72305c260..e144f4486 100644 --- a/Makefile +++ b/Makefile @@ -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 . @@ -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 . @@ -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 . @@ -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 . @@ -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 . diff --git a/src/openqaoa-core/openqaoa/backends/qaoa_device.py b/src/openqaoa-core/openqaoa/backends/qaoa_device.py index f07826c20..650fe17d2 100644 --- a/src/openqaoa-core/openqaoa/backends/qaoa_device.py +++ b/src/openqaoa-core/openqaoa/backends/qaoa_device.py @@ -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, diff --git a/src/openqaoa-pyquil/openqaoa_pyquil/backend_config.py b/src/openqaoa-pyquil/openqaoa_pyquil/backend_config.py index ad28a6272..5471ed045 100644 --- a/src/openqaoa-pyquil/openqaoa_pyquil/backend_config.py +++ b/src/openqaoa-pyquil/openqaoa_pyquil/backend_config.py @@ -18,7 +18,7 @@ "execution_timeout", "client_configuration", "endpoint_id", - "engagement_manager", + # "engagement_manager", ] } backend_args = { diff --git a/src/openqaoa-pyquil/openqaoa_pyquil/backends/devices.py b/src/openqaoa-pyquil/openqaoa_pyquil/backends/devices.py index 78b5b9694..a0430b704 100644 --- a/src/openqaoa-pyquil/openqaoa_pyquil/backends/devices.py +++ b/src/openqaoa-pyquil/openqaoa_pyquil/backends/devices.py @@ -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 @@ -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 @@ -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 @@ -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, @@ -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()) diff --git a/src/openqaoa-pyquil/openqaoa_pyquil/backends/qaoa_pyquil_qpu.py b/src/openqaoa-pyquil/openqaoa_pyquil/backends/qaoa_pyquil_qpu.py index 1860917d8..455297ebf 100644 --- a/src/openqaoa-pyquil/openqaoa_pyquil/backends/qaoa_pyquil_qpu.py +++ b/src/openqaoa-pyquil/openqaoa_pyquil/backends/qaoa_pyquil_qpu.py @@ -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 @@ -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 @@ -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: @@ -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" ) @@ -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. @@ -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 @@ -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: @@ -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") @@ -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 diff --git a/src/openqaoa-pyquil/requirements.txt b/src/openqaoa-pyquil/requirements.txt index 19adc00df..c4fc2f327 100644 --- a/src/openqaoa-pyquil/requirements.txt +++ b/src/openqaoa-pyquil/requirements.txt @@ -1 +1 @@ -pyquil>=3.1.0,<4.0.0 \ No newline at end of file +pyquil \ No newline at end of file diff --git a/src/openqaoa-pyquil/tests/test_circuit_routing_pyquil.py b/src/openqaoa-pyquil/tests/test_circuit_routing_pyquil.py index 80f2de3bc..994198831 100644 --- a/src/openqaoa-pyquil/tests/test_circuit_routing_pyquil.py +++ b/src/openqaoa-pyquil/tests/test_circuit_routing_pyquil.py @@ -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( @@ -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, @@ -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, @@ -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 diff --git a/src/openqaoa-pyquil/tests/test_gate_applicators_pyquil.py b/src/openqaoa-pyquil/tests/test_gate_applicators_pyquil.py index a64af8785..da11f1d23 100644 --- a/src/openqaoa-pyquil/tests/test_gate_applicators_pyquil.py +++ b/src/openqaoa-pyquil/tests/test_gate_applicators_pyquil.py @@ -245,10 +245,10 @@ def test_static_methods_1q(self): self.assertEqual( [ - each_instruction.get_qubits() + each_instruction.get_qubit_indices() for each_instruction in circuit.instructions ], - [{0}], + [[0]], ) self.assertEqual( [ @@ -284,10 +284,10 @@ def test_static_methods_1qr(self): ) self.assertEqual( [ - each_instruction.get_qubits() + each_instruction.get_qubit_indices() for each_instruction in circuit.instructions ], - [{0}], + [[0]], ) self.assertEqual( [ @@ -322,10 +322,10 @@ def test_static_methods_2q(self): self.assertEqual( [ - each_instruction.get_qubits() + each_instruction.get_qubit_indices() for each_instruction in circuit.instructions ], - [{0, 1}], + [[0, 1]], ) self.assertEqual( [ @@ -369,10 +369,10 @@ def test_static_methods_2qr(self): ) self.assertEqual( [ - each_instruction.get_qubits() + each_instruction.get_qubit_indices() for each_instruction in circuit.instructions ], - [{0, 1}], + [[0, 1]], ) self.assertEqual( [ diff --git a/src/openqaoa-pyquil/tests/test_pyquil_qvm.py b/src/openqaoa-pyquil/tests/test_pyquil_qvm.py index bd44f0730..e27e0e39b 100644 --- a/src/openqaoa-pyquil/tests/test_pyquil_qvm.py +++ b/src/openqaoa-pyquil/tests/test_pyquil_qvm.py @@ -224,11 +224,11 @@ def test_qaoa_pyquil_gate_names(self): "RX", "RX", ] - + program, _ = backend_obj_pyquil.qaoa_circuit(params) measurement_gate_no = len( [ instr - for instr in backend_obj_pyquil.qaoa_circuit(params) + for instr in program if type(instr) == quilbase.Measurement ] ) @@ -276,10 +276,11 @@ def test_qaoa_pyquil_gate_names(self): "RX", ] + program, _ = backend_obj_pyquil.qaoa_circuit(params) measurement_gate_no = len( [ instr - for instr in backend_obj_pyquil.qaoa_circuit(params) + for instr in program if type(instr) == quilbase.Measurement ] ) @@ -391,7 +392,7 @@ def test_circuit_append_state(self): init_hadamard=False, cvar_alpha=1, ) - + program, _ = pyquil_backend.qaoa_circuit(params) assert set( [ "RZ", @@ -434,7 +435,7 @@ def test_circuit_append_state(self): ) == set( [ instr.name - for instr in pyquil_backend.qaoa_circuit(params) + for instr in program if type(instr) == quilbase.Gate ] ) diff --git a/tests/test_imports.py b/tests/test_imports.py index a745087a8..28ccfbc14 100644 --- a/tests/test_imports.py +++ b/tests/test_imports.py @@ -17,9 +17,7 @@ def test_all_module_import(self): """ folder_names = [ - each_file - for each_file in os.listdir("src") - if ("openqaoa-" in each_file and not "openqaoa-pyquil") + each_file for each_file in os.listdir("src") if "openqaoa" in each_file ] packages_import = []