diff --git a/mpitests/test_adjoint_jacobian.py b/mpitests/test_adjoint_jacobian.py index 2c9737bbb5..862ad4c4ef 100644 --- a/mpitests/test_adjoint_jacobian.py +++ b/mpitests/test_adjoint_jacobian.py @@ -26,12 +26,12 @@ from pennylane import QNode from pennylane import numpy as np from pennylane import qnode -from scipy.stats import unitary_group - -from pennylane.tape import QuantumScript from pennylane.devices import DefaultExecutionConfig, DefaultQubit, ExecutionConfig, MCMConfig +from pennylane.tape import QuantumScript +from scipy.stats import unitary_group import pennylane_lightning + if hasattr(pennylane_lightning, "lightning_gpu_ops"): import pennylane_lightning.lightning_gpu_ops as lightning_ops from pennylane_lightning.lightning_gpu_ops import LightningException @@ -120,7 +120,6 @@ def process_and_execute(device, qscript, execute_and_derivatives=False, obs_batc jac = device.compute_derivatives(qscript, config) return transf_fn(results), jac - @pytest.mark.parametrize("batch_obs", [True, False]) def test_not_expval(self, dev, batch_obs): """Test if a QuantumFunctionError is raised for a tape with measurements that are not @@ -133,7 +132,7 @@ def test_not_expval(self, dev, batch_obs): qml.QuantumFunctionError, match="Adjoint differentiation method does not" ): _ = dev.compute_derivatives(qs, config) - + qs = QuantumScript([qml.RX(1.23, 0)], [qml.state()], trainable_params=[0]) with pytest.raises( @@ -143,14 +142,18 @@ def test_not_expval(self, dev, batch_obs): _ = dev.compute_derivatives(qs, config) @pytest.mark.parametrize("batch_obs", [True, False]) - def test_finite_shots_warns(self,dev, batch_obs): + def test_finite_shots_warns(self, dev, batch_obs): """Tests warning raised when finite shots specified""" - qs = QuantumScript([qml.RX(1.23, 0)], [qml.expval(qml.Z(0))], shots=10, trainable_params=[0]) + qs = QuantumScript( + [qml.RX(1.23, 0)], [qml.expval(qml.Z(0))], shots=10, trainable_params=[0] + ) config = ExecutionConfig(gradient_method="adjoint", device_options={"batch_obs": batch_obs}) - with pytest.raises(qml.QuantumFunctionError, - match="Requested adjoint differentiation to be computed with finite shots."): + with pytest.raises( + qml.QuantumFunctionError, + match="Requested adjoint differentiation to be computed with finite shots.", + ): _ = dev.compute_derivatives(qs, config) def test_empty_measurements(self, dev): @@ -163,10 +166,10 @@ def circuit(): qml.RX(0.4, wires=[0]) return qml.expval(qml.PauliZ(0)) - qnode = QNode(circuit, dev, diff_method='adjoint') - + qnode = QNode(circuit, dev, diff_method="adjoint") + jac = qml.grad(qnode)() - + assert len(jac) == 0 @pytest.mark.parametrize("batch_obs", [True, False]) @@ -178,7 +181,7 @@ def test_unsupported_op(self, batch_obs, dev): qs = QuantumScript( [qml.CRot(0.1, 0.2, 0.3, wires=[0, 1])], [qml.expval(qml.PauliZ(0))], - trainable_params=[0] + trainable_params=[0], ) config = ExecutionConfig(gradient_method="adjoint", device_options={"batch_obs": batch_obs}) @@ -186,19 +189,19 @@ def test_unsupported_op(self, batch_obs, dev): LightningException, match="The operation is not supported using the adjoint differentiation method", ): - _ = dev.compute_derivatives(qs, config) + _ = dev.compute_derivatives(qs, config) @pytest.mark.skip("WIP: Need a deep review if LGPU accept Projector") @pytest.mark.parametrize("batch_obs", [True, False]) - def test_proj_unsupported(self,batch_obs, dev): + def test_proj_unsupported(self, batch_obs, dev): """Test if a QuantumFunctionError is raised for a Projector observable""" config = ExecutionConfig(gradient_method="adjoint", device_options={"batch_obs": batch_obs}) - qs = QuantumScript( + qs = QuantumScript( [qml.CRX(0.1, wires=[0, 1])], [qml.expval(qml.Projector([0, 1], wires=[0, 1]))], - trainable_params=[0] + trainable_params=[0], ) with pytest.raises( @@ -207,10 +210,10 @@ def test_proj_unsupported(self,batch_obs, dev): ): _ = dev.compute_derivatives(qs, config) - qs = QuantumScript( + qs = QuantumScript( [qml.CRX(0.1, wires=[0, 1])], [qml.expval(qml.Projector([0], wires=[0]) @ qml.PauliZ(0))], - trainable_params=[0] + trainable_params=[0], ) with pytest.raises( @@ -223,16 +226,16 @@ def test_proj_unsupported(self,batch_obs, dev): @pytest.mark.parametrize("G", [qml.RX, qml.RY, qml.RZ]) @pytest.mark.parametrize("stateprep", [qml.QubitStateVector, qml.StatePrep]) @pytest.mark.parametrize("batch_obs", [True, False]) - def test_pauli_rotation_gradient(self, stateprep, G, theta,batch_obs, dev): + def test_pauli_rotation_gradient(self, stateprep, G, theta, batch_obs, dev): """Tests that the automatic gradients of Pauli rotations are correct.""" random_state = np.array( [0.43593284 - 0.02945156j, 0.40812291 + 0.80158023j], requires_grad=False ) qs = QuantumScript( - [stateprep(random_state, 0), G(theta, 0)], + [stateprep(random_state, 0), G(theta, 0)], [qml.expval(qml.PauliZ(0))], - trainable_params=[1] + trainable_params=[1], ) config = ExecutionConfig(gradient_method="adjoint", device_options={"batch_obs": batch_obs}) @@ -248,7 +251,7 @@ def test_pauli_rotation_gradient(self, stateprep, G, theta,batch_obs, dev): @pytest.mark.parametrize("theta", np.linspace(-2 * np.pi, 2 * np.pi, 7)) @pytest.mark.parametrize("stateprep", [qml.QubitStateVector, qml.StatePrep]) @pytest.mark.parametrize("batch_obs", [True, False]) - def test_Rot_gradient(self, stateprep, theta,batch_obs, dev): + def test_Rot_gradient(self, stateprep, theta, batch_obs, dev): """Tests that the device gradient of an arbitrary Euler-angle-parameterized gate is correct.""" params = np.array([theta, theta**3, np.sqrt(2) * theta]) @@ -256,10 +259,10 @@ def test_Rot_gradient(self, stateprep, theta,batch_obs, dev): qs = QuantumScript( [ stateprep(np.array([1.0, -1.0], requires_grad=False) / np.sqrt(2), wires=0), - qml.Rot(*params, wires=[0]) + qml.Rot(*params, wires=[0]), ], [qml.expval(qml.PauliZ(0))], - trainable_params = [1, 2, 3] + trainable_params=[1, 2, 3], ) config = ExecutionConfig(gradient_method="adjoint", device_options={"batch_obs": batch_obs}) @@ -267,7 +270,7 @@ def test_Rot_gradient(self, stateprep, theta,batch_obs, dev): calculated_val = dev.compute_derivatives(qs, config) tol = 1e-3 if dev.c_dtype == np.complex64 else 1e-7 - + # compare to finite differences tapes, fn = qml.gradients.param_shift(qs) numeric_val = fn(qml.execute(tapes, dev, None)) @@ -277,10 +280,8 @@ def test_Rot_gradient(self, stateprep, theta,batch_obs, dev): @pytest.mark.parametrize("batch_obs", [True, False]) def test_ry_gradient(self, par, tol, batch_obs, dev): """Test that the gradient of the RY gate matches the exact analytic formula.""" - qs = QuantumScript( - [qml.RY(par, wires=[0])], - [qml.expval(qml.PauliX(0))], - trainable_params = [0] + qs = QuantumScript( + [qml.RY(par, wires=[0])], [qml.expval(qml.PauliX(0))], trainable_params=[0] ) config = ExecutionConfig(gradient_method="adjoint", device_options={"batch_obs": batch_obs}) @@ -296,14 +297,9 @@ def test_rx_gradient(self, tol, batch_obs, dev): """Test that the gradient of the RX gate matches the known formula.""" a = 0.7418 - qs = QuantumScript( - [qml.RX(a, wires=0)], - [qml.expval(qml.PauliZ(0))], - trainable_params = [0] - ) - - config = ExecutionConfig(gradient_method="adjoint", device_options={"batch_obs": batch_obs}) + qs = QuantumScript([qml.RX(a, wires=0)], [qml.expval(qml.PauliZ(0))], trainable_params=[0]) + config = ExecutionConfig(gradient_method="adjoint", device_options={"batch_obs": batch_obs}) # circuit jacobians dev_jacobian = dev.compute_derivatives(qs, config) @@ -311,33 +307,28 @@ def test_rx_gradient(self, tol, batch_obs, dev): assert np.allclose(dev_jacobian, expected_jacobian, atol=tol, rtol=0) @staticmethod - def process_and_execute_multiple_rx(dev,params,obs,batch_obs): - qs = QuantumScript( - [ - qml.RX(params[0], wires=0), - qml.RX(params[1], wires=1), - qml.RX(params[2], wires=2) - ], + def process_and_execute_multiple_rx(dev, params, obs, batch_obs): + qs = QuantumScript( + [qml.RX(params[0], wires=0), qml.RX(params[1], wires=1), qml.RX(params[2], wires=2)], obs, - trainable_params = [0,1,2] + trainable_params=[0, 1, 2], ) config = ExecutionConfig(gradient_method="adjoint", device_options={"batch_obs": batch_obs}) # circuit jacobians dev_jacobian = dev.compute_derivatives(qs, config) - + return dev_jacobian - @pytest.mark.parametrize("batch_obs", [True, False]) def test_multiple_rx_gradient_pauliz(self, tol, batch_obs, dev): """Tests that the gradient of multiple RX gates in a circuit yields the correct result.""" params = np.array([np.pi, np.pi / 2, np.pi / 3]) - obs = [qml.expval(qml.PauliZ(idx)) for idx in range(3)] - + obs = [qml.expval(qml.PauliZ(idx)) for idx in range(3)] + # circuit jacobians - dev_jacobian = self.process_and_execute_multiple_rx(dev,params,obs,batch_obs) + dev_jacobian = self.process_and_execute_multiple_rx(dev, params, obs, batch_obs) expected_jacobian = -np.diag(np.sin(params)) assert np.allclose(dev_jacobian, expected_jacobian, atol=tol, rtol=0) @@ -348,11 +339,11 @@ def test_multiple_rx_gradient_hermitian(self, tol, batch_obs, dev): """ params = np.array([np.pi, np.pi / 2, np.pi / 3]) - + obs = [qml.expval(qml.Hermitian([[1, 0], [0, -1]], wires=[idx])) for idx in range(3)] # circuit jacobians - dev_jacobian = self.process_and_execute_multiple_rx(dev,params,obs,batch_obs) + dev_jacobian = self.process_and_execute_multiple_rx(dev, params, obs, batch_obs) expected_jacobian = -np.diag(np.sin(params)) assert np.allclose(dev_jacobian, expected_jacobian, atol=tol, rtol=0) @@ -364,14 +355,16 @@ def test_multiple_rx_gradient_expval_hermitian(self, tol, batch_obs, dev): """ params = np.array([np.pi / 3, np.pi / 4, np.pi / 5]) - obs = [qml.expval( + obs = [ + qml.expval( qml.Hermitian( [[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]], wires=[0, 2], ) - )] + ) + ] - dev_jacobian = self.process_and_execute_multiple_rx(dev,params,obs,batch_obs) + dev_jacobian = self.process_and_execute_multiple_rx(dev, params, obs, batch_obs) expected_jacobian = np.array( [ -np.sin(params[0]) * np.cos(params[2]), @@ -389,20 +382,24 @@ def test_multiple_rx_gradient_expval_hamiltonian(self, tol, batch_obs, dev): """ params = np.array([np.pi / 3, np.pi / 4, np.pi / 5]) - obs= [qml.expval(qml.Hamiltonian( - [1.0, 0.3, 0.3, 0.4], - [ - qml.PauliX(0) @ qml.PauliX(1), - qml.PauliZ(0), - qml.PauliZ(1), - qml.Hermitian( - [[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]], - wires=[0, 2], - ), - ], - ))] + obs = [ + qml.expval( + qml.Hamiltonian( + [1.0, 0.3, 0.3, 0.4], + [ + qml.PauliX(0) @ qml.PauliX(1), + qml.PauliZ(0), + qml.PauliZ(1), + qml.Hermitian( + [[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]], + wires=[0, 2], + ), + ], + ) + ) + ] - dev_jacobian = self.process_and_execute_multiple_rx(dev,params,obs,batch_obs) + dev_jacobian = self.process_and_execute_multiple_rx(dev, params, obs, batch_obs) expected_jacobian = ( 0.3 * np.array([-np.sin(params[0]), 0, 0]) + 0.3 * np.array([0, -np.sin(params[1]), 0]) @@ -418,18 +415,21 @@ def test_multiple_rx_gradient_expval_hamiltonian(self, tol, batch_obs, dev): assert np.allclose(dev_jacobian, expected_jacobian, atol=tol, rtol=0) - @pytest.mark.parametrize("obs", - [ - [qml.expval(qml.PauliX(wires=0)),qml.expval(qml.PauliZ(wires=1))], - [qml.expval(qml.PauliY(wires=0)),qml.expval(qml.PauliZ(wires=1))], - [qml.expval( - qml.Hermitian( - [[0, 0, 1, 1], [0, 1, 2, 1], [1, 2, 1, 0], [1, 1, 0, 0]], - wires=[0, 1], + @pytest.mark.parametrize( + "obs", + [ + [qml.expval(qml.PauliX(wires=0)), qml.expval(qml.PauliZ(wires=1))], + [qml.expval(qml.PauliY(wires=0)), qml.expval(qml.PauliZ(wires=1))], + [ + qml.expval( + qml.Hermitian( + [[0, 0, 1, 1], [0, 1, 2, 1], [1, 2, 1, 0], [1, 1, 0, 0]], + wires=[0, 1], + ) ) - )] - ] - ) + ], + ], + ) @pytest.mark.parametrize( "op", [ @@ -447,22 +447,19 @@ def test_gradients_pauliz_hermitian(self, op, obs, batch_obs, dev): """Tests that the gradients of circuits match between the finite difference and device methods.""" # op.num_wires and op.num_params must be initialized a priori - qs = QuantumScript( + qs = QuantumScript( [ - - qml.Hadamard(wires=0), - qml.RX(0.543, wires=0), - qml.CNOT(wires=[0, 1]), - - op, # pylint: disable=pointless-statement, - - qml.Rot(1.3, -2.3, 0.5, wires=[0]), - qml.RZ(-0.5, wires=0), - qml.adjoint(qml.RY(0.5, wires=1), lazy=False), - qml.CNOT(wires=[0, 1]), + qml.Hadamard(wires=0), + qml.RX(0.543, wires=0), + qml.CNOT(wires=[0, 1]), + op, # pylint: disable=pointless-statement, + qml.Rot(1.3, -2.3, 0.5, wires=[0]), + qml.RZ(-0.5, wires=0), + qml.adjoint(qml.RY(0.5, wires=1), lazy=False), + qml.CNOT(wires=[0, 1]), ], obs, - trainable_params = list(range(1, 1 + op.num_params)) + trainable_params=list(range(1, 1 + op.num_params)), ) config = ExecutionConfig(gradient_method="adjoint", device_options={"batch_obs": batch_obs}) @@ -475,16 +472,21 @@ def test_gradients_pauliz_hermitian(self, op, obs, batch_obs, dev): grad_D = dev.compute_derivatives(qs, config) assert np.allclose(grad_D, grad_F, atol=tol, rtol=0) - @pytest.mark.parametrize("obs",[ - [qml.expval(qml.PauliZ(0))], - [qml.expval(qml.Hermitian([[0, 1], [1, 1]], wires=0))], - [qml.expval( - qml.Hamiltonian( - [1.0, 0.3, 0.3], - [qml.PauliX(0) @ qml.PauliX(1), qml.PauliZ(0), qml.PauliZ(1)], - ) - )] - ]) + @pytest.mark.parametrize( + "obs", + [ + [qml.expval(qml.PauliZ(0))], + [qml.expval(qml.Hermitian([[0, 1], [1, 1]], wires=0))], + [ + qml.expval( + qml.Hamiltonian( + [1.0, 0.3, 0.3], + [qml.PauliX(0) @ qml.PauliX(1), qml.PauliZ(0), qml.PauliZ(1)], + ) + ) + ], + ], + ) @pytest.mark.parametrize("batch_obs", [True, False]) def test_gradient_gate_with_multiple_parameters(self, obs, batch_obs, dev): """Tests that gates with multiple free parameters yield correct gradients.""" @@ -497,7 +499,7 @@ def test_gradient_gate_with_multiple_parameters(self, obs, batch_obs, dev): qml.RY(-0.2, wires=[0]), ], obs, - trainable_params = [1, 2, 3] + trainable_params=[1, 2, 3], ) config = ExecutionConfig(gradient_method="adjoint", device_options={"batch_obs": batch_obs}) @@ -519,7 +521,6 @@ def test_gradient_gate_with_multiple_parameters(self, obs, batch_obs, dev): class TestAdjointJacobianQNode: """Test QNode integration with the adjoint_jacobian method""" - def test_finite_shots_error(self): """Tests that an error is raised when computing the adjoint diff on a device with finite shots""" @@ -562,7 +563,7 @@ def circuit(x, y, z): spy.assert_called() - h = 1e-3 if dev.c_dtype == np.complex64 else 1e-7 + h = 1e-3 if dev.c_dtype == np.complex64 else 1e-7 tol = 1e-3 if dev.c_dtype == np.complex64 else 1e-7 qnode2 = QNode(circuit, dev, diff_method="finite-diff", h=h) @@ -638,7 +639,7 @@ def circuit(params): spy_analytic = mocker.spy(dev, "LightningAdjointJacobian") - h = 1e-3 if dev.c_dtype == np.complex64 else 1e-7 + h = 1e-3 if dev.c_dtype == np.complex64 else 1e-7 tol = 1e-3 if dev.c_dtype == np.complex64 else 1e-7 cost = QNode(circuit, dev, diff_method="finite-diff", h=h) diff --git a/mpitests/test_apply.py b/mpitests/test_apply.py index 3b44514b6d..0b0abf51a0 100644 --- a/mpitests/test_apply.py +++ b/mpitests/test_apply.py @@ -380,6 +380,7 @@ def circuit(): local_state_vector = gpumpi_qnode() assert np.allclose(local_state_vector, local_expected_output_cpu, atol=tol, rtol=0) + class TestSparseHamExpval: # pylint: disable=too-few-public-methods,missing-function-docstring """Tests sparse hamiltonian expectation values.""" diff --git a/mpitests/test_expval.py b/mpitests/test_expval.py index 6aebd505c8..180d5a5965 100644 --- a/mpitests/test_expval.py +++ b/mpitests/test_expval.py @@ -24,6 +24,7 @@ numQubits = 8 + def create_random_init_state(numWires, C_DTYPE, seed_value=48): """Returns a random initial state of a certain type.""" np.random.seed(seed_value) @@ -108,10 +109,10 @@ def circuit(): assert np.allclose(local_state_vector, local_expected_output_cpu, atol=tol, rtol=0) + class TestExpval: """Tests that expectation values are properly calculated or that the proper errors are raised.""" - @pytest.mark.parametrize("C_DTYPE", [np.complex128, np.complex64]) @pytest.mark.parametrize( "operation", @@ -389,13 +390,15 @@ def circuit(x, y): class TestTensorExpval: """Test tensor expectation values""" - - @pytest.mark.parametrize("obs,expected",[ - (qml.PauliX(0) @ qml.PauliY(2), "PXPY"), - (qml.PauliZ(0) @ qml.Identity(1) @ qml.PauliZ(2), "PZIPZ"), - (qml.PauliZ(0) @ qml.Hadamard(1) @ qml.PauliY(2), "PZHPY") - ]) - def test_tensor(self, theta, phi, varphi,obs,expected, tol): + @pytest.mark.parametrize( + "obs,expected", + [ + (qml.PauliX(0) @ qml.PauliY(2), "PXPY"), + (qml.PauliZ(0) @ qml.Identity(1) @ qml.PauliZ(2), "PZIPZ"), + (qml.PauliZ(0) @ qml.Hadamard(1) @ qml.PauliY(2), "PZHPY"), + ], + ) + def test_tensor(self, theta, phi, varphi, obs, expected, tol): """Test that a tensor product involving PauliX and PauliY works correctly""" dev = qml.device(device_name, mpi=True, wires=3) @@ -416,6 +419,8 @@ def circuit(): elif expected == "PZIPZ": expected_val = np.cos(varphi) * np.cos(phi) elif expected == "PZHPY": - expected_val = -(np.cos(varphi) * np.sin(phi) + np.sin(varphi) * np.cos(theta)) / np.sqrt(2) - + expected_val = -( + np.cos(varphi) * np.sin(phi) + np.sin(varphi) * np.cos(theta) + ) / np.sqrt(2) + assert np.allclose(res, expected_val, atol=tol) diff --git a/mpitests/test_measurements_sparse.py b/mpitests/test_measurements_sparse.py index 114f0e013e..7ca88867eb 100644 --- a/mpitests/test_measurements_sparse.py +++ b/mpitests/test_measurements_sparse.py @@ -27,6 +27,7 @@ if not ld._CPP_BINARY_AVAILABLE: pytest.skip("No binary module found. Skipping.", allow_module_level=True) + class TestSparseExpval: """Tests for the expval function""" diff --git a/pennylane_lightning/lightning_gpu/_adjoint_jacobian.py b/pennylane_lightning/lightning_gpu/_adjoint_jacobian.py index 3d4cbcb7f4..719647b52c 100644 --- a/pennylane_lightning/lightning_gpu/_adjoint_jacobian.py +++ b/pennylane_lightning/lightning_gpu/_adjoint_jacobian.py @@ -18,11 +18,8 @@ from warnings import warn try: - - from pennylane_lightning.lightning_gpu_ops import ( - DevPool, - ) + from pennylane_lightning.lightning_gpu_ops import DevPool from pennylane_lightning.lightning_gpu_ops.algorithms import ( AdjointJacobianC64, AdjointJacobianC128, @@ -48,18 +45,14 @@ pass import numpy as np -from pennylane.tape import QuantumTape -from scipy.sparse import csr_matrix - from pennylane import BasisState, QuantumFunctionError, StatePrep from pennylane.operation import Operation - -from pennylane_lightning.core._serialize import QuantumScriptSerializer - - +from pennylane.tape import QuantumTape +from scipy.sparse import csr_matrix # pylint: disable=ungrouped-imports from pennylane_lightning.core._adjoint_jacobian_base import LightningBaseAdjointJacobian +from pennylane_lightning.core._serialize import QuantumScriptSerializer from ._state_vector import LightningGPUStateVector @@ -74,24 +67,23 @@ class LightningGPUAdjointJacobian(LightningBaseAdjointJacobian): # pylint: disable=too-few-public-methods - def __init__(self, - qubit_state: LightningGPUStateVector, - batch_obs: bool = False, - use_mpi: bool = False, - mpi_handler=None, - ) -> None: - + def __init__( + self, + qubit_state: LightningGPUStateVector, + batch_obs: bool = False, + use_mpi: bool = False, + mpi_handler=None, + ) -> None: + super().__init__(qubit_state, batch_obs) - + self._dp = DevPool() - - + self._use_mpi = use_mpi if use_mpi: self._mpi_handler = mpi_handler - # Initialize the C++ binds self._jacobian_lightning, self._create_ops_list_lightning = self._adjoint_jacobian_dtype() @@ -108,7 +100,7 @@ def _adjoint_jacobian_dtype(self): create_ops_listMPIC64 if self.dtype == np.complex64 else create_ops_listMPIC128 ) return jacobian_lightning, create_ops_list_lightning - else: # without MPI + else: # without MPI jacobian_lightning = ( AdjointJacobianC64() if self.dtype == np.complex64 else AdjointJacobianC128() ) @@ -117,7 +109,7 @@ def _adjoint_jacobian_dtype(self): ) return jacobian_lightning, create_ops_list_lightning - def _process_jacobian_tape(self, tape: QuantumTape, split_obs: bool = False, use_mpi = False): + def _process_jacobian_tape(self, tape: QuantumTape, split_obs: bool = False, use_mpi=False): """Process a tape, serializing and building a dictionary proper for the adjoint Jacobian calculation in the C++ layer. @@ -176,8 +168,6 @@ def _process_jacobian_tape(self, tape: QuantumTape, split_obs: bool = False, use "obs_indices": obs_indices, } - - def calculate_jacobian(self, tape: QuantumTape): """Computes the Jacobian with the adjoint method. diff --git a/pennylane_lightning/lightning_gpu/_measurements.py b/pennylane_lightning/lightning_gpu/_measurements.py index 8650574d92..90f4ceb287 100644 --- a/pennylane_lightning/lightning_gpu/_measurements.py +++ b/pennylane_lightning/lightning_gpu/_measurements.py @@ -39,12 +39,11 @@ import numpy as np import pennylane as qml from pennylane.measurements import CountsMP, MeasurementProcess, SampleMeasurement, Shots -from pennylane.typing import TensorLike from pennylane.tape import QuantumScript - -from pennylane_lightning.core._serialize import QuantumScriptSerializer +from pennylane.typing import TensorLike from pennylane_lightning.core._measurements_base import LightningBaseMeasurements +from pennylane_lightning.core._serialize import QuantumScriptSerializer from ._mpi_handler import MPIHandler @@ -75,7 +74,6 @@ def __init__( if use_mpi: self._mpi_handler = mpi_handler self._num_local_wires = mpi_handler.num_local_wires - self._measurement_lightning = self._measurement_dtype()(lgpu_state.state_vector) @@ -167,7 +165,7 @@ def expval(self, measurementprocess: MeasurementProcess): # CSR_SparseHamiltonian.indices, # CSR_SparseHamiltonian.data, # ) - + if self._use_mpi: # Identity for CSR_SparseHamiltonian to pass to processes with rank != 0 to reduce # host(cpu) memory requirements @@ -221,7 +219,6 @@ def expval(self, measurementprocess: MeasurementProcess): measurementprocess.obs.name, measurementprocess.obs.wires ) - def _probs_retval_conversion(self, probs_results: Any) -> np.ndarray: """Convert the data structure from the C++ backend to a common structure through lightning devices. diff --git a/pennylane_lightning/lightning_gpu/lightning_gpu.py b/pennylane_lightning/lightning_gpu/lightning_gpu.py index 0ad81258b5..611dc83735 100644 --- a/pennylane_lightning/lightning_gpu/lightning_gpu.py +++ b/pennylane_lightning/lightning_gpu/lightning_gpu.py @@ -21,12 +21,11 @@ from dataclasses import replace from functools import reduce from importlib import util as imp_util +from numbers import Number from pathlib import Path from typing import Callable, Optional, Tuple, Union from warnings import warn -from numbers import Number - import numpy as np import pennylane as qml from pennylane.devices import DefaultExecutionConfig, ExecutionConfig @@ -524,10 +523,9 @@ def simulate( state.reset_state(sync=False) final_state = state.get_final_state(circuit) - return LightningGPUMeasurements(final_state, self._mpi_handler.use_mpi,self._mpi_handler).measure_final_state( - circuit - ) - + return LightningGPUMeasurements( + final_state, self._mpi_handler.use_mpi, self._mpi_handler + ).measure_final_state(circuit) def jacobian( self, @@ -552,9 +550,9 @@ def jacobian( [circuit], _ = qml.map_wires(circuit, wire_map) state.reset_state(self._sync) final_state = state.get_final_state(circuit) - return self.LightningAdjointJacobian(final_state, batch_obs, self._mpi_handler.use_mpi,self._mpi_handler).calculate_jacobian( - circuit - ) + return self.LightningAdjointJacobian( + final_state, batch_obs, self._mpi_handler.use_mpi, self._mpi_handler + ).calculate_jacobian(circuit) def simulate_and_jacobian( self, @@ -580,7 +578,9 @@ def simulate_and_jacobian( if wire_map is not None: [circuit], _ = qml.map_wires(circuit, wire_map) res = self.simulate(circuit, state) - jac = self.LightningAdjointJacobian(state, batch_obs, self._mpi_handler.use_mpi,self._mpi_handler).calculate_jacobian(circuit) + jac = self.LightningAdjointJacobian( + state, batch_obs, self._mpi_handler.use_mpi, self._mpi_handler + ).calculate_jacobian(circuit) return res, jac def vjp( # pylint: disable=too-many-arguments @@ -610,9 +610,9 @@ def vjp( # pylint: disable=too-many-arguments [circuit], _ = qml.map_wires(circuit, wire_map) state.reset_state(self._sync) final_state = state.get_final_state(circuit) - return self.LightningAdjointJacobian(final_state, batch_obs,self._mpi_handler.use_mpi,self._mpi_handler).calculate_vjp( - circuit, cotangents - ) + return self.LightningAdjointJacobian( + final_state, batch_obs, self._mpi_handler.use_mpi, self._mpi_handler + ).calculate_vjp(circuit, cotangents) def simulate_and_vjp( # pylint: disable=too-many-arguments self, @@ -641,8 +641,7 @@ def simulate_and_vjp( # pylint: disable=too-many-arguments if wire_map is not None: [circuit], _ = qml.map_wires(circuit, wire_map) res = self.simulate(circuit, state) - _vjp = self.LightningAdjointJacobian(state, batch_obs,self._mpi_handler.use_mpi,self._mpi_handler).calculate_vjp( - circuit, cotangents - ) + _vjp = self.LightningAdjointJacobian( + state, batch_obs, self._mpi_handler.use_mpi, self._mpi_handler + ).calculate_vjp(circuit, cotangents) return res, _vjp -