Repository: qiboteam/qibo
Issue: Multiple tests do not work for `cupy` backend

List:

- `test_derivative.py`
- `test_hamiltonians_terms.py`
- `test_hamiltonians_trotter.py`

Changed files:
tests/test_derivative.py, src/qibo/derivative.py

diff --git a/src/qibo/derivative.py b/src/qibo/derivative.py
index 70bbe180..9db764e3 100644
--- a/src/qibo/derivative.py
+++ b/src/qibo/derivative.py
@@ -13,74 +13,78 @@ def parameter_shift(
     nshots=None,
 ):
     """In this method the parameter shift rule (PSR) is implemented.
-    Given a circuit U and an observable H, the PSR allows to calculate the derivative
-    of the expected value of H on the final state with respect to a variational
-    parameter of the circuit.
-    There is also the possibility of setting a scale factor. It is useful when a
-    circuit's parameter is obtained by combination of a variational
-    parameter and an external object, such as a training variable in a Quantum
-    Machine Learning problem. For example, performing a re-uploading strategy
-    to embed some data into a circuit, we apply to the quantum state rotations
-    whose angles are in the form: theta' = theta * x, where theta is a variational
-    parameter and x an input variable. The PSR allows to calculate the derivative
-    with respect of theta' but, if we want to optimize a system with respect its
-    variational parameters we need to "free" this procedure from the x depencency.
-    If the `scale_factor` is not provided, it is set equal to one and doesn't
-    affect the calculation.
-    If the PSR is needed to be executed on a real quantum device, it is important
-    to set `nshots` to some integer value. This enables the execution on the
-    hardware by calling the proper methods.
-
-    Args:
-        circuit (:class:`qibo.models.circuit.Circuit`): custom quantum circuit.
-        hamiltonian (:class:`qibo.hamiltonians.Hamiltonian`): target observable.
-        if you want to execute on hardware, a symbolic hamiltonian must be provided
-        as follows (example with Pauli Z and `nqubits=1`): `SymbolicHamiltonian(np.prod([ Z(i) for i in range(1) ]))`.
-        parameter_index (int): the index which identifies the target parameter in the `circuit.get_parameters()` list.
-        initial_state ((2**nqubits) vector): initial state on which the circuit acts (default None).
-        scale_factor (float): parameter scale factor (default None).
-        nshots (int): number of shots if derivative is evaluated on hardware. If
-        `None`, the simulation mode is executed (default None).
-
-    Returns:
-        np.float value of the derivative of the expectation value of the hamiltonian
-        with respect to the target variational parameter.
-
-    Example:
-        .. testcode::
-
-            import qibo
-            import numpy as np
-            from qibo import hamiltonians, gates
-            from qibo.models import Circuit
-            from qibo.derivative import parameter_shift
-
-            # defining an observable
-            def hamiltonian(nqubits = 1):
-                m0 = (1/nqubits)*hamiltonians.Z(nqubits).matrix
-                ham = hamiltonians.Hamiltonian(nqubits, m0)
-                return ham
-
-            # defining a dummy circuit
-            def circuit(nqubits = 1):
-                c = Circuit(nqubits = 1)
-                c.add(gates.RY(q = 0, theta = 0))
-                c.add(gates.RX(q = 0, theta = 0))
-                c.add(gates.M(0))
-                return c
-
-            # initializing the circuit
-            c = circuit(nqubits = 1)
-
-            # some parameters
-            test_params = np.random.randn(2)
-            c.set_parameters(test_params)
-
-            test_hamiltonian = hamiltonian()
-
-            # running the psr with respect to the two parameters
-            grad_0 = parameter_shift(circuit = c, hamiltonian = test_hamiltonian, parameter_index = 0)
-            grad_1 = parameter_shift(circuit = c, hamiltonian = test_hamiltonian, parameter_index = 1)
+        Given a circuit U and an observable H, the PSR allows to calculate the derivative
+        of the expected value of H on the final state with respect to a variational
+        parameter of the circuit.
+        There is also the possibility of setting a scale factor. It is useful when a
+        circuit's parameter is obtained by combination of a variational
+        parameter and an external object, such as a training variable in a Quantum
+        Machine Learning problem. For example, performing a re-uploading strategy
+        to embed some data into a circuit, we apply to the quantum state rotations
+        whose angles are in the form: theta' = theta * x, where theta is a variational
+        parameter and x an input variable. The PSR allows to calculate the derivative
+        with respect of theta' but, if we want to optimize a system with respect its
+        variational parameters we need to "free" this procedure from the x depencency.
+        If the `scale_factor` is not provided, it is set equal to one and doesn't
+        affect the calculation.
+        If the PSR is needed to be executed on a real quantum device, it is important
+        to set `nshots` to some integer value. This enables the execution on the
+        hardware by calling the proper methods.
+
+        Args:
+            circuit (:class:`qibo.models.circuit.Circuit`): custom quantum circuit.
+            hamiltonian (:class:`qibo.hamiltonians.Hamiltonian`): target observable.
+                if you want to execute on hardware, a symbolic hamiltonian must be
+                provided as follows (example with Pauli Z and ``nqubits=1``):
+                ``SymbolicHamiltonian(np.prod([ Z(i) for i in range(1) ]))``.
+            parameter_index (int): the index which identifies the target parameter
+                in the ``circuit.get_parameters()`` list.
+            initial_state (ndarray, optional): initial state on which the circuit
+                acts. Default is ``None``.
+            scale_factor (float, optional): parameter scale factor. Default is ``1``.
+            nshots (int, optional): number of shots if derivative is evaluated on
+                hardware. If ``None``, the simulation mode is executed.
+                Default is ``None``.
+    `
+        Returns:
+            (float): Value of the derivative of the expectation value of the hamiltonian
+                with respect to the target variational parameter.
+
+        Example:
+            .. testcode::
+
+                import qibo
+                import numpy as np
+                from qibo import hamiltonians, gates
+                from qibo.models import Circuit
+                from qibo.derivative import parameter_shift
+
+                # defining an observable
+                def hamiltonian(nqubits = 1):
+                    m0 = (1/nqubits)*hamiltonians.Z(nqubits).matrix
+                    ham = hamiltonians.Hamiltonian(nqubits, m0)
+                    return ham
+
+                # defining a dummy circuit
+                def circuit(nqubits = 1):
+                    c = Circuit(nqubits = 1)
+                    c.add(gates.RY(q = 0, theta = 0))
+                    c.add(gates.RX(q = 0, theta = 0))
+                    c.add(gates.M(0))
+                    return c
+
+                # initializing the circuit
+                c = circuit(nqubits = 1)
+
+                # some parameters
+                test_params = np.random.randn(2)
+                c.set_parameters(test_params)
+
+                test_hamiltonian = hamiltonian()
+
+                # running the psr with respect to the two parameters
+                grad_0 = parameter_shift(circuit=c, hamiltonian=test_hamiltonian, parameter_index=0)
+                grad_1 = parameter_shift(circuit=c, hamiltonian=test_hamiltonian, parameter_index=1)
     """
 
     # some raise_error
