diff --git a/examples/15_Zero_Noise_Extrapolation.ipynb b/examples/15_Zero_Noise_Extrapolation.ipynb index 4225b393..25b938a4 100644 --- a/examples/15_Zero_Noise_Extrapolation.ipynb +++ b/examples/15_Zero_Noise_Extrapolation.ipynb @@ -336,7 +336,7 @@ "Available options to set up the ZNE with `set_error_mitigation_properties`:\n", "\n", "- **factory**: The name of the zero-noise extrapolation method. Supported values: \"Richardson\", \"Linear\", \"Poly\", \"Exp\", \"PolyExp\", \"AdaExp\", \"FakeNodes\".\n", - "- **scaling**: The name of the function for scaling the noise of a quantum circuit. Supported values: \"fold_gates_at_random\", \"fold_gates_from_right\", \"fold_gates_from_left\".\n", + "- **scaling**: The name of the function for scaling the noise of a quantum circuit. Supported values: \"fold_gates_at_random\" (\"fold_gates_from_right\", \"fold_gates_from_left\" not supported as of version 0.8).\n", "- **scale_factors**: List[int] Sequence of noise scale factors at which expectation values should be measured. For factory = \"AdaExp\", just the first element of the list will be considered.\n", "- **order**: Extrapolation order (degree of the polynomial fit). It cannot exceed len(scale_factors) - 1. Only used for factory = \"Poly\" or \"PolyExp\".\n", "- **steps**: The number of optimization steps. At least 3 are necessary. Only used for factory = \"AdaExp\"." diff --git a/src/openqaoa-core/openqaoa/algorithms/baseworkflow.py b/src/openqaoa-core/openqaoa/algorithms/baseworkflow.py index ab2c43ab..454a06c3 100644 --- a/src/openqaoa-core/openqaoa/algorithms/baseworkflow.py +++ b/src/openqaoa-core/openqaoa/algorithms/baseworkflow.py @@ -283,7 +283,7 @@ def set_error_mitigation_properties(self, **kwargs): factory: str Used in "mitiq_zne". The name of the zero-noise extrapolation method. Supported values: "Richardson", "Linear", "Poly", "Exp", "PolyExp", "AdaExp", "FakeNodes". scaling: str - Used in "mitiq_zne". The name of the function for scaling the noise of a quantum circuit. Supported values: "fold_gates_at_random", "fold_gates_from_right", "fold_gates_from_left". + Used in "mitiq_zne". The name of the function for scaling the noise of a quantum circuit. Supported values: "fold_gates_at_random" ("fold_gates_from_right", "fold_gates_from_left" not supported as of version 0.8) scale_factors: List[int] Used in "mitiq_zne". Sequence of noise scale factors at which expectation values should be measured. For factory = "AdaExp", just the first element of the list will be considered. diff --git a/src/openqaoa-core/openqaoa/algorithms/workflow_properties.py b/src/openqaoa-core/openqaoa/algorithms/workflow_properties.py index a49a1a17..57d549e4 100644 --- a/src/openqaoa-core/openqaoa/algorithms/workflow_properties.py +++ b/src/openqaoa-core/openqaoa/algorithms/workflow_properties.py @@ -354,7 +354,7 @@ class MitiqZNEProperties(ErrorMitigationProperties): factory: str The name of the zero-noise extrapolation method. Supported values: "Richardson", "Linear", "Poly", "Exp", "PolyExp", "AdaExp", "FakeNodes". scaling: str - The name of the function for scaling the noise of a quantum circuit. Supported values: "fold_gates_at_random", "fold_gates_from_right", "fold_gates_from_left". + The name of the function for scaling the noise of a quantum circuit. Supported values: "fold_gates_at_random" ("fold_gates_from_right", "fold_gates_from_left" not supported as of version 0.8). scale_factors: List[int] Sequence of noise scale factors at which expectation values should be measured. For factory = "AdaExp", just the first element of the list will be considered. diff --git a/src/openqaoa-core/openqaoa/backends/wrapper.py b/src/openqaoa-core/openqaoa/backends/wrapper.py index 14d90a4e..a8be6d1c 100644 --- a/src/openqaoa-core/openqaoa/backends/wrapper.py +++ b/src/openqaoa-core/openqaoa/backends/wrapper.py @@ -3,7 +3,7 @@ import json from mitiq.zne.inference import RichardsonFactory, LinearFactory, PolyExpFactory, PolyFactory, AdaExpFactory, FakeNodesFactory, ExpFactory -from mitiq.zne.scaling import fold_gates_at_random, fold_gates_from_left, fold_gates_from_right +from mitiq.zne.scaling import fold_gates_at_random from mitiq.zne import execute_with_zne import copy @@ -75,8 +75,6 @@ def exact_solution(self, *args, **kwargs): ] available_scaling = [ "fold_gates_at_random", - "fold_gates_from_right", - "fold_gates_from_left" ] class ZNEWrapper(BaseWrapper): """ @@ -92,7 +90,7 @@ class ZNEWrapper(BaseWrapper): factory: str The name of the zero-noise extrapolation method. Supported values: "Richardson", "Linear", "Poly", "Exp", "PolyExp", "AdaExp", "FakeNodes". scaling: str - The name of the function for scaling the noise of a quantum circuit. Supported values: "fold_gates_at_random", "fold_gates_from_right", "fold_gates_from_left". + The name of the function for scaling the noise of a quantum circuit. Supported values: "fold_gates_at_random" ("fold_gates_from_right", "fold_gates_from_left" not supported as of version 0.8). scale_factors: List[int] Sequence of noise scale factors at which expectation values should be measured. For factory = "AdaExp", just the first element of the list will be considered. @@ -116,7 +114,7 @@ def __init__(self, backend, factory, scaling, scale_factors, order, steps): if(factory not in available_factories): raise ValueError("Supported factories are: Poly, Richardson, Exp, FakeNodes, Linear, PolyExp, AdaExp") if(scaling not in available_scaling): - raise ValueError("Supported scaling methods are: fold_gates_at_random, fold_gates_from_right, fold_gates_from_left") + raise ValueError("Supported scaling methods are: fold_gates_at_random") if(not isinstance(scale_factors, list) or not all(isinstance(x, int) and x >= 1 for x in scale_factors)): raise ValueError("Scale factor must be a list of ints greater than or equal to 1") if(type(order) != int or order < 1): @@ -145,10 +143,6 @@ def __init__(self, backend, factory, scaling, scale_factors, order, steps): self.scale_noise = None if scaling == "fold_gates_at_random": self.scale_noise = fold_gates_at_random - elif scaling == "fold_gates_from_left": - self.scale_noise = fold_gates_from_left - elif scaling == "fold_gates_from_right": - self.scale_noise = fold_gates_from_right #setting the scale_factors self.scale_factors = scale_factors diff --git a/src/openqaoa-qiskit/tests/test_qpu_qiskit.py b/src/openqaoa-qiskit/tests/test_qpu_qiskit.py index 78707b72..88793669 100644 --- a/src/openqaoa-qiskit/tests/test_qpu_qiskit.py +++ b/src/openqaoa-qiskit/tests/test_qpu_qiskit.py @@ -79,13 +79,13 @@ def test_circuit_angle_assignment_qpu_backend(self): nqubits = 3 p = 2 - weights = [1, 1, 1] + weights = [1, 1] gammas = [0, 1 / 8 * np.pi] betas = [1 / 2 * np.pi, 3 / 8 * np.pi] - shots = 10000 + shots = 1 cost_hamil = Hamiltonian( - [PauliOp("ZZ", (0, 1)), PauliOp("ZZ", (1, 2)), PauliOp("ZZ", (0, 2))], + [PauliOp("ZZ", (0, 1)), PauliOp("ZZ", (1, 2))], weights, 1, ) @@ -94,13 +94,14 @@ def test_circuit_angle_assignment_qpu_backend(self): variate_params = QAOAVariationalStandardParams(qaoa_descriptor, betas, gammas) qiskit_device = DeviceQiskit( - "ibmq_qasm_simulator", self.HUB, self.GROUP, self.PROJECT + "ibm_kyoto", self.HUB, self.GROUP, self.PROJECT ) qiskit_backend = QAOAQiskitQPUBackend( qaoa_descriptor, qiskit_device, shots, None, None, False ) qpu_circuit = qiskit_backend.qaoa_circuit(variate_params) + qpu_circuit.draw() # Standard Decomposition main_circuit = QuantumCircuit(3) @@ -110,9 +111,6 @@ def test_circuit_angle_assignment_qpu_backend(self): main_circuit.cx(1, 2) main_circuit.rz(2 * gammas[0], 2) main_circuit.cx(1, 2) - main_circuit.cx(0, 2) - main_circuit.rz(2 * gammas[0], 2) - main_circuit.cx(0, 2) main_circuit.rx(-2 * betas[0], 0) main_circuit.rx(-2 * betas[0], 1) main_circuit.rx(-2 * betas[0], 2) @@ -122,9 +120,6 @@ def test_circuit_angle_assignment_qpu_backend(self): main_circuit.cx(1, 2) main_circuit.rz(2 * gammas[1], 2) main_circuit.cx(1, 2) - main_circuit.cx(0, 2) - main_circuit.rz(2 * gammas[1], 2) - main_circuit.cx(0, 2) main_circuit.rx(-2 * betas[1], 0) main_circuit.rx(-2 * betas[1], 1) main_circuit.rx(-2 * betas[1], 2) @@ -144,13 +139,13 @@ def test_circuit_angle_assignment_qpu_backend_w_hadamard(self): nqubits = 3 p = 2 - weights = [1, 1, 1] + weights = [1, 1] gammas = [0, 1 / 8 * np.pi] betas = [1 / 2 * np.pi, 3 / 8 * np.pi] - shots = 10000 + shots = 1 cost_hamil = Hamiltonian( - [PauliOp("ZZ", (0, 1)), PauliOp("ZZ", (1, 2)), PauliOp("ZZ", (0, 2))], + [PauliOp("ZZ", (0, 1)), PauliOp("ZZ", (1, 2))], weights, 1, ) @@ -159,7 +154,7 @@ def test_circuit_angle_assignment_qpu_backend_w_hadamard(self): variate_params = QAOAVariationalStandardParams(qaoa_descriptor, betas, gammas) qiskit_device = DeviceQiskit( - "ibmq_qasm_simulator", self.HUB, self.GROUP, self.PROJECT + "ibm_kyoto", self.HUB, self.GROUP, self.PROJECT ) qiskit_backend = QAOAQiskitQPUBackend( @@ -173,9 +168,6 @@ def test_circuit_angle_assignment_qpu_backend_w_hadamard(self): main_circuit.cx(0, 1) main_circuit.rz(2 * gammas[0], 1) main_circuit.cx(0, 1) - main_circuit.cx(1, 2) - main_circuit.rz(2 * gammas[0], 2) - main_circuit.cx(1, 2) main_circuit.cx(0, 2) main_circuit.rz(2 * gammas[0], 2) main_circuit.cx(0, 2) @@ -188,9 +180,6 @@ def test_circuit_angle_assignment_qpu_backend_w_hadamard(self): main_circuit.cx(1, 2) main_circuit.rz(2 * gammas[1], 2) main_circuit.cx(1, 2) - main_circuit.cx(0, 2) - main_circuit.rz(2 * gammas[1], 2) - main_circuit.cx(0, 2) main_circuit.rx(-2 * betas[1], 0) main_circuit.rx(-2 * betas[1], 1) main_circuit.rx(-2 * betas[1], 2) @@ -210,17 +199,17 @@ def test_prepend_circuit(self): nqubits = 3 p = 1 - weights = [1, 1, 1] + weights = [1, 1] gammas = [1 / 8 * np.pi] betas = [1 / 8 * np.pi] - shots = 10000 + shots = 1 # Prepended Circuit prepend_circuit = QuantumCircuit(3) prepend_circuit.x([0, 1, 2]) cost_hamil = Hamiltonian( - [PauliOp("ZZ", (0, 1)), PauliOp("ZZ", (1, 2)), PauliOp("ZZ", (0, 2))], + [PauliOp("ZZ", (0, 1)), PauliOp("ZZ", (1, 2))], weights, 1, ) @@ -229,7 +218,7 @@ def test_prepend_circuit(self): variate_params = QAOAVariationalStandardParams(qaoa_descriptor, betas, gammas) qiskit_device = DeviceQiskit( - "ibmq_qasm_simulator", self.HUB, self.GROUP, self.PROJECT + "ibm_kyoto", self.HUB, self.GROUP, self.PROJECT ) qiskit_backend = QAOAQiskitQPUBackend( @@ -247,9 +236,6 @@ def test_prepend_circuit(self): main_circuit.cx(1, 2) main_circuit.rz(2 * gammas[0], 2) main_circuit.cx(1, 2) - main_circuit.cx(0, 2) - main_circuit.rz(2 * gammas[0], 2) - main_circuit.cx(0, 2) main_circuit.rx(-2 * betas[0], 0) main_circuit.rx(-2 * betas[0], 1) main_circuit.rx(-2 * betas[0], 2) @@ -270,17 +256,17 @@ def test_append_circuit(self): nqubits = 3 p = 1 - weights = [1, 1, 1] + weights = [1, 1] gammas = [1 / 8 * np.pi] betas = [1 / 8 * np.pi] - shots = 10000 + shots = 1 # Appended Circuit append_circuit = QuantumCircuit(3) append_circuit.x([0, 1, 2]) cost_hamil = Hamiltonian( - [PauliOp("ZZ", (0, 1)), PauliOp("ZZ", (1, 2)), PauliOp("ZZ", (0, 2))], + [PauliOp("ZZ", (0, 1)), PauliOp("ZZ", (1, 2))], weights, 1, ) @@ -289,7 +275,7 @@ def test_append_circuit(self): variate_params = QAOAVariationalStandardParams(qaoa_descriptor, betas, gammas) qiskit_device = DeviceQiskit( - "ibmq_qasm_simulator", self.HUB, self.GROUP, self.PROJECT + "ibm_kyoto", self.HUB, self.GROUP, self.PROJECT ) qiskit_backend = QAOAQiskitQPUBackend( @@ -306,9 +292,6 @@ def test_append_circuit(self): main_circuit.cx(1, 2) main_circuit.rz(2 * gammas[0], 2) main_circuit.cx(1, 2) - main_circuit.cx(0, 2) - main_circuit.rz(2 * gammas[0], 2) - main_circuit.cx(0, 2) main_circuit.rx(-2 * betas[0], 0) main_circuit.rx(-2 * betas[0], 1) main_circuit.rx(-2 * betas[0], 2) @@ -390,55 +373,56 @@ def test_expectations_in_init(self): True, ) - @pytest.mark.sim - def test_remote_integration_sim_run(self): - """ - Checks if Remote IBM QASM Simulator is similar/close to Local IBM - Statevector Simulator. - This test also serves as an integration test for the IBMQPU Backend. - - This test takes a long time to complete. - """ - - nqubits = 3 - p = 1 - weights = [1, 1, 1] - gammas = [[0], [1 / 8 * np.pi], [0], [1 / 8 * np.pi]] - betas = [[0], [0], [1 / 8 * np.pi], [1 / 8 * np.pi]] - shots = 10000 - - for i in range(4): - cost_hamil = Hamiltonian( - [PauliOp("ZZ", (0, 1)), PauliOp("ZZ", (1, 2)), PauliOp("ZZ", (0, 2))], - weights, - 1, - ) - mixer_hamil = X_mixer_hamiltonian(n_qubits=nqubits) - qaoa_descriptor = QAOADescriptor(cost_hamil, mixer_hamil, p=p) - variate_params = QAOAVariationalStandardParams( - qaoa_descriptor, betas[i], gammas[i] - ) - - qiskit_device = DeviceQiskit( - "ibmq_qasm_simulator", self.HUB, self.GROUP, self.PROJECT - ) - - qiskit_backend = QAOAQiskitQPUBackend( - qaoa_descriptor, qiskit_device, shots, None, None, False - ) - qiskit_expectation = qiskit_backend.expectation(variate_params) - - qiskit_statevec_backend = QAOAQiskitBackendStatevecSimulator( - qaoa_descriptor, None, None, False - ) - qiskit_statevec_expectation = qiskit_statevec_backend.expectation( - variate_params - ) - - acceptable_delta = 0.05 * qiskit_statevec_expectation - self.assertAlmostEqual( - qiskit_expectation, qiskit_statevec_expectation, delta=acceptable_delta - ) + # Removed after removal of ibm_qasm_simulator backend + # @pytest.mark.sim + # def test_remote_integration_sim_run(self): + # """ + # Checks if Remote IBM QASM Simulator is similar/close to Local IBM + # Statevector Simulator. + # This test also serves as an integration test for the IBMQPU Backend. + + # This test takes a long time to complete. + # """ + + # nqubits = 3 + # p = 1 + # weights = [1, 1] + # gammas = [[0], [1 / 8 * np.pi], [0], [1 / 8 * np.pi]] + # betas = [[0], [0], [1 / 8 * np.pi], [1 / 8 * np.pi]] + # shots = 1 + + # for i in range(4): + # cost_hamil = Hamiltonian( + # [PauliOp("ZZ", (0, 1)), PauliOp("ZZ", (1, 2))], + # weights, + # 1, + # ) + # mixer_hamil = X_mixer_hamiltonian(n_qubits=nqubits) + # qaoa_descriptor = QAOADescriptor(cost_hamil, mixer_hamil, p=p) + # variate_params = QAOAVariationalStandardParams( + # qaoa_descriptor, betas[i], gammas[i] + # ) + + # qiskit_device = DeviceQiskit( + # "ibmq_qasm_simulator", self.HUB, self.GROUP, self.PROJECT + # ) + + # qiskit_backend = QAOAQiskitQPUBackend( + # qaoa_descriptor, qiskit_device, shots, None, None, False + # ) + # qiskit_expectation = qiskit_backend.expectation(variate_params) + + # qiskit_statevec_backend = QAOAQiskitBackendStatevecSimulator( + # qaoa_descriptor, None, None, False + # ) + # qiskit_statevec_expectation = qiskit_statevec_backend.expectation( + # variate_params + # ) + + # acceptable_delta = 0.05 * qiskit_statevec_expectation + # self.assertAlmostEqual( + # qiskit_expectation, qiskit_statevec_expectation, delta=acceptable_delta + # ) @pytest.mark.api def test_remote_qubit_overflow(self): @@ -450,10 +434,10 @@ def test_remote_qubit_overflow(self): shots = 100 - set_of_numbers = np.random.randint(1, 10, 8).tolist() + set_of_numbers = np.random.randint(1, 10, 129).tolist() qubo = NumberPartition(set_of_numbers).qubo - mixer_hamil = X_mixer_hamiltonian(n_qubits=8) + mixer_hamil = X_mixer_hamiltonian(n_qubits=129) qaoa_descriptor = QAOADescriptor(qubo.hamiltonian, mixer_hamil, p=1) # Check the creation of the varitional parms @@ -461,15 +445,16 @@ def test_remote_qubit_overflow(self): qiskit_device = DeviceQiskit("ibm_kyoto", self.HUB, self.GROUP, self.PROJECT) - try: - QAOAQiskitQPUBackend( - qaoa_descriptor, qiskit_device, shots, None, None, True - ) - except Exception as e: - self.assertEqual( - str(e), - "There are lesser qubits on the device than the number of qubits required for the circuit.", - ) + self.assertRaises( + Exception, + QAOAQiskitQPUBackend, + qaoa_descriptor, + qiskit_device, + shots, + None, + None, + True, + ) @pytest.mark.qpu def test_integration_on_emulator(self): @@ -483,7 +468,7 @@ def test_integration_on_emulator(self): weights = [1, 1, 1] gammas = [[1 / 8 * np.pi]] betas = [[1 / 8 * np.pi]] - shots = 10000 + shots = 1 cost_hamil = Hamiltonian( [PauliOp("ZZ", (0, 1)), PauliOp("ZZ", (1, 2)), PauliOp("ZZ", (0, 2))], @@ -520,7 +505,7 @@ def test_remote_integration_qpu_run(self): weights = [1, 1, 1] gammas = [[1 / 8 * np.pi]] betas = [[1 / 8 * np.pi]] - shots = 10000 + shots = 1 cost_hamil = Hamiltonian( [PauliOp("ZZ", (0, 1)), PauliOp("ZZ", (1, 2)), PauliOp("ZZ", (0, 2))],