@@ -146,4 +150,7 @@ def parameter_shift(
 
     circuit.set_parameters(original)
 
-    return generator_eigenval * (forward - backward) * scale_factor
+    # float() necessary to not return a 0-dim ndarray
+    result = float(generator_eigenval * (forward - backward) * scale_factor)
+
+    return result
diff --git a/tests/test_derivative.py b/tests/test_derivative.py
index 7008a9bc..04ef78da 100644
--- a/tests/test_derivative.py
+++ b/tests/test_derivative.py
@@ -8,7 +8,7 @@ from qibo.symbols import Z
 
 
 # defining an observable
-def hamiltonian(nqubits, backend):
+def hamiltonian(nqubits):
     return hamiltonians.hamiltonians.SymbolicHamiltonian(
         np.prod([Z(i) for i in range(nqubits)])
     )
@@ -31,6 +31,8 @@ def circuit(nqubits=1):
     [(1, [-8.51104358e-02, -5.20075970e-01, 0]), (0.5, [-0.02405061, -0.13560379, 0])],
 )
 def test_derivative(backend, nshots, atol, scale_factor, grads):
+    grads = backend.cast(grads, dtype=float)
+
     # initializing the circuit
     c = circuit(nqubits=1)
 
@@ -40,7 +42,7 @@ def test_derivative(backend, nshots, atol, scale_factor, grads):
     test_params *= scale_factor
     c.set_parameters(test_params)
 
-    test_hamiltonian = hamiltonian(nqubits=1, backend=backend)
+    test_hamiltonian = hamiltonian(nqubits=1)
 
     # testing parameter out of bounds
     with pytest.raises(ValueError):