diff --git a/tests/math/test_entropies_math.py b/tests/math/test_entropies_math.py index 8a1f6114f2f..080fddd0a67 100644 --- a/tests/math/test_entropies_math.py +++ b/tests/math/test_entropies_math.py @@ -491,6 +491,7 @@ def test_max_entropy_grad_tf(self, params, wires, base, check_state): def test_max_entropy_grad_jax(self, params, wires, base, check_state, jit): """Test `max_entropy` differentiability with jax.""" jnp = jax.numpy + jax.config.update("jax_enable_x64", True) params = jnp.array(params) diff --git a/tests/ops/functions/test_eigvals.py b/tests/ops/functions/test_eigvals.py index da4c955eae0..f17cc8a5a31 100644 --- a/tests/ops/functions/test_eigvals.py +++ b/tests/ops/functions/test_eigvals.py @@ -14,17 +14,15 @@ """ Unit tests for the eigvals transform """ +# pylint: disable=too-few-public-methods from functools import reduce import pytest import scipy +from gate_data import CNOT, H, I, S, X, Y, Z import pennylane as qml -from gate_data import CNOT, H, I -from gate_data import Roty as RY -from gate_data import S, X, Y, Z from pennylane import numpy as np -from pennylane.transforms.op_transforms import OperationTransformError one_qubit_no_parameter = [ qml.PauliX, @@ -100,7 +98,9 @@ def test_adjoint(self, op_class): rounding_precision = 6 res = qml.eigvals(qml.adjoint(op_class))(0.54, wires=0) expected = op_class(-0.54, wires=0).eigvals() - assert set(np.around(res, rounding_precision)) == set(np.around(res, rounding_precision)) + assert set(np.around(res, rounding_precision)) == set( + np.around(expected, rounding_precision) + ) def test_ctrl(self): """Test that the ctrl is correctly taken into account""" @@ -116,10 +116,10 @@ def test_tensor_product(self): def test_hamiltonian(self): """Test that the matrix of a Hamiltonian is correctly returned""" - H = qml.PauliZ(0) @ qml.PauliY(1) - 0.5 * qml.PauliX(1) + ham = qml.PauliZ(0) @ qml.PauliY(1) - 0.5 * qml.PauliX(1) with pytest.warns(UserWarning, match="the eigenvalues will be computed numerically"): - res = qml.eigvals(H) + res = qml.eigvals(ham) expected = np.linalg.eigvalsh(reduce(np.kron, [Z, Y]) - 0.5 * reduce(np.kron, [I, X])) assert np.allclose(res, expected) @@ -142,7 +142,7 @@ def ansatz(x): assert np.allclose(res, expected) @pytest.mark.parametrize( - ("row", "col", "dat", "val_ref"), + ("row", "col", "dat"), [ ( # coordinates and values of a sparse Hamiltonian computed for H2 @@ -173,35 +173,10 @@ def ansatz(x): 0.93441394 + 0.0j, ] ), - # eigenvalues of the same matrix computed with np.linalg.eigh(H_dense) - np.array( - [ - -1.13730605, - -0.5363422, - -0.5363422, - -0.52452264, - -0.52452264, - -0.52452264, - -0.44058792, - -0.44058792, - -0.16266858, - 0.0, - 0.0, - 0.0, - 0.0, - 0.2481941, - 0.2481941, - 0.36681148, - 0.36681148, - 0.49523726, - 0.72004228, - 0.93441394, - ] - ), ), ], ) - def test_sparse_hamiltonian(self, row, col, dat, val_ref): + def test_sparse_hamiltonian(self, row, col, dat): """Test that the eigenvalues of a sparse Hamiltonian are correctly returned""" # N x N matrix with N = 16 h_mat = scipy.sparse.csr_matrix((dat, (row, col)), shape=(16, 16)) diff --git a/tests/ops/functions/test_equal.py b/tests/ops/functions/test_equal.py index aca29cbc1b9..42aa05b6e48 100644 --- a/tests/ops/functions/test_equal.py +++ b/tests/ops/functions/test_equal.py @@ -584,6 +584,7 @@ def test_equal_simple_op_3p1w(self, op1): @pytest.mark.all_interfaces def test_equal_op_remaining(self): """Test optional arguments are working""" + # pylint: disable=too-many-statements wire = 0 import jax @@ -1055,7 +1056,7 @@ def jax_assertion_func(x, other_tensor): operation1 = op1(jax.numpy.array(x), wires=1) operation2 = op1(other_tensor, wires=1) if isinstance(other_tensor, tf.Variable): - with tf.GradientTape() as tape: + with tf.GradientTape(): assert qml.equal( operation1, operation2, check_interface=False, check_trainability=True ) @@ -1071,7 +1072,7 @@ def jax_assertion_func(x, other_tensor): # TF and Autograd # ------------------ - with tf.GradientTape() as tape: + with tf.GradientTape(): assert qml.equal( op1(tf_tensor, wires=wire), op1(pl_tensor, wires=wire), @@ -1081,7 +1082,7 @@ def jax_assertion_func(x, other_tensor): # TF and Torch # ------------------ - with tf.GradientTape() as tape: + with tf.GradientTape(): assert qml.equal( op1(tf_tensor, wires=wire), op1(torch_tensor, wires=wire), @@ -1247,15 +1248,15 @@ def test_hamiltonian_and_operation_not_equal(self): """Tests that comparing a Hamiltonian with an Operator that is not an Observable returns False""" op1 = qml.Hamiltonian([1, 1], [qml.PauliX(0), qml.PauliY(0)]) op2 = qml.RX(1.2, 0) - assert qml.equal(op1, op2) == False - assert qml.equal(op2, op1) == False + assert qml.equal(op1, op2) is False + assert qml.equal(op2, op1) is False def test_tensor_and_operation_not_equal(self): """Tests that comparing a Tensor with an Operator that is not an Observable returns False""" op1 = qml.PauliX(0) @ qml.PauliY(1) op2 = qml.RX(1.2, 0) - assert qml.equal(op1, op2) == False - assert qml.equal(op2, op1) == False + assert qml.equal(op1, op2) is False + assert qml.equal(op2, op1) is False def test_tensor_and_unsupported_observable_not_implemented(self): """Tests that trying to compare a Tensor to something other than another Tensor or a Hamiltonian raises a NotImplmenetedError""" @@ -1298,7 +1299,7 @@ def test_mismatched_arithmetic_depth(self): assert op1.arithmetic_depth == 1 assert op2.arithmetic_depth == 2 - assert qml.equal(op1, op2) == False + assert qml.equal(op1, op2) is False def test_comparison_of_base_not_implemented_error(self): """Test that comparing SymbolicOps of base operators whose comparison is not yet implemented raises an error""" @@ -1379,26 +1380,32 @@ def test_adjoint_comparison(self, base): assert qml.equal(op1, op2) assert not qml.equal(op1, op3) - @pytest.mark.parametrize(("base1", "base2", "bases_match"), BASES) - @pytest.mark.parametrize(("param1", "param2", "params_match"), PARAMS) - def test_pow_comparison(self, base1, base2, bases_match, param1, param2, params_match): + @pytest.mark.parametrize("bases_bases_match", BASES) + @pytest.mark.parametrize("params_params_match", PARAMS) + def test_pow_comparison(self, bases_bases_match, params_params_match): """Test that equal compares two objects of the Pow class""" + base1, base2, bases_match = bases_bases_match + param1, param2, params_match = params_params_match op1 = qml.pow(base1, param1) op2 = qml.pow(base2, param2) assert qml.equal(op1, op2) == (bases_match and params_match) - @pytest.mark.parametrize(("base1", "base2", "bases_match"), BASES) - @pytest.mark.parametrize(("param1", "param2", "params_match"), PARAMS) - def test_exp_comparison(self, base1, base2, bases_match, param1, param2, params_match): + @pytest.mark.parametrize("bases_bases_match", BASES) + @pytest.mark.parametrize("params_params_match", PARAMS) + def test_exp_comparison(self, bases_bases_match, params_params_match): """Test that equal compares two objects of the Exp class""" + base1, base2, bases_match = bases_bases_match + param1, param2, params_match = params_params_match op1 = qml.exp(base1, param1) op2 = qml.exp(base2, param2) assert qml.equal(op1, op2) == (bases_match and params_match) - @pytest.mark.parametrize(("base1", "base2", "bases_match"), BASES) - @pytest.mark.parametrize(("param1", "param2", "params_match"), PARAMS) - def test_s_prod_comparison(self, base1, base2, bases_match, param1, param2, params_match): + @pytest.mark.parametrize("bases_bases_match", BASES) + @pytest.mark.parametrize("params_params_match", PARAMS) + def test_s_prod_comparison(self, bases_bases_match, params_params_match): """Test that equal compares two objects of the SProd class""" + base1, base2, bases_match = bases_bases_match + param1, param2, params_match = params_params_match op1 = qml.s_prod(param1, base1) op2 = qml.s_prod(param2, base2) assert qml.equal(op1, op2) == (bases_match and params_match) diff --git a/tests/ops/functions/test_generator.py b/tests/ops/functions/test_generator.py index 1eecc348809..0f4813160c9 100644 --- a/tests/ops/functions/test_generator.py +++ b/tests/ops/functions/test_generator.py @@ -14,6 +14,7 @@ """ Unit tests for the qml.generator transform """ +# pylint: disable=too-few-public-methods from functools import reduce from operator import matmul @@ -22,7 +23,7 @@ import pennylane as qml from pennylane import numpy as np -from pennylane.ops import Hamiltonian, Prod, SProd, Sum +from pennylane.ops import Prod, SProd, Sum ################################################################### # Test operations @@ -438,7 +439,7 @@ def test_tensor_observable(self): gen = qml.generator(TensorOp, format="arithmetic")(0.5, wires=[0, 1]) result = qml.s_prod(0.5, qml.PauliX(0) @ qml.PauliY(1)) - assert not isinstance(gen, Hamiltonian) + assert not isinstance(gen, qml.Hamiltonian) assert np.allclose( qml.matrix(gen, wire_order=[0, 1]), qml.matrix(result, wire_order=[0, 1]), @@ -451,7 +452,7 @@ def test_hamiltonian(self): qml.PauliX(0) @ qml.Identity(1), qml.s_prod(0.5, qml.PauliX(0) @ qml.PauliY(1)), ) - assert not isinstance(gen, Hamiltonian) + assert not isinstance(gen, qml.Hamiltonian) assert np.allclose( qml.matrix(gen, wire_order=[0, 1]), qml.matrix(result, wire_order=[0, 1]), @@ -463,7 +464,7 @@ def test_hermitian(self): gen = qml.generator(HermitianOp, format="arithmetic")(0.5, wires=0) expected = qml.pauli_decompose(HermitianOp.H, hide_identity=True, pauli=True).operation() - assert not isinstance(gen, Hamiltonian) + assert not isinstance(gen, qml.Hamiltonian) assert np.allclose( qml.matrix(gen), qml.matrix(expected), @@ -477,7 +478,7 @@ def test_sparse_hamiltonian(self): SparseOp.H.toarray(), hide_identity=True, pauli=True ).operation() - assert not isinstance(gen, Hamiltonian) + assert not isinstance(gen, qml.Hamiltonian) assert np.allclose( qml.matrix(gen), qml.matrix(expected), diff --git a/tests/ops/functions/test_is_commuting.py b/tests/ops/functions/test_is_commuting.py index 910832e0c11..236ab6a495f 100644 --- a/tests/ops/functions/test_is_commuting.py +++ b/tests/ops/functions/test_is_commuting.py @@ -14,6 +14,7 @@ """ Unittests for is_commuting """ +# pylint: disable=too-many-public-methods import pytest import pennylane.numpy as np import pennylane as qml @@ -847,4 +848,4 @@ def test_non_commuting(self): """Test the function with an operator from the non-commuting list.""" res = qml.is_commuting(qml.PauliX(wires=0), qml.QFT(wires=[1, 0])) - assert res == False + assert res is False diff --git a/tests/ops/functions/test_map_wires.py b/tests/ops/functions/test_map_wires.py index b6a795874fc..33b6643ac78 100644 --- a/tests/ops/functions/test_map_wires.py +++ b/tests/ops/functions/test_map_wires.py @@ -14,12 +14,13 @@ """ Unit tests for the qml.map_wires function """ +# pylint: disable=too-few-public-methods from functools import partial import pytest import pennylane as qml -from pennylane.ops import Prod, Sum +from pennylane.ops import Prod from pennylane.tape import QuantumScript from pennylane.wires import Wires @@ -210,7 +211,7 @@ def test_jitting_simplified_qfunc(self): @qml.qnode(qml.device("default.qubit", wires=5)) def circuit(x): qml.adjoint(qml.RX(x, wires=0)) - qml.PauliX(0) ** 2 + _ = qml.PauliX(0) ** 2 return qml.expval(qml.PauliY(0)) x = jax.numpy.array(4 * jax.numpy.pi + 0.1) diff --git a/tests/ops/functions/test_matrix.py b/tests/ops/functions/test_matrix.py index bba6e35014b..1883e8c58e3 100644 --- a/tests/ops/functions/test_matrix.py +++ b/tests/ops/functions/test_matrix.py @@ -14,16 +14,17 @@ """ Unit tests for the get_unitary_matrix transform """ +# pylint: disable=too-few-public-methods from functools import reduce import pytest +from gate_data import I, X, Y, Z, H, S, CNOT, Rotx as RX, Roty as RY + import pennylane as qml from pennylane import numpy as np from pennylane.transforms.op_transforms import OperationTransformError -from gate_data import I, X, Y, Z, H, S, CNOT, Rotx as RX, Roty as RY - one_qubit_no_parameter = [ qml.PauliX, qml.PauliY, @@ -132,9 +133,10 @@ def test_CNOT_permutations(self, target_wire): def test_hamiltonian(self): """Test that the matrix of a Hamiltonian is correctly returned""" - H = qml.PauliZ(0) @ qml.PauliY(1) - 0.5 * qml.PauliX(1) - mat = qml.matrix(H, wire_order=[1, 0, 2]) + ham = qml.PauliZ(0) @ qml.PauliY(1) - 0.5 * qml.PauliX(1) + mat = qml.matrix(ham, wire_order=[1, 0, 2]) expected = reduce(np.kron, [Y, Z, I]) - 0.5 * np.kron(X, np.eye(4)) + assert qml.math.allclose(mat, expected) @pytest.mark.xfail( reason="This test will fail because Hamiltonians are not queued to tapes yet!" @@ -148,6 +150,7 @@ def ansatz(x): x = 0.5 mat = qml.matrix(ansatz, wire_order=[1, 0, 2])(x) expected = reduce(np.kron, [Y, Z, I]) - x * np.kron(X, np.eye(4)) + assert qml.math.allclose(mat, expected) def test_qutrits(self): """Test that the function works with qutrits""" @@ -194,7 +197,7 @@ def test_multiple_operations_tape(self): assert np.allclose(matrix, expected_matrix) qs = qml.tape.QuantumScript(tape.operations) - qs_matrix = qml.matrix(tape, wire_order) + qs_matrix = qml.matrix(qs, wire_order) assert np.allclose(qs_matrix, expected_matrix) @@ -324,8 +327,8 @@ def test_multiple_operations_tape_bcasting_matches_Hilbert_dim(self): class TestCustomWireOrdering: def test_tensor_wire_oder(self): """Test wire order of a tensor product""" - H = qml.PauliZ(0) @ qml.PauliX(1) - res = qml.matrix(H, wire_order=[0, 2, 1]) + ham = qml.PauliZ(0) @ qml.PauliX(1) + res = qml.matrix(ham, wire_order=[0, 2, 1]) expected = np.kron(Z, np.kron(I, X)) assert np.allclose(res, expected) @@ -368,7 +371,7 @@ def test_qnode_wireorder(self): @qml.matrix() @qml.qnode(dev) - def testcircuit(x): + def testcircuit1(x): qml.PauliX(wires=0) qml.RY(x, wires=1) qml.PauliZ(wires=2) @@ -378,18 +381,18 @@ def testcircuit(x): # default wire ordering will come from the device expected_matrix = np.kron(RY(x), np.kron(X, np.kron(Z, I))) - assert np.allclose(testcircuit(x), expected_matrix) + assert np.allclose(testcircuit1(x), expected_matrix) @qml.matrix(wire_order=[1, 0, 2]) @qml.qnode(dev) - def testcircuit(x): + def testcircuit2(x): qml.PauliX(wires=0) qml.RY(x, wires=1) qml.PauliZ(wires=2) return qml.expval(qml.PauliZ(0)) expected_matrix = np.kron(RY(x), np.kron(X, Z)) - assert np.allclose(testcircuit(x), expected_matrix) + assert np.allclose(testcircuit2(x), expected_matrix) class TestTemplates: @@ -514,7 +517,7 @@ def circuit(): OperationTransformError, match=r"Wires in circuit \[1, 0\] are inconsistent with those in wire_order \[0, 'b'\]", ): - matrix = qml.matrix(circuit, wire_order=wires)() + qml.matrix(circuit, wire_order=wires)() class TestInterfaces: @@ -606,7 +609,6 @@ def test_get_unitary_matrix_interface_jax(self): from jax import numpy as jnp from jax.config import config - remember = config.read("jax_enable_x64") config.update("jax_enable_x64", True) @qml.matrix diff --git a/tests/ops/functions/test_simplify.py b/tests/ops/functions/test_simplify.py index ae164c0fda5..5d97f1fbfd4 100644 --- a/tests/ops/functions/test_simplify.py +++ b/tests/ops/functions/test_simplify.py @@ -14,6 +14,7 @@ """ Unit tests for the qml.simplify function """ +# pylint: disable=too-few-public-methods import pytest import pennylane as qml @@ -176,7 +177,7 @@ def test_jitting_simplified_qfunc(self): @qml.simplify def circuit(x): qml.adjoint(qml.RX(x, wires=0)) - qml.PauliX(0) ** 2 + _ = qml.PauliX(0) ** 2 return qml.expval(qml.PauliY(0)) x = jax.numpy.array(4 * jax.numpy.pi + 0.1) diff --git a/tests/ops/qubit/test_all_qubit_ops.py b/tests/ops/qubit/test_all_qubit_ops.py index e77b5e626d5..0322307e99e 100644 --- a/tests/ops/qubit/test_all_qubit_ops.py +++ b/tests/ops/qubit/test_all_qubit_ops.py @@ -12,13 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. """ -Unit tests for the available built-in discrete-variable quantum operations. Only tests over multiple -types of operations should exist in this file. Type-specific tests should go in the more specific file. +Unit tests for the available built-in discrete-variable quantum operations. Only tests over +multiple types of operations should exist in this file. Type-specific tests should go in +the more specific file. """ +# pylint: disable=too-few-public-methods import pytest -import pennylane as qml - from gate_data import I +import pennylane as qml class TestOperations: diff --git a/tests/ops/qubit/test_arithmetic_ops.py b/tests/ops/qubit/test_arithmetic_ops.py index 9377573a820..90aa57c569b 100644 --- a/tests/ops/qubit/test_arithmetic_ops.py +++ b/tests/ops/qubit/test_arithmetic_ops.py @@ -14,6 +14,7 @@ """ Unit tests for the the arithmetic qubit operations """ +# pylint: disable=too-many-arguments import copy import itertools @@ -85,8 +86,8 @@ def test_output(self, wires, input_string, output_string, expand, mocker): spy = mocker.spy(qml.QubitCarry, "decomposition") with qml.queuing.AnnotatedQueue() as q: - for i in range(len(input_string)): - if input_string[i] == "1": + for i, letter in enumerate(input_string): + if letter == "1": qml.PauliX(i) qml.QubitCarry(wires=wires) qml.probs(wires=[0, 1, 2, 3]) diff --git a/tests/ops/qubit/test_attributes.py b/tests/ops/qubit/test_attributes.py index 3c71f8abdb7..ef1ec52ea82 100644 --- a/tests/ops/qubit/test_attributes.py +++ b/tests/ops/qubit/test_attributes.py @@ -21,7 +21,6 @@ import pennylane as qml from pennylane.ops.qubit.attributes import Attribute, has_unitary_generator -from pennylane.ops import Controlled from pennylane.operation import AnyWires # Dummy attribute diff --git a/tests/ops/qubit/test_hamiltonian.py b/tests/ops/qubit/test_hamiltonian.py index dea965a4f70..b861d6bee02 100644 --- a/tests/ops/qubit/test_hamiltonian.py +++ b/tests/ops/qubit/test_hamiltonian.py @@ -14,6 +14,7 @@ """ Tests for the Hamiltonian class. """ +# pylint: disable=too-many-public-methods from collections.abc import Iterable from unittest.mock import patch @@ -33,6 +34,7 @@ ] try: + import jax from jax import numpy as jnp COEFFS_PARAM_INTERFACE.append((jnp.array([-0.05, 0.17]), jnp.array(1.7), "jax")) @@ -49,9 +51,9 @@ pass try: - from torch import tensor + import torch - COEFFS_PARAM_INTERFACE.append((tensor([-0.05, 0.17]), tensor(1.7), "torch")) + COEFFS_PARAM_INTERFACE.append((torch.tensor([-0.05, 0.17]), torch.tensor(1.7), "torch")) except ImportError: pass @@ -651,7 +653,7 @@ def test_hamiltonian_invalid_init_exception(self, coeffs, ops): """Tests that an exception is raised when giving an invalid combination of coefficients and ops""" with pytest.raises(ValueError, match="number of coefficients and operators does not match"): - H = qml.Hamiltonian(coeffs, ops) + qml.Hamiltonian(coeffs, ops) @pytest.mark.parametrize( "obs", [[qml.PauliX(0), qml.CNOT(wires=[0, 1])], [qml.PauliZ, qml.PauliZ(0)]] @@ -668,7 +670,7 @@ def test_hamiltonian_invalid_observables(self, obs): def test_hamiltonian_wires(self, coeffs, ops): """Tests that the Hamiltonian object has correct wires.""" H = qml.Hamiltonian(coeffs, ops) - assert set(H.wires) == set([w for op in H.ops for w in op.wires]) + assert set(H.wires) == set(w for op in H.ops for w in op.wires) def test_label(self): """Tests the label method of Hamiltonian when <=3 coefficients.""" @@ -696,6 +698,7 @@ def test_hamiltonian_str(self, terms, string): @patch("builtins.print") def test_small_hamiltonian_ipython_display(self, mock_print): """Test that the ipython_dipslay method prints __str__.""" + # pylint: disable=protected-access H = 1.0 * qml.PauliX(0) H._ipython_display_() mock_print.assert_called_with(str(H)) @@ -703,6 +706,7 @@ def test_small_hamiltonian_ipython_display(self, mock_print): @patch("builtins.print") def test_big_hamiltonian_ipython_display(self, mock_print): """Test that the ipython_display method prints __repr__ when H has more than 15 terms.""" + # pylint: disable=protected-access H = qml.Hamiltonian([1] * 16, [qml.PauliX(i) for i in range(16)]) H._ipython_display_() mock_print.assert_called_with(repr(H)) @@ -743,6 +747,7 @@ def test_simplify_while_queueing(self): def test_data(self): """Tests the obs_data method""" + # pylint: disable=protected-access H = qml.Hamiltonian( [1, 1, 0.5], @@ -827,7 +832,7 @@ def test_hamiltonian_matmul(self, H1, H2, H): assert H.compare(H1 @ H2) @pytest.mark.parametrize(("H1", "H2", "H"), rmatmul_hamiltonians) - def test_hamiltonian_matmul(self, H1, H2, H): + def test_hamiltonian_rmatmul(self, H1, H2, H): """Tests that Hamiltonians are tensored correctly when using __rmatmul__""" assert H.compare(H1.__rmatmul__(H2)) @@ -837,7 +842,7 @@ def test_hamiltonian_same_wires(self): h1 = qml.Hamiltonian([1, 1], [qml.PauliZ(0), qml.PauliZ(1)]) with pytest.raises(ValueError, match="Hamiltonians can only be multiplied together if"): - h1 @ h1 + _ = h1 @ h1 @pytest.mark.parametrize(("H1", "H2", "H"), add_hamiltonians) def test_hamiltonian_iadd(self, H1, H2, H): @@ -893,14 +898,6 @@ def test_arithmetic_errors(self): def test_hamiltonian_queue_outside(self): """Tests that Hamiltonian are queued correctly when components are defined outside the recording context.""" - queue = [ - qml.Hadamard(wires=1), - qml.PauliX(wires=0), - qml.Hamiltonian( - [1, 3, 1], [qml.PauliX(1), qml.PauliZ(0) @ qml.PauliZ(2), qml.PauliZ(1)] - ), - ] - H = qml.PauliX(1) + 3 * qml.PauliZ(0) @ qml.PauliZ(2) + qml.PauliZ(1) with qml.queuing.AnnotatedQueue() as q: @@ -989,15 +986,13 @@ def test_simplify(self, coeffs): assert H1.data == H2.data +@pytest.mark.tf class TestHamiltonianArithmeticTF: """Tests creation of Hamiltonians using arithmetic operations with TensorFlow tensor coefficients.""" - @pytest.mark.tf def test_hamiltonian_equal(self): """Tests equality""" - import tensorflow as tf - coeffs = tf.Variable([0.5, -1.6]) obs = [qml.PauliX(0), qml.PauliY(1)] H1 = qml.Hamiltonian(coeffs, obs) @@ -1008,11 +1003,8 @@ def test_hamiltonian_equal(self): assert H1.compare(H2) - @pytest.mark.tf def test_hamiltonian_add(self): """Tests that Hamiltonians are added correctly""" - import tensorflow as tf - coeffs = tf.Variable([0.5, -1.6]) obs = [qml.PauliX(0), qml.PauliY(1)] H1 = qml.Hamiltonian(coeffs, obs) @@ -1028,11 +1020,8 @@ def test_hamiltonian_add(self): H1 += H2 assert H.compare(H1) - @pytest.mark.tf def test_hamiltonian_sub(self): """Tests that Hamiltonians are subtracted correctly""" - import tensorflow as tf - coeffs = tf.Variable([1.0, -2.0]) obs = [qml.PauliX(0), qml.PauliY(1)] H1 = qml.Hamiltonian(coeffs, obs) @@ -1048,11 +1037,8 @@ def test_hamiltonian_sub(self): H1 -= H2 assert H.compare(H1) - @pytest.mark.tf def test_hamiltonian_matmul(self): """Tests that Hamiltonians are tensored correctly""" - import tensorflow as tf - coeffs = tf.Variable([1.0, 2.0]) obs = [qml.PauliX(0), qml.PauliY(1)] H1 = qml.Hamiltonian(coeffs, obs) @@ -1080,8 +1066,6 @@ class TestHamiltonianArithmeticTorch: @pytest.mark.torch def test_hamiltonian_equal(self): """Tests equality""" - import torch - coeffs = torch.tensor([0.5, -1.6]) obs = [qml.PauliX(0), qml.PauliY(1)] H1 = qml.Hamiltonian(coeffs, obs) @@ -1095,8 +1079,6 @@ def test_hamiltonian_equal(self): @pytest.mark.torch def test_hamiltonian_add(self): """Tests that Hamiltonians are added correctly""" - import torch - coeffs = torch.tensor([0.5, -1.6]) obs = [qml.PauliX(0), qml.PauliY(1)] H1 = qml.Hamiltonian(coeffs, obs) @@ -1115,8 +1097,6 @@ def test_hamiltonian_add(self): @pytest.mark.torch def test_hamiltonian_sub(self): """Tests that Hamiltonians are subtracted correctly""" - import torch - coeffs = torch.tensor([1.0, -2.0]) obs = [qml.PauliX(0), qml.PauliY(1)] H1 = qml.Hamiltonian(coeffs, obs) @@ -1135,8 +1115,6 @@ def test_hamiltonian_sub(self): @pytest.mark.torch def test_hamiltonian_matmul(self): """Tests that Hamiltonians are tensored correctly""" - import torch - coeffs = torch.tensor([1.0, 2.0]) obs = [qml.PauliX(0), qml.PauliY(1)] H1 = qml.Hamiltonian(coeffs, obs) @@ -1392,15 +1370,13 @@ def test_observable_error(self): H.sparse_matrix(wire_order=["a", "c", "b"]) +@pytest.mark.jax class TestHamiltonianArithmeticJax: """Tests creation of Hamiltonians using arithmetic operations with jax tensor coefficients.""" - @pytest.mark.jax def test_hamiltonian_equal(self): """Tests equality""" - from jax import numpy as jnp - coeffs = jnp.array([0.5, -1.6]) obs = [qml.PauliX(0), qml.PauliY(1)] H1 = qml.Hamiltonian(coeffs, obs) @@ -1411,11 +1387,8 @@ def test_hamiltonian_equal(self): assert H1.compare(H2) - @pytest.mark.jax def test_hamiltonian_add(self): """Tests that Hamiltonians are added correctly""" - from jax import numpy as jnp - coeffs = jnp.array([0.5, -1.6]) obs = [qml.PauliX(0), qml.PauliY(1)] H1 = qml.Hamiltonian(coeffs, obs) @@ -1431,10 +1404,8 @@ def test_hamiltonian_add(self): H1 += H2 assert H.compare(H1) - @pytest.mark.jax def test_hamiltonian_sub(self): """Tests that Hamiltonians are subtracted correctly""" - from jax import numpy as jnp coeffs = jnp.array([1.0, -2.0]) obs = [qml.PauliX(0), qml.PauliY(1)] @@ -1451,11 +1422,8 @@ def test_hamiltonian_sub(self): H1 -= H2 assert H.compare(H1) - @pytest.mark.jax def test_hamiltonian_matmul(self): """Tests that Hamiltonians are tensored correctly""" - from jax import numpy as jnp - coeffs = jnp.array([1.0, 2.0]) obs = [qml.PauliX(0), qml.PauliY(1)] H1 = qml.Hamiltonian(coeffs, obs) @@ -1588,36 +1556,36 @@ class TestHamiltonianEvaluation: def test_vqe_forward_different_coeff_types(self, coeffs, param, interface): """Check that manually splitting a Hamiltonian expectation has the same result as passing the Hamiltonian as an observable""" - dev = qml.device("default.qubit", wires=2) + device = qml.device("default.qubit", wires=2) H = qml.Hamiltonian(coeffs, [qml.PauliX(0), qml.PauliZ(0)]) - @qml.qnode(dev, interface=interface) + @qml.qnode(device, interface=interface) def circuit(): qml.RX(param, wires=0) qml.RY(param, wires=0) return qml.expval(H) - @qml.qnode(dev, interface=interface) - def circuit1(): + @qml.qnode(device, interface=interface) + def node1(): qml.RX(param, wires=0) qml.RY(param, wires=0) return qml.expval(qml.PauliX(0)) - @qml.qnode(dev, interface=interface) - def circuit2(): + @qml.qnode(device, interface=interface) + def node2(): qml.RX(param, wires=0) qml.RY(param, wires=0) return qml.expval(qml.PauliZ(0)) res = circuit() - res_expected = coeffs[0] * circuit1() + coeffs[1] * circuit2() + res_expected = coeffs[0] * node1() + coeffs[1] * node2() assert np.isclose(res, res_expected) def test_simplify_reduces_tape_parameters(self): """Test that simplifying a Hamiltonian reduces the number of parameters on a tape""" - dev = qml.device("default.qubit", wires=2) + device = qml.device("default.qubit", wires=2) - @qml.qnode(dev) + @qml.qnode(device) def circuit(): qml.RY(0.1, wires=0) return qml.expval( @@ -1779,11 +1747,8 @@ def combine(coeffs, param): @pytest.mark.parametrize("simplify", [True, False]) @pytest.mark.parametrize("group", [None, "qwc"]) def test_trainable_coeffs_jax(self, simplify, group): - """Test the jax interface by comparing the differentiation of linearly combined subcircuits - with the differentiation of a Hamiltonian expectation""" - - import jax - import jax.numpy as jnp + """Test the jax interface by comparing the differentiation of linearly + combined subcircuits with the differentiation of a Hamiltonian expectation""" coeffs = jnp.array([-0.05, 0.17]) param = jnp.array(1.7) @@ -1822,10 +1787,6 @@ def combine(coeffs, param): @pytest.mark.jax def test_nontrainable_coeffs_jax(self): """Test the jax interface if the coefficients are explicitly set non-trainable""" - - import jax - import jax.numpy as jnp - coeffs = np.array([-0.05, 0.17]) param = jnp.array(1.7) @@ -1858,9 +1819,6 @@ def combine(coeffs, param): def test_trainable_coeffs_torch(self, simplify, group): """Test the torch interface by comparing the differentiation of linearly combined subcircuits with the differentiation of a Hamiltonian expectation""" - - import torch - coeffs = torch.tensor([-0.05, 0.17], requires_grad=True) param = torch.tensor(1.7, requires_grad=True) @@ -1905,9 +1863,6 @@ def combine(coeffs, param): @pytest.mark.torch def test_nontrainable_coeffs_torch(self): """Test the torch interface if the coefficients are explicitly set non-trainable""" - - import torch - coeffs = torch.tensor([-0.05, 0.17], requires_grad=False) param = torch.tensor(1.7, requires_grad=True) @@ -1951,9 +1906,6 @@ def combine(coeffs, param): def test_trainable_coeffs_tf(self, simplify, group): """Test the tf interface by comparing the differentiation of linearly combined subcircuits with the differentiation of a Hamiltonian expectation""" - - import tensorflow as tf - coeffs = tf.Variable([-0.05, 0.17], dtype=tf.double) param = tf.Variable(1.7, dtype=tf.double) @@ -1998,8 +1950,6 @@ def combine(coeffs, param): def test_nontrainable_coeffs_tf(self): """Test the tf interface if the coefficients are explicitly set non-trainable""" - import tensorflow as tf - coeffs = tf.constant([-0.05, 0.17], dtype=tf.double) param = tf.Variable(1.7, dtype=tf.double) @@ -2040,12 +1990,12 @@ def combine(coeffs, param): def test_not_supported_by_adjoint_differentiation(self): """Test that error is raised when attempting the adjoint differentiation method.""" - dev = qml.device("default.qubit", wires=2) + device = qml.device("default.qubit", wires=2) coeffs = pnp.array([-0.05, 0.17], requires_grad=True) param = pnp.array(1.7, requires_grad=True) - @qml.qnode(dev, diff_method="adjoint") + @qml.qnode(device, diff_method="adjoint") def circuit(coeffs, param): qml.RX(param, wires=0) qml.RY(param, wires=0) diff --git a/tests/ops/qubit/test_non_parametric_ops.py b/tests/ops/qubit/test_non_parametric_ops.py index c4bfe416a43..0678ee0219e 100644 --- a/tests/ops/qubit/test_non_parametric_ops.py +++ b/tests/ops/qubit/test_non_parametric_ops.py @@ -14,6 +14,7 @@ """ Unit tests for the available non-parametric qubit operations """ +# pylint: disable=too-few-public-methods import copy import itertools @@ -71,8 +72,8 @@ class TestOperations: - @pytest.mark.parametrize("op_cls, mat", NON_PARAMETRIZED_OPERATIONS) - def test_nonparametrized_op_copy(self, op_cls, mat, tol): + @pytest.mark.parametrize("op_cls, _", NON_PARAMETRIZED_OPERATIONS) + def test_nonparametrized_op_copy(self, op_cls, _, tol): """Tests that copied nonparametrized ops function as expected""" op = op_cls(wires=0 if op_cls.num_wires is AnyWires else range(op_cls.num_wires)) copied_op = copy.copy(op) @@ -187,7 +188,7 @@ def test_sx_decomposition(self, tol): assert len(res) == 4 - assert all([res[i].wires == Wires([0]) for i in range(4)]) + assert all(res[i].wires == Wires([0]) for i in range(4)) assert res[0].name == "RZ" assert res[1].name == "RY" @@ -599,7 +600,7 @@ def qfunc(): assert optimized_gates == 0 - def qfunc(): + def qfunc1(): qml.Hadamard(wires=0) qml.Barrier(wires=0) qml.Barrier(wires=0) @@ -608,12 +609,12 @@ def qfunc(): return qml.expval(qml.PauliZ(0)) dev = qml.device("default.qubit", wires=3) - qnode = qml.QNode(qfunc, dev) + qnode = qml.QNode(qfunc1, dev) gates = qml.specs(qnode)()["resources"].gate_sizes[1] assert gates == 4 - def qfunc(): + def qfunc2(): qml.Hadamard(wires=0) qml.Barrier(only_visual=True, wires=0) qml.Barrier(wires=0) @@ -622,7 +623,7 @@ def qfunc(): return qml.expval(qml.PauliZ(0)) dev = qml.device("default.qubit", wires=3) - optimized_qfunc = qml.compile()(qfunc) + optimized_qfunc = qml.compile()(qfunc2) optimized_qnode = qml.QNode(optimized_qfunc, dev) optimized_gates = qml.specs(optimized_qnode)()["resources"].gate_sizes[1] @@ -929,6 +930,7 @@ def test_decomposition_with_many_workers(self, n_ctrl_wires): """Test that the decomposed MultiControlledX gate performs the same unitary as the matrix-based version by checking if U^dagger U applies the identity to each basis state. This test focuses on the case where there are many work wires.""" + # pylint: disable=protected-access control_wires = range(n_ctrl_wires) target_wire = n_ctrl_wires work_wires = range(n_ctrl_wires + 1, 2 * n_ctrl_wires + 1) @@ -960,6 +962,7 @@ def test_decomposition_with_one_worker(self, n_ctrl_wires): """Test that the decomposed MultiControlledX gate performs the same unitary as the matrix-based version by checking if U^dagger U applies the identity to each basis state. This test focuses on the case where there is one work wire.""" + # pylint: disable=protected-access control_wires = Wires(range(n_ctrl_wires)) target_wire = n_ctrl_wires work_wires = n_ctrl_wires + 1 @@ -972,9 +975,7 @@ def test_decomposition_with_one_worker(self, n_ctrl_wires): ) tape = qml.tape.QuantumScript.from_queue(q) tape = tape.expand(depth=1) - assert all( - isinstance(op, qml.Toffoli) or isinstance(op, qml.CNOT) for op in tape.operations - ) + assert all(isinstance(op, (qml.Toffoli, qml.CNOT)) for op in tape.operations) @qml.qnode(dev) def f(bitstring): @@ -995,7 +996,7 @@ def test_not_enough_workers(self): control_target_wires = range(4) op = qml.MultiControlledX(wires=control_target_wires) - match = f"At least one work wire is required to decompose operation: MultiControlledX" + match = "At least one work wire is required to decompose operation: MultiControlledX" with pytest.raises(ValueError, match=match): op.decomposition() @@ -1282,6 +1283,8 @@ def test_pow_independent_ops(self, op, n): class TestControlledMethod: """Tests for the _controlled method of non-parametric operations.""" + # pylint: disable=protected-access + def test_PauliX(self): """Test the PauliX _controlled method.""" out = qml.PauliX(0)._controlled("a") @@ -1325,7 +1328,7 @@ def test_sparse_matrix(self, op, mat): expected_sparse_mat = csr_matrix(mat) sparse_mat = op.sparse_matrix() - assert type(sparse_mat) == type(expected_sparse_mat) + assert isinstance(sparse_mat, type(expected_sparse_mat)) assert all(sparse_mat.data == expected_sparse_mat.data) assert all(sparse_mat.indices == expected_sparse_mat.indices) @@ -1409,7 +1412,7 @@ def test_control_wires(op, control_wires): @pytest.mark.parametrize("op", involution_ops) -def test_adjoint_method(op, tol): +def test_adjoint_method(op): adj_op = copy.copy(op) for _ in range(4): adj_op = adj_op.adjoint() @@ -1427,4 +1430,5 @@ def test_adjoint_method(op, tol): @pytest.mark.parametrize("op, rep", op_pauli_rep) def test_pauli_rep(op, rep): + # pylint: disable=protected-access assert op._pauli_rep == rep diff --git a/tests/ops/qubit/test_observables.py b/tests/ops/qubit/test_observables.py index 0332fa35403..e030e17014c 100644 --- a/tests/ops/qubit/test_observables.py +++ b/tests/ops/qubit/test_observables.py @@ -12,19 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. """Unit tests for qubit observables.""" +# pylint: disable=protected-access import functools import pytest -import pennylane as qml import numpy as np -from pennylane.ops.qubit.observables import _BasisStateProjector, _StateVectorProjector -from gate_data import ( - I, - X, - Y, - Z, - H, -) +from gate_data import I, X, Y, Z, H +import pennylane as qml +from pennylane.ops.qubit.observables import _BasisStateProjector, _StateVectorProjector @pytest.fixture(autouse=True) @@ -108,8 +103,8 @@ def run_before_tests(): class TestSimpleObservables: """Tests for simple single-qubit observables""" - @pytest.mark.parametrize("obs, mat, eigs", OBSERVABLES) - def test_diagonalization(self, obs, mat, eigs, tol): + @pytest.mark.parametrize("obs, _, eigs", OBSERVABLES) + def test_diagonalization(self, obs, _, eigs, tol): """Test the method transforms standard observables into the Z-gate.""" ob = obs(wires=0) A = ob.matrix() @@ -165,15 +160,15 @@ def test_diagonalization_static_pauliz(self): """Test the static compute_diagonalizing_gates method for the PauliZ observable.""" assert qml.PauliZ.compute_diagonalizing_gates(wires=1) == [] - @pytest.mark.parametrize("obs, mat, eigs", OBSERVABLES) - def test_eigvals(self, obs, mat, eigs, tol): + @pytest.mark.parametrize("obs, _, eigs", OBSERVABLES) + def test_eigvals(self, obs, _, eigs, tol): """Test eigenvalues of standard observables are correct""" obs = obs(wires=0) res = obs.eigvals() assert np.allclose(res, eigs, atol=tol, rtol=0) - @pytest.mark.parametrize("obs, mat, eigs", OBSERVABLES) - def test_matrices(self, obs, mat, eigs, tol): + @pytest.mark.parametrize("obs, mat, _", OBSERVABLES) + def test_matrices(self, obs, mat, _, tol): """Test matrices of standard observables are correct""" obs = obs(wires=0) res = obs.matrix() @@ -196,11 +191,11 @@ def test_preserves_autograd_trainability(self): def test_hermitian_creation_exceptions(self): """Tests that the hermitian matrix method raises the proper errors.""" - H = np.array([[1, 1], [1, -1]]) / np.sqrt(2) + ham = np.array([[1, 1], [1, -1]]) / np.sqrt(2) # test non-square matrix with pytest.raises(ValueError, match="must be a square matrix"): - qml.Hermitian(H[1:], wires=0) + qml.Hermitian(ham[1:], wires=0) H1 = np.array([[1]]) / np.sqrt(2) @@ -209,20 +204,20 @@ def test_hermitian_creation_exceptions(self): qml.Hermitian(H1, wires=[0]) # test non-Hermitian matrix - H2 = H.copy() + H2 = ham.copy() H2[0, 1] = 2 with pytest.raises(ValueError, match="must be Hermitian"): qml.Hermitian(H2, wires=0) def test_ragged_input_raises(self): """Tests that an error is raised if the input to Hermitian is ragged.""" - H = [[1, 0], [0, 1, 2]] + ham = [[1, 0], [0, 1, 2]] with pytest.warns( np.VisibleDeprecationWarning, match="Creating an ndarray from ragged nested sequences" ): with pytest.raises(ValueError, match="must be a square matrix"): - qml.Hermitian(H, wires=0) + qml.Hermitian(ham, wires=0) @pytest.mark.parametrize("observable, eigvals, eigvecs", EIGVALS_TEST_DATA) def test_hermitian_eigegendecomposition_single_wire(self, observable, eigvals, eigvecs, tol): @@ -313,6 +308,7 @@ def test_hermitian_eigvals_eigvecs_same_observable_twice( @pytest.mark.parametrize("observable, eigvals, eigvecs", EIGVALS_TEST_DATA) def test_hermitian_diagonalizing_gates(self, observable, eigvals, eigvecs, tol, mocker): """Tests that the diagonalizing_gates method of the Hermitian class returns the correct results.""" + # pylint: disable=too-many-arguments # check calling `diagonalizing_gates` when `observable` is not in `_eigs` adds expected entry to `_eigs` spy = mocker.spy(np.linalg, "eigh") @@ -406,8 +402,8 @@ def test_hermitian_diagonalizing_gatesi_same_observable_twice( assert np.allclose(qubit_unitary[0].data, eigvecs.conj().T, atol=tol, rtol=0) assert len(qml.Hermitian._eigs) == 1 - @pytest.mark.parametrize("observable, eigvals, eigvecs", EIGVALS_TEST_DATA) - def test_hermitian_diagonalizing_gates_integration(self, observable, eigvals, eigvecs, tol): + @pytest.mark.parametrize("observable, eigvals, _", EIGVALS_TEST_DATA) + def test_hermitian_diagonalizing_gates_integration(self, observable, eigvals, _, tol): """Tests that the diagonalizing_gates method of the Hermitian class diagonalizes the given observable.""" tensor_obs = np.kron(observable, observable) @@ -423,25 +419,25 @@ def test_hermitian_diagonalizing_gates_integration(self, observable, eigvals, ei def test_hermitian_matrix(self, tol): """Test that the hermitian matrix method produces the correct output.""" - H = np.array([[1, 1], [1, -1]]) / np.sqrt(2) - out = qml.Hermitian(H, wires=0).matrix() + ham = np.array([[1, 1], [1, -1]]) / np.sqrt(2) + out = qml.Hermitian(ham, wires=0).matrix() # verify output type assert isinstance(out, np.ndarray) # verify equivalent to input state - assert np.allclose(out, H, atol=tol, rtol=0) + assert np.allclose(out, ham, atol=tol, rtol=0) def test_hermitian_exceptions(self): """Tests that the hermitian matrix method raises the proper errors.""" - H = np.array([[1, 1], [1, -1]]) / np.sqrt(2) + ham = np.array([[1, 1], [1, -1]]) / np.sqrt(2) # test non-square matrix with pytest.raises(ValueError, match="must be a square matrix"): - qml.Hermitian(H[1:], wires=0).matrix() + qml.Hermitian(ham[1:], wires=0).matrix() # test non-Hermitian matrix - H2 = H.copy() + H2 = ham.copy() H2[0, 1] = 2 with pytest.raises(ValueError, match="must be Hermitian"): qml.Hermitian(H2, wires=0).matrix() @@ -708,9 +704,9 @@ def test_hermitian_labelling_w_cache(): op = qml.Hermitian(X, wires=0) cache = {"matrices": [Z]} - op.label(cache=cache) == "𝓗(M1)" + assert op.label(cache=cache) == "𝓗(M1)" assert qml.math.allclose(cache["matrices"][1], X) cache = {"matrices": [Z, Y, X]} - op.label(cache=cache) == "𝓗(M2)" + assert op.label(cache=cache) == "𝓗(M2)" assert len(cache["matrices"]) == 3 diff --git a/tests/ops/qubit/test_parametric_ops.py b/tests/ops/qubit/test_parametric_ops.py index fe17dfa4c99..41a2a6fd3f0 100644 --- a/tests/ops/qubit/test_parametric_ops.py +++ b/tests/ops/qubit/test_parametric_ops.py @@ -14,6 +14,7 @@ """ Unit tests for the available built-in parametric qubit operations. """ +# pylint: disable=too-few-public-methods,too-many-public-methods import copy from functools import reduce @@ -842,7 +843,7 @@ def test_controlled_phase_shift_decomp(self, phi, cphase_op): assert np.allclose(decomposed_matrix, exp) @pytest.mark.parametrize("cphase_op", [qml.ControlledPhaseShift, qml.CPhase]) - def test_controlled_phase_shift_decomp(self, cphase_op): + def test_controlled_phase_shift_decomp_broadcasted(self, cphase_op): """Tests that the ControlledPhaseShift and CPhase operation calculates the correct decomposition""" phi = np.array([-0.2, 4.2, 1.8]) @@ -1156,7 +1157,7 @@ def get_expected(theta): ) @pytest.mark.parametrize("phi", np.linspace(-np.pi, np.pi, 10)) - def test_pswap_eigvals(self, phi, tol): + def test_pswap_eigvals(self, phi): """Test eigenvalues computation for PSWAP""" evs = qml.PSWAP.compute_eigvals(phi) evs_expected = [1, 1, -qml.math.exp(1j * phi), qml.math.exp(1j * phi)] @@ -1164,7 +1165,7 @@ def test_pswap_eigvals(self, phi, tol): @pytest.mark.tf @pytest.mark.parametrize("phi", np.linspace(-np.pi, np.pi, 10)) - def test_pswap_eigvals_tf(self, phi, tol): + def test_pswap_eigvals_tf(self, phi): """Test eigenvalues computation for PSWAP using Tensorflow interface""" import tensorflow as tf @@ -1175,7 +1176,7 @@ def test_pswap_eigvals_tf(self, phi, tol): @pytest.mark.torch @pytest.mark.parametrize("phi", np.linspace(-np.pi, np.pi, 10)) - def test_pswap_eigvals_torch(self, phi, tol): + def test_pswap_eigvals_torch(self, phi): """Test eigenvalues computation for PSWAP using Torch interface""" import torch @@ -1186,7 +1187,7 @@ def test_pswap_eigvals_torch(self, phi, tol): @pytest.mark.jax @pytest.mark.parametrize("phi", np.linspace(-np.pi, np.pi, 10)) - def test_pswap_eigvals_jax(self, phi, tol): + def test_pswap_eigvals_jax(self, phi): """Test eigenvalues computation for PSWAP using JAX interface""" import jax @@ -1228,7 +1229,6 @@ def test_isingxy_broadcasted(self, tol): def get_expected(theta): expected = np.array([np.eye(4) for i in theta], dtype=complex) - sin_coeff = 1j * np.sin(theta / 2) expected[:, 1, 1] = np.cos(theta / 2) expected[:, 2, 2] = np.cos(theta / 2) expected[:, 1, 2] = 1j * np.sin(theta / 2) @@ -1248,7 +1248,7 @@ def get_expected(theta): ) @pytest.mark.parametrize("phi", np.linspace(-np.pi, np.pi, 10)) - def test_isingxy_eigvals(self, phi, tol): + def test_isingxy_eigvals(self, phi): """Test eigenvalues computation for IsingXY""" evs = qml.IsingXY.compute_eigvals(phi) evs_expected = [ @@ -1259,7 +1259,7 @@ def test_isingxy_eigvals(self, phi, tol): ] assert qml.math.allclose(evs, evs_expected) - def test_isingxy_eigvals_broadcasted(self, tol): + def test_isingxy_eigvals_broadcasted(self): """Test broadcasted eigenvalues computation for IsingXY""" phi = np.linspace(-np.pi, np.pi, 10) evs = qml.IsingXY.compute_eigvals(phi) @@ -1270,7 +1270,7 @@ def test_isingxy_eigvals_broadcasted(self, tol): @pytest.mark.tf @pytest.mark.parametrize("phi", np.linspace(-np.pi, np.pi, 10)) - def test_isingxy_eigvals_tf(self, phi, tol): + def test_isingxy_eigvals_tf(self, phi): """Test eigenvalues computation for IsingXY using Tensorflow interface""" import tensorflow as tf @@ -1285,7 +1285,7 @@ def test_isingxy_eigvals_tf(self, phi, tol): assert qml.math.allclose(evs, evs_expected) @pytest.mark.tf - def test_isingxy_eigvals_tf_broadcasted(self, tol): + def test_isingxy_eigvals_tf_broadcasted(self): """Test broadcasted eigenvalues computation for IsingXY on TF""" import tensorflow as tf @@ -1299,7 +1299,7 @@ def test_isingxy_eigvals_tf_broadcasted(self, tol): @pytest.mark.torch @pytest.mark.parametrize("phi", np.linspace(-np.pi, np.pi, 10)) - def test_isingxy_eigvals_torch(self, phi, tol): + def test_isingxy_eigvals_torch(self, phi): """Test eigenvalues computation for IsingXY using Torch interface""" import torch @@ -1314,7 +1314,7 @@ def test_isingxy_eigvals_torch(self, phi, tol): assert qml.math.allclose(evs, evs_expected) @pytest.mark.torch - def test_isingxy_eigvals_torch_broadcasted(self, tol): + def test_isingxy_eigvals_torch_broadcasted(self): """Test broadcasted eigenvalues computation for IsingXY with torch""" import torch @@ -1328,7 +1328,7 @@ def test_isingxy_eigvals_torch_broadcasted(self, tol): @pytest.mark.jax @pytest.mark.parametrize("phi", np.linspace(-np.pi, np.pi, 10)) - def test_isingxy_eigvals_jax(self, phi, tol): + def test_isingxy_eigvals_jax(self, phi): """Test eigenvalues computation for IsingXY using JAX interface""" import jax @@ -1343,7 +1343,7 @@ def test_isingxy_eigvals_jax(self, phi, tol): assert qml.math.allclose(evs, evs_expected) @pytest.mark.jax - def test_isingxy_eigvals_jax_broadcasted(self, tol): + def test_isingxy_eigvals_jax_broadcasted(self): """Test broadcasted eigenvalues computation for IsingXY with jax""" import jax @@ -1903,7 +1903,7 @@ def test_controlled_phase_shift_matrix_and_eigvals(self, phi, cphase_op): @pytest.mark.tf @pytest.mark.parametrize("phi", [-0.1, 0.2, 0.5]) @pytest.mark.parametrize("cphase_op", [qml.ControlledPhaseShift, qml.CPhase]) - def test_controlled_phase_shift_matrix_and_eigvals(self, phi, cphase_op): + def test_controlled_phase_shift_matrix_and_eigvals_tf(self, phi, cphase_op): """Tests that the ControlledPhaseShift and CPhase operation calculate the correct matrix and eigenvalues for the Tensorflow interface, because the code differs in that case.""" @@ -1984,7 +1984,7 @@ def test_c_phase_shift_matrix_and_eigvals(self, phi, cphase_op, gate_data_mat): (qml.CPhaseShift10, CPhaseShift10), ], ) - def test_c_phase_shift_matrix_and_eigvals_tf(self, phi, cphase_op, gate_data_mat, tol): + def test_c_phase_shift_matrix_and_eigvals_tf(self, phi, cphase_op, gate_data_mat): """Test matrix and eigenvalues computation for CPhaseShift using Tensorflow interface""" import tensorflow as tf @@ -2007,7 +2007,7 @@ def test_c_phase_shift_matrix_and_eigvals_tf(self, phi, cphase_op, gate_data_mat (qml.CPhaseShift10, CPhaseShift10), ], ) - def test_c_phase_shift_matrix_and_eigvals_torch(self, phi, cphase_op, gate_data_mat, tol): + def test_c_phase_shift_matrix_and_eigvals_torch(self, phi, cphase_op, gate_data_mat): """Test matrix and eigenvalues computation for CPhaseShift using Torch interface""" import torch @@ -2030,7 +2030,7 @@ def test_c_phase_shift_matrix_and_eigvals_torch(self, phi, cphase_op, gate_data_ (qml.CPhaseShift10, CPhaseShift10), ], ) - def test_c_phase_shift_matrix_and_eigvals_jax(self, phi, cphase_op, gate_data_mat, tol): + def test_c_phase_shift_matrix_and_eigvals_jax(self, phi, cphase_op, gate_data_mat): """Test matrix and eigenvalues computation for CPhaseShift using JAX interface""" import jax @@ -3093,6 +3093,7 @@ def test_PauliRot_matrix_identity( self, theta, pauli_word, compressed_pauli_word, wires, compressed_wires, tol ): """Test PauliRot matrix correctly accounts for identities.""" + # pylint: disable=too-many-arguments res = qml.PauliRot.compute_matrix(theta, pauli_word) expected = qml.math.expand_matrix( @@ -3237,7 +3238,6 @@ def circuit(theta): return qml.expval(qml.PauliZ(0) @ qml.PauliZ(1)) - res = circuit(angle) gradient = np.squeeze(qml.grad(circuit)(angle)) assert gradient == pytest.approx( @@ -3256,7 +3256,6 @@ def circuit(theta): return qml.expval(qml.PauliZ(0) @ qml.PauliZ(1)) angle = npp.linspace(0, 2 * np.pi, 7, requires_grad=True) - res = circuit(angle) jac = qml.jacobian(circuit)(angle) assert np.allclose( @@ -3266,7 +3265,7 @@ def circuit(theta): ) @pytest.mark.parametrize("angle", npp.linspace(0, 2 * np.pi, 7, requires_grad=True)) - def test_decomposition_integration(self, angle, tol): + def test_decomposition_integration(self, angle): """Test that the decompositon of PauliRot yields the same results.""" dev = qml.device("default.qubit", wires=2) @@ -3491,7 +3490,6 @@ def circuit(theta): return qml.expval(qml.PauliX(0)) - res = circuit(angle) gradient = np.squeeze(qml.grad(circuit)(angle)) assert gradient == pytest.approx( @@ -3512,7 +3510,6 @@ def circuit(theta): return qml.expval(qml.PauliX(0) @ qml.PauliX(1)) angle = npp.linspace(0, 2 * np.pi, 7, requires_grad=True) - res = circuit(angle) jac = qml.jacobian(circuit)(angle) assert np.allclose( @@ -3520,7 +3517,7 @@ def circuit(theta): ) @pytest.mark.parametrize("angle", npp.linspace(0, 2 * np.pi, 7, requires_grad=True)) - def test_decomposition_integration(self, angle, tol): + def test_decomposition_integration(self, angle): """Test that the decompositon of MultiRZ yields the same results.""" angle = qml.numpy.array(angle) dev = qml.device("default.qubit", wires=2) @@ -3560,7 +3557,7 @@ def test_multirz_generator(self, qubits, mocker): spy.assert_not_called() @pytest.mark.parametrize("theta", [0.4, np.array([np.pi / 3, 0.1, -0.9])]) - def test_multirz_eigvals(self, theta, tol): + def test_multirz_eigvals(self, theta): """Test that the eigenvalues of the MultiRZ gate are correct.""" op = qml.MultiRZ(theta, wires=range(3)) @@ -4039,6 +4036,7 @@ def test_simplify_u3(self): @pytest.mark.parametrize("base, cbase", controlled_data) def test_controlled_method(base, cbase): """Tests the _controlled method for parametric ops.""" + # pylint: disable=protected-access assert qml.equal(base._controlled("a"), cbase) diff --git a/tests/ops/qubit/test_qchem_ops.py b/tests/ops/qubit/test_qchem_ops.py index d2be9499a1a..2e14798ea1e 100644 --- a/tests/ops/qubit/test_qchem_ops.py +++ b/tests/ops/qubit/test_qchem_ops.py @@ -14,18 +14,12 @@ """ Unit tests for the available qubit operations for quantum chemistry purposes. """ +# pylint: disable=too-few-public-methods import pytest import numpy as np from scipy.linalg import expm, fractional_matrix_power -import pennylane as qml -from pennylane import numpy as pnp - from gate_data import ( - X, - StateZeroProjector, - StateOneProjector, - ControlledPhaseShift, SingleExcitation, SingleExcitationPlus, SingleExcitationMinus, @@ -35,6 +29,8 @@ OrbitalRotation, FermionicSWAP, ) +import pennylane as qml +from pennylane import numpy as pnp PARAMETRIZED_QCHEM_OPERATIONS = [ @@ -303,7 +299,7 @@ def test_autograd_grad(self, diff_method, excitation, phi): dev = qml.device("default.qubit.autograd", wires=2) - @qml.qnode(dev) + @qml.qnode(dev, diff_method=diff_method) def circuit(phi): qml.PauliX(wires=0) excitation(phi, wires=[0, 1]) @@ -391,19 +387,6 @@ def test_double_excitation_matrix_broadcasted(self): assert np.allclose(res_dynamic, exp) assert np.allclose(res_static, exp) - @pytest.mark.parametrize("phi", [-0.1, 0.2, np.pi / 4]) - def test_double_excitation_decomp(self, phi): - """Tests that the DoubleExcitation operation calculates the correct decomposition""" - decomp1 = qml.DoubleExcitation(phi, wires=[0, 1, 2, 3]).decomposition() - decomp2 = qml.DoubleExcitation.compute_decomposition(phi, wires=[0, 1, 2, 3]) - - for decomp in [decomp1, decomp2]: - mats = [m.matrix() for m in decomp] - decomposed_matrix = mats[0] @ mats[1] - exp = DoubleExcitation(phi) - - assert np.allclose(decomposed_matrix, exp) - @pytest.mark.parametrize("phi", [-0.1, 0.2, np.pi / 4]) def test_double_excitation_generator(self, phi): """Tests that the DoubleExcitation operation calculates the correct generator""" @@ -441,38 +424,8 @@ def test_double_excitation_decomp(self, phi): decomp1 = qml.DoubleExcitation(phi, wires=[0, 1, 2, 3]).decomposition() decomp2 = qml.DoubleExcitation.compute_decomposition(phi, wires=[0, 1, 2, 3]) - from functools import reduce - - # To compute the matrix for CX on an arbitrary number of qubits, use the fact that - # CU = |0><0| \otimes I + |1><1| \otimes U - def cnot_four_qubits(wires): - proj_0_term = [StateZeroProjector if idx == wires[0] else np.eye(2) for idx in range(4)] - - proj_1_term = [np.eye(2) for idx in range(4)] - proj_1_term[wires[0]] = StateOneProjector - proj_1_term[wires[1]] = X - - proj_0_kron = reduce(np.kron, proj_0_term) - proj_1_kron = reduce(np.kron, proj_1_term) - - return proj_0_kron + proj_1_kron - - # Inserts a single-qubit matrix into a four-qubit matrix at the right place - def single_mat_four_qubits(mat, wire): - individual_mats = [mat if idx == wire else np.eye(2) for idx in range(4)] - return reduce(np.kron, individual_mats) - for decomp in [decomp1, decomp2]: - mats = [] - for i in reversed(decomp): - # Single-qubit gate - if len(i.wires.tolist()) == 1: - mat = single_mat_four_qubits(i.matrix(), i.wires.tolist()[0]) - mats.append(mat) - # Two-qubit gate - else: - mat = cnot_four_qubits(i.wires.tolist()) - mats.append(mat) + mats = [op.matrix(wire_order=list(range(4))) for op in decomp] decomposed_matrix = np.linalg.multi_dot(mats) exp = DoubleExcitation(phi) @@ -894,8 +847,6 @@ def test_jax(self): """Tests that operations are computed correctly using the jax interface""" - import jax - dev = qml.device("default.qubit.jax", wires=4) state = np.array( [ @@ -933,8 +884,6 @@ def test_torch(self): """Tests that operations are computed correctly using the torch interface""" - import torch - dev = qml.device("default.qubit.torch", wires=4) state = np.array( [ @@ -1189,7 +1138,7 @@ def test_autograd_grad(self, diff_method, phi): dev = qml.device("default.qubit.autograd", wires=2) - @qml.qnode(dev) + @qml.qnode(dev, diff_method=diff_method) def circuit(phi): qml.PauliX(wires=0) qml.FermionicSWAP(phi, wires=[0, 1]) diff --git a/tests/ops/qubit/test_sparse.py b/tests/ops/qubit/test_sparse.py index 93cf7545645..30039971588 100644 --- a/tests/ops/qubit/test_sparse.py +++ b/tests/ops/qubit/test_sparse.py @@ -16,11 +16,8 @@ """ import pytest import numpy as np -import scipy.sparse.coo from scipy.sparse import coo_matrix, csr_matrix import pennylane as qml -from pennylane import DeviceError -from pennylane.wires import Wires SPARSE_HAMILTONIAN_TEST_DATA = [(np.array([[1, 0], [-1.5, 0]])), (np.eye(4))] @@ -191,6 +188,7 @@ def circuit(): ) def test_sparse_hamiltonian_expval(self, qubits, operations, hamiltonian, expected_output, tol): """Test that expectation values of sparse hamiltonians are properly calculated.""" + # pylint: disable=too-many-arguments hamiltonian = csr_matrix(hamiltonian) @@ -208,4 +206,4 @@ def test_sparse_expval_error(self): dev = qml.device("default.qubit", wires=1, shots=1) with pytest.raises(AssertionError, match="SparseHamiltonian must be used with shots=None"): - dev.expval(qml.SparseHamiltonian(hamiltonian, [0]))[0] + dev.expval(qml.SparseHamiltonian(hamiltonian, [0])) diff --git a/tests/ops/qutrit/test_qutrit_matrix_ops.py b/tests/ops/qutrit/test_qutrit_matrix_ops.py index 3da68311f0c..7acee79a346 100644 --- a/tests/ops/qutrit/test_qutrit_matrix_ops.py +++ b/tests/ops/qutrit/test_qutrit_matrix_ops.py @@ -14,16 +14,16 @@ """ Unit tests for the qutrit matrix-based operations. """ -from pennylane.ops.qutrit.matrix_ops import ControlledQutritUnitary +# pylint: disable=protected-access import pytest import numpy as np from scipy.stats import unitary_group +from gate_data import TSWAP import pennylane as qml from pennylane.wires import Wires from pennylane.operation import DecompositionUndefinedError -from gate_data import TSWAP U_thadamard_01 = np.multiply( 1 / np.sqrt(2), @@ -617,24 +617,6 @@ def test_adjoint(self): adjoint_mat = op.data[0].T.conj() assert qml.math.allclose(adjoint_op.data[0], adjoint_mat) - def test_adjoint(self): - """Tests the metadata and unitary for an adjoint ControlledQutritUnitary operation.""" - U1 = unitary_group.rvs(3, random_state=10) - - op = qml.ControlledQutritUnitary( - U1, control_wires=("b", "c"), wires="a", control_values="01" - ) - - adjoint_op = op.adjoint() - assert isinstance(adjoint_op, qml.ControlledQutritUnitary) - - assert adjoint_op.hyperparameters["u_wires"] == op.hyperparameters["u_wires"] - assert adjoint_op.control_wires == op.control_wires - assert adjoint_op.control_values == op.control_values - - adjoint_mat = op.data[0].T.conj() - assert qml.math.allclose(adjoint_op.data[0], adjoint_mat) - label_data = [ (U_thadamard_01, qml.QutritUnitary(U_thadamard_01, wires=0)), @@ -644,6 +626,7 @@ def test_adjoint(self): @pytest.mark.parametrize("mat, op", label_data) class TestUnitaryLabels: + # pylint: disable=unused-argument def test_no_cache(self, mat, op): """Test labels work without a provided cache.""" assert op.label() == "U" diff --git a/tests/ops/qutrit/test_qutrit_non_parametric_ops.py b/tests/ops/qutrit/test_qutrit_non_parametric_ops.py index fbf722ccf65..51f8ffcae7b 100644 --- a/tests/ops/qutrit/test_qutrit_non_parametric_ops.py +++ b/tests/ops/qutrit/test_qutrit_non_parametric_ops.py @@ -14,15 +14,14 @@ """ Unit tests for the available non-parametric qutrit operations """ -import pytest import copy +import pytest import numpy as np -from scipy.stats import unitary_group +from gate_data import TSHIFT, TCLOCK, TADD, TSWAP, TH import pennylane as qml from pennylane.wires import Wires -from gate_data import OMEGA, TSHIFT, TCLOCK, TADD, TSWAP, TH NON_PARAMETRIZED_OPERATIONS = [ (qml.TShift, TSHIFT, None), @@ -37,8 +36,8 @@ class TestOperations: - @pytest.mark.parametrize("op_cls, mat, subspace", NON_PARAMETRIZED_OPERATIONS) - def test_nonparametrized_op_copy(self, op_cls, mat, subspace, tol): + @pytest.mark.parametrize("op_cls, _, subspace", NON_PARAMETRIZED_OPERATIONS) + def test_nonparametrized_op_copy(self, op_cls, _, subspace, tol): """Tests that copied nonparametrized ops function as expected""" op = ( op_cls(wires=range(op_cls.num_wires)) @@ -144,7 +143,7 @@ def test_period_three_ops_pow_offset_2(self, op, offset): # When raising to power == 2 mod 3 with pytest.raises(qml.operation.PowUndefinedError): - op_pow_2 = op.pow(2 + offset) + op.pow(2 + offset) @pytest.mark.parametrize("op", period_three_ops + period_two_ops) def test_period_two_three_noninteger_power(self, op): @@ -224,7 +223,7 @@ def test_control_wires(op, control_wires): @pytest.mark.parametrize("op", no_adjoint_ops) -def test_adjoint_method(op, tol): +def test_adjoint_method(op): """Assert that ops that are not their own inverses do not have a defined adjoint.""" assert not op.has_adjoint @@ -233,7 +232,7 @@ def test_adjoint_method(op, tol): @pytest.mark.parametrize("op", involution_ops) -def test_adjoint_method_involution(op, tol): +def test_adjoint_method_involution(op): """Assert that involution ops are their own adjoint.""" assert op.has_adjoint diff --git a/tests/ops/test_channel_ops.py b/tests/ops/test_channel_ops.py index 17a06074bbc..d337a0baa56 100644 --- a/tests/ops/test_channel_ops.py +++ b/tests/ops/test_channel_ops.py @@ -14,6 +14,7 @@ """ Unit tests for the available built-in quantum channels. """ +# pylint: disable=too-few-public-methods from itertools import product import pytest import numpy as np @@ -332,7 +333,7 @@ def test_p_arbitrary(self, p, tol): assert np.allclose(op(p, wires=0).kraus_matrices()[1], expected_K1, atol=tol, rtol=0) @pytest.mark.parametrize("angle", np.linspace(0, 2 * np.pi, 7)) - def test_grad_bitflip(self, angle, tol): + def test_grad_bitflip(self, angle): """Test that analytical gradient is computed correctly for different states. Channel grad recipes are independent of channel parameter""" @@ -408,7 +409,7 @@ def test_p_arbitrary(self, p, tol): assert np.allclose(op(p, wires=0).kraus_matrices()[1], expected_K1, atol=tol, rtol=0) @pytest.mark.parametrize("angle", np.linspace(0, 2 * np.pi, 7)) - def test_grad_phaseflip(self, angle, tol): + def test_grad_phaseflip(self, angle): """Test that analytical gradient is computed correctly for different states. Channel grad recipes are independent of channel parameter""" @@ -485,7 +486,7 @@ def test_p_arbitrary(self, tol): assert np.allclose(op(0.1, wires=0).kraus_matrices()[1], expected, atol=tol, rtol=0) @pytest.mark.parametrize("angle", np.linspace(0, 2 * np.pi, 7)) - def test_grad_depolarizing(self, angle, tol): + def test_grad_depolarizing(self, angle): """Test that analytical gradient is computed correctly for different states. Channel grad recipes are independent of channel parameter""" @@ -596,7 +597,7 @@ def test_p0_p1_sum_not_normalized(self): channel.ResetError(1.0, 1.0, wires=0).kraus_matrices() @pytest.mark.parametrize("angle", np.linspace(0, 2 * np.pi, 7)) - def test_grad_reset_error(self, angle, tol): + def test_grad_reset_error(self, angle): """Test that gradient is computed correctly for different states. Channel grad recipes are independent of channel parameter""" @@ -719,13 +720,14 @@ class TestPauliError: ) def test_wrong_parameters(self, operators, p, wires, error, message): """Test wrong parametrizations of PauliError""" + # pylint: disable=too-many-arguments with pytest.raises(error, match=message): - Ks = channel.PauliError(operators, p, wires=wires) + channel.PauliError(operators, p, wires=wires) def test_warning_many_qubits(self): """Test if warning is thrown when huge matrix""" with pytest.warns(UserWarning): - Ks = channel.PauliError("X" * 512, 0.5, wires=list(range(512))) + channel.PauliError("X" * 512, 0.5, wires=list(range(512))) def test_p_zero(self, tol): """Test resulting Kraus matrices for p=0""" @@ -924,7 +926,9 @@ class TestThermalRelaxationError: ), ) def test_t2_le_t1_arbitrary(self, pe, t1, t2, tg, tol): - """Test that various values of pe, t1, t2, and tg for t2 <= t1 give correct Kraus matrices""" + """Test that various values of pe, t1, t2, and tg + for t2 <= t1 give correct Kraus matrices""" + # pylint: disable=too-many-arguments op = channel.ThermalRelaxationError @@ -978,7 +982,9 @@ def test_t2_le_t1_arbitrary(self, pe, t1, t2, tg, tol): ), ) def test_t2_g_t1_arbitrary(self, pe, t1, t2, tg, tol): - """Test that various values of pe, t1, t2, and tg for t2 > t1 give correct Kraus matrices""" + """Test that various values of pe, t1, t2, and tg + for t2 > t1 give correct Kraus matrices""" + # pylint: disable=too-many-arguments op = channel.ThermalRelaxationError @@ -1007,22 +1013,22 @@ def test_t2_g_t1_arbitrary(self, pe, t1, t2, tg, tol): e3 = 1 - p_reset / 2 + common_term / 2 v3 = np.array([[term3], [0], [0], [1]]) / np.sqrt(term3**2 + 1**2) - expected_K0 = np.sqrt(e0) * v0.reshape(2, 2, order="F") + expected_K0 = np.sqrt(e0) * v0.reshape((2, 2), order="F") assert np.allclose( op(pe, t1, t2, tg, wires=0).kraus_matrices()[0], expected_K0, atol=tol, rtol=0 ) - expected_K1 = np.sqrt(e1) * v1.reshape(2, 2, order="F") + expected_K1 = np.sqrt(e1) * v1.reshape((2, 2), order="F") assert np.allclose( op(pe, t1, t2, tg, wires=0).kraus_matrices()[1], expected_K1, atol=tol, rtol=0 ) - expected_K2 = np.sqrt(e2) * v2.reshape(2, 2, order="F") + expected_K2 = np.sqrt(e2) * v2.reshape((2, 2), order="F") assert np.allclose( op(pe, t1, t2, tg, wires=0).kraus_matrices()[2], expected_K2, atol=tol, rtol=0 ) - expected_K3 = np.sqrt(e3) * v3.reshape(2, 2, order="F") + expected_K3 = np.sqrt(e3) * v3.reshape((2, 2), order="F") assert np.allclose( op(pe, t1, t2, tg, wires=0).kraus_matrices()[3], expected_K3, atol=tol, rtol=0 ) @@ -1048,7 +1054,7 @@ def test_tg_le_0_invalid_parameter(self): channel.ThermalRelaxationError(0.3, 100e-6, 100e-6, -20e-9, wires=0).kraus_matrices() @pytest.mark.parametrize("angle", np.linspace(0, 2 * np.pi, 7)) - def test_grad_thermal_relaxation_error(self, angle, tol): + def test_grad_thermal_relaxation_error(self, angle): """Test that gradient is computed correctly for different states. Channel grad recipes are independent of channel parameter""" diff --git a/tests/ops/test_cv_ops.py b/tests/ops/test_cv_ops.py index d6e7c03c901..5e69cd16aa3 100644 --- a/tests/ops/test_cv_ops.py +++ b/tests/ops/test_cv_ops.py @@ -16,12 +16,11 @@ """ # pylint: disable=protected-access,cell-var-from-loop -from scipy.linalg import block_diag import pytest +import numpy.testing as np_testing from pennylane import numpy as np from pennylane.operation import AnyWires -import numpy.testing as np_testing from pennylane.ops import cv from pennylane.wires import Wires @@ -83,7 +82,7 @@ def test_adjoint_cv_ops(self, op, size, tol): cv.Kerr(2.568, wires=2), ], ) - def test_adjoint_no_heisenberg_rep_defined(self, op, tol): + def test_adjoint_no_heisenberg_rep_defined(self, op): op_d = op.adjoint() assert op.parameters[0] == -op_d.parameters[0] diff --git a/tests/ops/test_snapshot.py b/tests/ops/test_snapshot.py index 723e77843bc..fbe1f382116 100644 --- a/tests/ops/test_snapshot.py +++ b/tests/ops/test_snapshot.py @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. """Unit tests for the Snapshot operation.""" +# pylint: disable=protected-access from pennylane import Snapshot import pennylane as qml diff --git a/tests/optimize/test_adagrad.py b/tests/optimize/test_adagrad.py index 020e88a023d..499351b0104 100644 --- a/tests/optimize/test_adagrad.py +++ b/tests/optimize/test_adagrad.py @@ -1,3 +1,19 @@ +# Copyright 2018-2023 Xanadu Quantum Technologies Inc. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +""" +Unit tests for the ``AdagradOptimizer``. +""" import pytest from pennylane import numpy as np @@ -50,11 +66,7 @@ def test_adagrad_optimizer_univar(self, x_start, tol): adag_opt = AdagradOptimizer(stepsize) univariate_funcs = [np.sin, lambda x: np.exp(x / 10.0), lambda x: x**2] - grad_uni_fns = [ - lambda x: np.cos(x), - lambda x: np.exp(x / 10.0) / 10.0, - lambda x: 2 * x, - ] + grad_uni_fns = [np.cos, lambda x: np.exp(x / 10.0) / 10.0, lambda x: 2 * x] for gradf, f in zip(grad_uni_fns, univariate_funcs): adag_opt.reset() diff --git a/tests/optimize/test_adam.py b/tests/optimize/test_adam.py index 89214f67f66..8fc14334a4f 100644 --- a/tests/optimize/test_adam.py +++ b/tests/optimize/test_adam.py @@ -154,9 +154,9 @@ def test_adam_optimizer_properties(self): adam_opt = AdamOptimizer(stepsize, beta1=gamma, beta2=delta) # check if None is returned when accumulation is empty - assert adam_opt.fm == None - assert adam_opt.sm == None - assert adam_opt.t == None + assert adam_opt.fm is None + assert adam_opt.sm is None + assert adam_opt.t is None # Do some calculations to fill accumulation adam_opt.step(np.sin, np.random.rand(1)) diff --git a/tests/optimize/test_adaptive.py b/tests/optimize/test_adaptive.py index 48bf2e2e554..24b8ac05876 100644 --- a/tests/optimize/test_adaptive.py +++ b/tests/optimize/test_adaptive.py @@ -14,6 +14,7 @@ """ Unit tests for the ``AdaptiveOptimizer``. """ +import copy import pytest import pennylane as qml from pennylane import numpy as np @@ -53,12 +54,13 @@ def initial_circuit(): ) def test_private_circuit(circuit, params, gates, energy_ref): r"""Test that _circuit returns the correct output.""" + # pylint: disable=protected-access qnode = qml.QNode(qml.AdaptiveOptimizer._circuit, dev) energy = qnode(params, gates, circuit.func) assert np.allclose(energy, energy_ref) -pool = [ +pool_exc = [ qml.DoubleExcitation(np.array(0.0), wires=[0, 1, 2, 3]), qml.DoubleExcitation(np.array(0.0), wires=[0, 1, 2, 5]), qml.DoubleExcitation(np.array(0.0), wires=[0, 1, 3, 4]), @@ -73,7 +75,7 @@ def test_private_circuit(circuit, params, gates, energy_ref): @pytest.mark.parametrize( "circuit, energy_ref, pool", [ - (initial_circuit, energy_first_step, pool), + (initial_circuit, energy_first_step, pool_exc), ], ) def test_step(circuit, energy_ref, pool): @@ -84,29 +86,17 @@ def test_step(circuit, energy_ref, pool): assert np.allclose(energy, energy_ref) -pool = [ - qml.DoubleExcitation(np.array(0.0), wires=[0, 1, 2, 3]), - qml.DoubleExcitation(np.array(0.0), wires=[0, 1, 2, 5]), - qml.DoubleExcitation(np.array(0.0), wires=[0, 1, 3, 4]), - qml.DoubleExcitation(np.array(0.0), wires=[0, 1, 4, 5]), - qml.SingleExcitation(np.array(0.0), wires=[0, 2]), - qml.SingleExcitation(np.array(0.0), wires=[0, 4]), - qml.SingleExcitation(np.array(0.0), wires=[1, 3]), - qml.SingleExcitation(np.array(0.0), wires=[1, 5]), -] - - @pytest.mark.parametrize( "circuit, energy_ref, pool", [ - (initial_circuit, energy_h3p, pool), + (initial_circuit, energy_h3p, pool_exc), ], ) def test_step_and_cost_drain(circuit, energy_ref, pool): """Test that step_and_cost function returns the correct results when drain_pool is True.""" opt = qml.AdaptiveOptimizer() - for i in range(4): - circuit, energy, gradient = opt.step_and_cost(circuit, pool, drain_pool=True) + for _ in range(4): + circuit, energy, _ = opt.step_and_cost(circuit, copy.copy(pool), drain_pool=True) _ = circuit() selected_excitations = [op.wires for op in circuit.tape.operations[1:]] @@ -116,31 +106,19 @@ def test_step_and_cost_drain(circuit, energy_ref, pool): assert len(set(selected_excitations)) == len(selected_excitations) -pool = [ - qml.DoubleExcitation(np.array(0.0), wires=[0, 1, 2, 3]), - qml.DoubleExcitation(np.array(0.0), wires=[0, 1, 2, 5]), - qml.DoubleExcitation(np.array(0.0), wires=[0, 1, 3, 4]), - qml.DoubleExcitation(np.array(0.0), wires=[0, 1, 4, 5]), - qml.SingleExcitation(np.array(0.0), wires=[0, 2]), - qml.SingleExcitation(np.array(0.0), wires=[0, 4]), - qml.SingleExcitation(np.array(0.0), wires=[1, 3]), - qml.SingleExcitation(np.array(0.0), wires=[1, 5]), -] - - @pytest.mark.parametrize( "circuit, energy_ref, pool", [ - (initial_circuit, energy_h3p, pool), + (initial_circuit, energy_h3p, pool_exc), ], ) def test_step_and_cost_nodrain(circuit, energy_ref, pool): """Test that step_and_cost function returns the correct results when drain_pool is False.""" opt = qml.AdaptiveOptimizer() - for i in range(4): - circuit, energy, gradient = opt.step_and_cost(circuit, pool, drain_pool=False) + for _ in range(4): + circuit, energy, __ = opt.step_and_cost(circuit, pool, drain_pool=False) - _ = circuit() + circuit() selected_excitations = [op.wires for op in circuit.tape.operations[1:]] assert np.allclose(energy, energy_ref, rtol=1e-4) @@ -148,29 +126,13 @@ def test_step_and_cost_nodrain(circuit, energy_ref, pool): assert len(set(selected_excitations)) < len(selected_excitations) -@pytest.mark.parametrize( - "circuit", - [ - (initial_circuit), - ], -) +@pytest.mark.parametrize("circuit", [(initial_circuit)]) def test_largest_gradient(circuit): """Test that step function selects the gate with the largest gradient.""" - pool = [ - qml.DoubleExcitation(np.array(0.0), wires=[0, 1, 2, 3]), - qml.DoubleExcitation(np.array(0.0), wires=[0, 1, 2, 5]), - qml.DoubleExcitation(np.array(0.0), wires=[0, 1, 3, 4]), - qml.DoubleExcitation(np.array(0.0), wires=[0, 1, 4, 5]), - qml.SingleExcitation(np.array(0.0), wires=[0, 2]), - qml.SingleExcitation(np.array(0.0), wires=[0, 4]), - qml.SingleExcitation(np.array(0.0), wires=[1, 3]), - qml.SingleExcitation(np.array(0.0), wires=[1, 5]), - ] - opt = qml.AdaptiveOptimizer() - circuit = opt.step(circuit, pool) - _ = circuit() + circuit = opt.step(circuit, pool_exc) + circuit() selected_gate = circuit.tape.operations[-1] # the reference gate is obtained manually @@ -188,7 +150,7 @@ def test_append_gate(circuit): param = np.array([0.0]) gate = qml.DoubleExcitation(np.array(0.0), wires=[0, 1, 2, 3]) - final_circuit = qml.optimize.adaptive.append_gate(param, [gate])(initial_circuit.func) + final_circuit = qml.optimize.adaptive.append_gate(param, [gate])(circuit.func) qnode = qml.QNode(final_circuit, dev) _ = qnode() @@ -232,7 +194,7 @@ def circuit(): return qml.expval(qml.PauliZ(0)) opt = qml.AdaptiveOptimizer() - circuit, _, _ = opt.step_and_cost(circuit, pool) + circuit, _, _ = opt.step_and_cost(circuit, pool_exc) assert circuit.interface == interface assert circuit.diff_method == diff_method diff --git a/tests/optimize/test_gradient_descent.py b/tests/optimize/test_gradient_descent.py index 6c6def1b912..b0aa2fef29a 100644 --- a/tests/optimize/test_gradient_descent.py +++ b/tests/optimize/test_gradient_descent.py @@ -21,7 +21,7 @@ from pennylane.optimize import GradientDescentOptimizer univariate = [ - (np.sin, lambda x: np.cos(x)), + (np.sin, np.cos), (lambda x: np.exp(x / 10.0), lambda x: np.exp(x / 10.0) / 10.0), (lambda x: x**2, lambda x: 2 * x), ] diff --git a/tests/optimize/test_momentum.py b/tests/optimize/test_momentum.py index 2ff5b0ed58d..4a8aa238f48 100644 --- a/tests/optimize/test_momentum.py +++ b/tests/optimize/test_momentum.py @@ -17,7 +17,7 @@ import pytest from pennylane import numpy as np -from pennylane.optimize import MomentumOptimizer, momentum +from pennylane.optimize import MomentumOptimizer class TestMomentumOptimizer: diff --git a/tests/optimize/test_nesterov_momentum.py b/tests/optimize/test_nesterov_momentum.py index e4aa1b49ff5..190a403e295 100644 --- a/tests/optimize/test_nesterov_momentum.py +++ b/tests/optimize/test_nesterov_momentum.py @@ -75,11 +75,7 @@ def test_nesterovmomentum_optimizer_univar(self, x_start, tol): nesmom_opt = NesterovMomentumOptimizer(stepsize, momentum=gamma) univariate_funcs = [np.sin, lambda x: np.exp(x / 10.0), lambda x: x**2] - grad_uni_fns = [ - lambda x: np.cos(x), - lambda x: np.exp(x / 10.0) / 10.0, - lambda x: 2 * x, - ] + grad_uni_fns = [np.cos, lambda x: np.exp(x / 10.0) / 10.0, lambda x: 2 * x] for gradf, f in zip(grad_uni_fns, univariate_funcs): nesmom_opt.reset() @@ -143,11 +139,7 @@ def test_nesterovmomentum_optimizer_usergrad(self, x_start, tol): nesmom_opt = NesterovMomentumOptimizer(stepsize, momentum=gamma) univariate_funcs = [np.sin, lambda x: np.exp(x / 10.0), lambda x: x**2] - grad_uni_fns = [ - lambda x: np.cos(x), - lambda x: np.exp(x / 10.0) / 10.0, - lambda x: 2 * x, - ] + grad_uni_fns = [np.cos, lambda x: np.exp(x / 10.0) / 10.0, lambda x: 2 * x] for gradf, f in zip(grad_uni_fns[::-1], univariate_funcs): nesmom_opt.reset() diff --git a/tests/optimize/test_optimize.py b/tests/optimize/test_optimize.py index 8ce72c259b5..12e1af4bea1 100644 --- a/tests/optimize/test_optimize.py +++ b/tests/optimize/test_optimize.py @@ -14,7 +14,7 @@ """ Unit tests for the :mod:`pennylane` optimizers. """ -# pylint: disable=redefined-outer-name +# pylint: disable=redefined-outer-name,too-few-public-methods import pytest import pennylane as qml @@ -49,6 +49,8 @@ def opt(opt_name): class TestOverOpts: """Tests keywords, multiple arguments, and non-training arguments in relevant optimizers""" + # pylint: disable=unused-argument + def test_kwargs(self, mocker, opt, opt_name, tol): """Test that the keywords get passed and alter the function""" @@ -62,12 +64,12 @@ def func(x, c=1.0): wrapper = func_wrapper() spy = mocker.spy(wrapper, "func") - x_new_two = opt.step(wrapper.func, x, c=2.0) + _ = opt.step(wrapper.func, x, c=2.0) self.reset(opt) args2, kwargs2 = spy.call_args_list[-1] - x_new_three_wc, cost_three = opt.step_and_cost(wrapper.func, x, c=3.0) + _, cost_three = opt.step_and_cost(wrapper.func, x, c=3.0) self.reset(opt) args3, kwargs3 = spy.call_args_list[-1] @@ -99,7 +101,7 @@ def func(x, y, z): self.reset(opt) args_called1, kwargs1 = spy.call_args_list[-1] # just take last call - x_new2, y_new2, z_new2 = opt.step(wrapper.func, x_new, y_new, z_new) + _ = opt.step(wrapper.func, x_new, y_new, z_new) self.reset(opt) args_called2, kwargs2 = spy.call_args_list[-1] # just take last call diff --git a/tests/optimize/test_optimize_shot_adaptive.py b/tests/optimize/test_optimize_shot_adaptive.py index d78e022bfb1..125bef5de33 100644 --- a/tests/optimize/test_optimize_shot_adaptive.py +++ b/tests/optimize/test_optimize_shot_adaptive.py @@ -12,9 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. """Tests for the shot adaptive optimizer""" +# pylint: disable=unused-argument import pytest from flaky import flaky -from scipy.stats import multinomial import pennylane as qml from pennylane import numpy as np @@ -36,7 +36,7 @@ def test_analytic_device_error(self): H = qml.Hamiltonian([0.3, 0.1], [qml.PauliX(0), qml.PauliZ(0)]) dev = qml.device("default.qubit", wires=1, shots=None) - def ansatz(x, **kwargs): + def ansatz(x): qml.RX(x, wires=0) expval_cost = catch_warn_ExpvalCost(ansatz, H, dev) @@ -109,6 +109,23 @@ def cost(x): assert isinstance(new_x, np.tensor) +def ansatz0(x, **kwargs): + qml.RX(x, wires=0) + + +def ansatz1(x, **kwargs): + qml.RX(x[0, 0], wires=0) + qml.RY(x[0, 1], wires=0) + qml.RZ(x[0, 2], wires=0) + qml.RX(x[1, 0], wires=0) + qml.RY(x[1, 1], wires=0) + qml.RZ(x[1, 2], wires=0) + + +def ansatz2(x, **kwargs): + qml.StronglyEntanglingLayers(x, wires=[0, 1]) + + class TestSingleShotGradientIntegration: """Integration tests to ensure that the single shot gradient is correctly computed for a variety of argument types.""" @@ -116,13 +133,11 @@ class TestSingleShotGradientIntegration: dev = qml.device("default.qubit", wires=1, shots=100) H = qml.Hamiltonian([1.0], [qml.PauliZ(0)]) - def ansatz(x, **kwargs): - qml.RX(x, wires=0) - - expval_cost = catch_warn_ExpvalCost(ansatz, H, dev) + expval_cost = catch_warn_ExpvalCost(ansatz0, H, dev) @qml.qnode(dev) def qnode(x): + # pylint: disable=no-self-argument qml.RX(x, wires=0) return qml.expval(qml.PauliZ(0)) @@ -131,6 +146,7 @@ def qnode(x): def test_single_argument_step(self, cost_fn, mocker, monkeypatch): """Test that a simple QNode with a single argument correctly performs an optimization step, and that the single-shot gradients generated have the correct shape""" + # pylint: disable=protected-access opt = qml.ShotAdaptiveOptimizer(min_shots=10) spy_single_shot_expval = mocker.spy(opt, "_single_shot_expval_gradients") @@ -184,21 +200,14 @@ def test_single_argument_step(self, cost_fn, mocker, monkeypatch): assert np.allclose(grad, np.mean(single_shot_grads[0][:5])) assert np.allclose(grad_variance, np.var(single_shot_grads[0][:5], ddof=1)) - def ansatz(x, **kwargs): - qml.RX(x[0, 0], wires=0) - qml.RY(x[0, 1], wires=0) - qml.RZ(x[0, 2], wires=0) - qml.RX(x[1, 0], wires=0) - qml.RY(x[1, 1], wires=0) - qml.RZ(x[1, 2], wires=0) - - expval_cost = catch_warn_ExpvalCost(ansatz, H, dev) + expval_cost = catch_warn_ExpvalCost(ansatz1, H, dev) qnode = expval_cost.qnodes[0] @pytest.mark.parametrize("cost_fn", [qnode, expval_cost]) def test_single_array_argument_step(self, cost_fn, mocker, monkeypatch): """Test that a simple QNode with a single array argument correctly performs an optimization step, and that the single-shot gradients generated have the correct shape""" + # pylint: disable=protected-access opt = qml.ShotAdaptiveOptimizer(min_shots=10) spy_single_shot_expval = mocker.spy(opt, "_single_shot_expval_gradients") spy_single_shot_qnodes = mocker.spy(opt, "_single_shot_qnode_gradients") @@ -264,10 +273,7 @@ def test_single_array_argument_step(self, cost_fn, mocker, monkeypatch): dev = qml.device("default.qubit", wires=2, shots=100) - def ansatz(x, **kwargs): - qml.StronglyEntanglingLayers(x, wires=[0, 1]) - - expval_cost = catch_warn_ExpvalCost(ansatz, H, dev) + expval_cost = catch_warn_ExpvalCost(ansatz2, H, dev) qnode = expval_cost.qnodes[0] @pytest.mark.parametrize("cost_fn", [qnode, expval_cost]) @@ -275,6 +281,7 @@ def test_padded_single_array_argument_step(self, cost_fn, mocker, monkeypatch): """Test that a simple QNode with a single array argument with extra dimensions correctly performs an optimization step, and that the single-shot gradients generated have the correct shape""" + # pylint: disable=protected-access opt = qml.ShotAdaptiveOptimizer(min_shots=10) spy_single_shot_expval = mocker.spy(opt, "_single_shot_expval_gradients") spy_single_shot_qnodes = mocker.spy(opt, "_single_shot_qnode_gradients") @@ -351,6 +358,7 @@ def test_padded_single_array_argument_step(self, cost_fn, mocker, monkeypatch): def test_multiple_argument_step(self, mocker, monkeypatch): """Test that a simple QNode with multiple scalar arguments correctly performs an optimization step, and that the single-shot gradients generated have the correct shape""" + # pylint: disable=protected-access dev = qml.device("default.qubit", wires=1, shots=100) @qml.qnode(dev) @@ -407,6 +415,7 @@ def circuit(x, y): def test_multiple_array_argument_step(self, mocker, monkeypatch): """Test that a simple QNode with multiple array arguments correctly performs an optimization step, and that the single-shot gradients generated have the correct shape""" + # pylint: disable=protected-access dev = qml.device("default.qubit", wires=1, shots=100) @qml.qnode(dev) @@ -530,7 +539,7 @@ def test_wrs_disabled(self, mocker): opt = qml.ShotAdaptiveOptimizer(min_shots=10, term_sampling=None) spy = mocker.spy(opt, "weighted_random_sampling") - new_weights = opt.step(expval_cost, weights) + opt.step(expval_cost, weights) spy.assert_not_called() def test_unknown_term_sampling_method(self): @@ -547,7 +556,7 @@ def test_unknown_term_sampling_method(self): with pytest.raises(ValueError, match="Unknown Hamiltonian term sampling method"): opt.step(expval_cost, weights) - def test_zero_shots(self, mocker, monkeypatch): + def test_zero_shots(self, mocker): """Test that, if the shot budget for a single term is 0, that the jacobian computation is skipped""" coeffs = [0.2, 0.1, 0.1] @@ -568,7 +577,7 @@ def test_zero_shots(self, mocker, monkeypatch): assert len(grads) == 1 assert grads[0].shape == (10, *weights.shape) - def test_single_shots(self, mocker, monkeypatch): + def test_single_shots(self, mocker): """Test that, if the shot budget for a single term is 1, that the number of dimensions for the returned Jacobian is expanded""" coeffs = [0.2, 0.1, 0.1] @@ -614,7 +623,7 @@ def circuit(x): loss = initial_loss opt = qml.ShotAdaptiveOptimizer(min_shots=10) - for i in range(100): + for _ in range(100): params = opt.step(circuit, params) loss = circuit(params) @@ -647,7 +656,7 @@ def ansatz(x, **kwargs): loss = initial_loss opt = qml.ShotAdaptiveOptimizer(min_shots=10) - for i in range(100): + for _ in range(100): params = opt.step(cost, params) loss = cost(params) @@ -677,7 +686,7 @@ def circuit(x): opt = qml.ShotAdaptiveOptimizer(min_shots=10) - for i in range(100): + for _ in range(100): params, res = opt.step_and_cost(circuit, params) assert np.allclose(res, -1, atol=tol, rtol=0) @@ -698,7 +707,7 @@ def ansatz(x, **kwargs): params = np.array([0.1, 0.3], requires_grad=True) opt = qml.ShotAdaptiveOptimizer(min_shots=10) - for i in range(100): + for _ in range(100): params, res = opt.step_and_cost(circuit, params) assert np.allclose(res, -1, atol=tol, rtol=0) diff --git a/tests/optimize/test_qng.py b/tests/optimize/test_qng.py index cdd67b55897..b541b660999 100644 --- a/tests/optimize/test_qng.py +++ b/tests/optimize/test_qng.py @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. """Tests for the QNG optimizer""" +# pylint: disable=too-few-public-methods import pytest import scipy as sp @@ -49,7 +50,7 @@ def cost(a): class TestOptimize: """Test basic optimization integration""" - def test_step_and_cost_autograd(self, tol): + def test_step_and_cost_autograd(self): """Test that the correct cost and step is returned via the step_and_cost method for the QNG optimizer""" dev = qml.device("default.qubit", wires=1) @@ -72,7 +73,7 @@ def circuit(params): assert np.allclose(step1, expected_step) assert np.allclose(step2, expected_step) - def test_step_and_cost_autograd_with_gen_hamiltonian(self, tol): + def test_step_and_cost_autograd_with_gen_hamiltonian(self): """Test that the correct cost and step is returned via the step_and_cost method for the QNG optimizer when the generator of an operator is a Hamiltonian""" @@ -97,7 +98,7 @@ def circuit(params): assert np.allclose(step1, expected_step) assert np.allclose(step2, expected_step) - def test_step_and_cost_with_grad_fn_grouped_input(self, tol): + def test_step_and_cost_with_grad_fn_grouped_input(self): """Test that the correct cost and update is returned via the step_and_cost method for the QNG optimizer when providing an explicit grad_fn. Using a circuit with a single input containing all parameters.""" @@ -120,7 +121,7 @@ def circuit(params): # With more custom gradient function, forward has to be computed explicitly. grad_fn = lambda param: np.array(qml.grad(circuit)(param)) step3, cost2 = opt.step_and_cost(circuit, var, grad_fn=grad_fn) - step4 = opt.step(circuit, var, grad_fn=grad_fn) + opt.step(circuit, var, grad_fn=grad_fn) expected_step = var - opt.stepsize * 4 * grad_fn(var) expected_cost = circuit(var) @@ -130,7 +131,7 @@ def circuit(params): assert np.isclose(cost2, expected_cost) @pytest.mark.skip("QNGOptimizer is not yet implemented for split inputs.") - def test_step_and_cost_with_grad_fn_split_input(self, tol): + def test_step_and_cost_with_grad_fn_split_input(self): """Test that the correct cost and update is returned via the step_and_cost method for the QNG optimizer when providing an explicit grad_fn. Using a circuit with multiple inputs containing the parameters.""" @@ -153,7 +154,7 @@ def circuit(params_0, params_1): # With more custom gradient function, forward has to be computed explicitly. grad_fn = lambda params_0, params_1: np.array(qml.grad(circuit)(params_0, params_1)) step3, cost2 = opt.step_and_cost(circuit, *var, grad_fn=grad_fn) - step4 = opt.step(circuit, *var, grad_fn=grad_fn) + opt.step(circuit, *var, grad_fn=grad_fn) expected_step = var - opt.stepsize * 4 * grad_fn(*var) expected_cost = circuit(*var) @@ -188,7 +189,7 @@ def gradient(params): theta = init_params # optimization for 200 steps total - for t in range(num_steps): + for _ in range(num_steps): theta_new = opt.step(circuit, theta) # check metric tensor @@ -238,7 +239,7 @@ def gradient(params): opt = qml.QNGOptimizer(eta) # optimization for 200 steps total - for t in range(num_steps): + for _ in range(num_steps): theta = np.array([x, y]) x, y = opt.step(circuit, x, y) diff --git a/tests/optimize/test_qnspsa.py b/tests/optimize/test_qnspsa.py index b02b388bb89..e72c87e4a31 100644 --- a/tests/optimize/test_qnspsa.py +++ b/tests/optimize/test_qnspsa.py @@ -14,12 +14,13 @@ """ Unit tests for the ``QNSPSAOptimizer`` """ +# pylint: disable=protected-access +from copy import deepcopy import pytest +from scipy.linalg import sqrtm import pennylane as qml from pennylane import numpy as np -from copy import deepcopy -from scipy.linalg import sqrtm def get_single_input_qnode(): diff --git a/tests/optimize/test_rmsprop.py b/tests/optimize/test_rmsprop.py index 01ce351d32b..7e11b71c3cc 100644 --- a/tests/optimize/test_rmsprop.py +++ b/tests/optimize/test_rmsprop.py @@ -62,11 +62,7 @@ def test_rmsprop_optimizer_univar(self, x_start, tol): rms_opt = RMSPropOptimizer(stepsize, decay=gamma) univariate_funcs = [np.sin, lambda x: np.exp(x / 10.0), lambda x: x**2] - grad_uni_fns = [ - lambda x: np.cos(x), - lambda x: np.exp(x / 10.0) / 10.0, - lambda x: 2 * x, - ] + grad_uni_fns = [np.cos, lambda x: np.exp(x / 10.0) / 10.0, lambda x: 2 * x] for gradf, f in zip(grad_uni_fns, univariate_funcs): rms_opt.reset() diff --git a/tests/optimize/test_rotoselect.py b/tests/optimize/test_rotoselect.py index 3b128af237a..aeed87536a7 100644 --- a/tests/optimize/test_rotoselect.py +++ b/tests/optimize/test_rotoselect.py @@ -116,10 +116,8 @@ def test_rotoselect_optimizer_raises(self): """Tests that step my raise an error.""" rotoselect_opt = RotoselectOptimizer() - def cost_fn(params, generators): - Z_1, Y_2 = circuit_1(params, generators=generators) - X_1 = circuit_2(params, generators=generators) - return 0.5 * Y_2 + 0.8 * Z_1 - 0.2 * X_1 + def cost_fn(): + return None with pytest.raises(ValueError, match="must be equal to the number of generators"): rotoselect_opt.step(cost_fn, [0.2], [qml.PauliX, qml.PauliZ]) @@ -154,9 +152,7 @@ def cost_fn(params, generators, shift=0.0): X_1 = circuit_2(params, generators=generators) return 0.5 * (Y_2 - shift) ** 2 + 0.8 * (Z_1 - shift) ** 2 - 0.2 * (X_1 - shift) ** 2 - params_new, _, res_new = rotoselect_opt.step_and_cost( - cost_fn, x_start, generators, shift=0.0 - ) + params_new, *_ = rotoselect_opt.step_and_cost(cost_fn, x_start, generators, shift=0.0) params_new2, _, res_new2 = rotoselect_opt.step_and_cost( cost_fn, x_start, generators, shift=1.0 ) diff --git a/tests/optimize/test_rotosolve.py b/tests/optimize/test_rotosolve.py index 32fe4957eda..f5b35beecd0 100644 --- a/tests/optimize/test_rotosolve.py +++ b/tests/optimize/test_rotosolve.py @@ -14,6 +14,7 @@ """ Unit tests for the ``RotosolveOptimizer``. """ +# pylint: disable=too-many-arguments,too-few-public-methods import functools import pytest from scipy.optimize import shgo @@ -83,14 +84,17 @@ def test_error_missing_frequency_info_single_par(): for one of the function arguments.""" opt = RotosolveOptimizer() - fun = lambda x: qml.math.sum(x) + + def sum_named_arg(x): + return qml.math.sum(x) + x = np.arange(4, requires_grad=True) nums_frequency = {"x": {(0,): 1, (1,): 1}} spectra = {"x": {(0,): [0.0, 1.0], (2,): [0.0, 1.0]}} # For the first three entries either nums_frequency or spectra is provided with pytest.raises(ValueError, match=r"was provided for the entry \(3,\)"): - opt.step(fun, x, nums_frequency=nums_frequency, spectra=spectra) + opt.step(sum_named_arg, x, nums_frequency=nums_frequency, spectra=spectra) def test_error_no_trainable_args(): @@ -99,8 +103,6 @@ def test_error_no_trainable_args(): opt = RotosolveOptimizer() fun = lambda x, y, z: 1.0 x = np.arange(4, requires_grad=False) - y = np.arange(2, requires_grad=False) - z = [1.2, -0.4, -9.1] with pytest.raises(ValueError, match="Found no parameters to optimize."): opt.step(fun, x, nums_frequency=None, spectra=None) @@ -188,16 +190,17 @@ def custom_optimizer(fun, **kwargs): list(zip(substep_optimizers, all_substep_kwargs)), ) class TestWithClassicalFunction: + # pylint: disable=unused-argument def test_number_of_function_calls( self, fun, x_min, param, nums_freq, exp_num_calls, substep_optimizer, substep_kwargs ): """Tests that per parameter 2R+1 function calls are used for an update step.""" - global num_calls + # pylint: disable=too-many-arguments num_calls = 0 @functools.wraps(fun) def _fun(*args, **kwargs): - global num_calls + nonlocal num_calls num_calls += 1 return fun(*args, **kwargs) @@ -206,14 +209,14 @@ def _fun(*args, **kwargs): # Make only the first argument trainable param = (np.array(param[0], requires_grad=True),) + param[1:] # Only one argument is marked as trainable -> Expect only the executions for that arg - new_param = opt.step(_fun, *param, nums_frequency=nums_freq) + opt.step(_fun, *param, nums_frequency=nums_freq) exp_num_calls_single_trainable = sum(2 * num + 1 for num in nums_freq["x"].values()) assert num_calls == exp_num_calls_single_trainable num_calls = 0 # Parameters are now marked as trainable -> Expect full number of executions param = tuple(np.array(p, requires_grad=True) for p in param) - new_param = opt.step(_fun, *param, nums_frequency=nums_freq) + opt.step(_fun, *param, nums_frequency=nums_freq) assert num_calls == exp_num_calls def test_single_step_convergence( diff --git a/tests/optimize/test_spsa.py b/tests/optimize/test_spsa.py index ba26d74610c..3d8c54d35a1 100644 --- a/tests/optimize/test_spsa.py +++ b/tests/optimize/test_spsa.py @@ -239,8 +239,8 @@ def quant_fun_mdarr(var): multiplier = ck * delta thetaplus[index] = arg + multiplier thetaminus[index] = arg - multiplier - yplus = quant_fun_mdarr(*thetaplus) - yminus = quant_fun_mdarr(*thetaminus) + yplus = np.array([quant_fun_mdarr(p) for p in thetaplus]) + yminus = np.array([quant_fun_mdarr(p) for p in thetaminus]) y_pm.append(yplus - yminus) # choose one delta d = 0 diff --git a/tests/pauli/grouping/test_pauli_group_observables.py b/tests/pauli/grouping/test_pauli_group_observables.py index ec5b690e44a..69c56117383 100644 --- a/tests/pauli/grouping/test_pauli_group_observables.py +++ b/tests/pauli/grouping/test_pauli_group_observables.py @@ -227,7 +227,7 @@ class TestGroupObservables: Tests for ``group_observables`` function using QWC, commuting, and anticommuting partitioning. """ - qwc_tuples = [(obs, sol) for obs, sol in zip(observables_list, qwc_sols)] + qwc_tuples = list(zip(observables_list, qwc_sols)) @pytest.mark.parametrize("observables,qwc_partitions_sol", qwc_tuples) def test_qwc_partitioning(self, observables, qwc_partitions_sol): @@ -238,14 +238,14 @@ def test_qwc_partitioning(self, observables, qwc_partitions_sol): assert len(qwc_partitions) == n_partitions # assert each partition is of the correct length: assert all( - [len(qwc_partitions[i]) == len(qwc_partitions_sol[i]) for i in range(n_partitions)] + len(part) == len(part_sol) for part, part_sol in zip(qwc_partitions, qwc_partitions_sol) ) # assert each partition contains the same Pauli terms as the solution partition: for i, partition in enumerate(qwc_partitions): for j, pauli in enumerate(partition): assert are_identical_pauli_words(pauli, qwc_partitions_sol[i][j]) - com_tuples = [(obs, sol) for obs, sol in zip(observables_list, commuting_sols)] + com_tuples = list(zip(observables_list, commuting_sols)) @pytest.mark.parametrize("observables,com_partitions_sol", com_tuples) def test_commuting_partitioning(self, observables, com_partitions_sol): @@ -255,15 +255,13 @@ def test_commuting_partitioning(self, observables, com_partitions_sol): n_partitions = len(com_partitions_sol) assert len(com_partitions) == n_partitions # assert each partition is of the correct length: - assert all( - [len(com_partitions[i]) == len(com_partitions_sol[i]) for i in range(n_partitions)] - ) + assert all(len(p) == len(p_sol) for p, p_sol in zip(com_partitions, com_partitions_sol)) # assert each partition contains the same Pauli terms as the solution partition: for i, partition in enumerate(com_partitions): for j, pauli in enumerate(partition): assert are_identical_pauli_words(pauli, com_partitions_sol[i][j]) - anticom_tuples = [(obs, sols) for obs, sols in zip(observables_list, anticommuting_sols)] + anticom_tuples = list(zip(observables_list, anticommuting_sols)) @pytest.mark.parametrize("observables,anticom_partitions_sol", anticom_tuples) def test_anticommuting_partitioning(self, observables, anticom_partitions_sol): @@ -274,10 +272,7 @@ def test_anticommuting_partitioning(self, observables, anticom_partitions_sol): assert len(anticom_partitions) == n_partitions # assert each partition is of the correct length: assert all( - [ - len(anticom_partitions[i]) == len(anticom_partitions_sol[i]) - for i in range(n_partitions) - ] + len(p) == len(p_sol) for p, p_sol in zip(anticom_partitions, anticom_partitions_sol) ) # assert each partition contains the same Pauli terms as the solution partition: for i, partition in enumerate(anticom_partitions): @@ -295,6 +290,7 @@ def test_group_observables_exception(self): def test_binary_repr_custom_wire_map(self): """Tests that the ``binary_repr`` method sets a custom wire map correctly.""" + # pylint: disable=protected-access observables = [Identity("alice"), Identity("bob"), Identity("charlie")] grouping_instance = PauliGroupingStrategy(observables, "anticommuting") diff --git a/tests/pauli/grouping/test_pauli_optimize_measurements.py b/tests/pauli/grouping/test_pauli_optimize_measurements.py index 300a3b426cb..7ae33c6ea05 100644 --- a/tests/pauli/grouping/test_pauli_optimize_measurements.py +++ b/tests/pauli/grouping/test_pauli_optimize_measurements.py @@ -79,10 +79,8 @@ def test_optimize_measurements_qwc_generic_case(self, observables, diagonalized_ assert len(diagonalized_groupings) == n_partitions # assert each partition is of the correct length: assert all( - [ - len(diagonalized_groupings[i]) == len(diagonalized_groupings_sol[i]) - for i in range(n_partitions) - ] + len(diagonalized_groupings[i]) == len(diagonalized_groupings_sol[i]) + for i in range(n_partitions) ) # assert each partition contains the same Pauli terms as the solution partition: for i, partition in enumerate(diagonalized_groupings): @@ -95,18 +93,13 @@ def test_optimize_measurements_qwc_generic_case_with_coefficients(self): observables = [PauliY(0), PauliX(0) @ PauliX(1), PauliZ(1)] coefficients = [1.43, 4.21, 0.97] - diagonalized_groupings_sol = [ - [PauliZ(wires=[0]) @ PauliZ(wires=[1])], - [PauliZ(wires=[0]), PauliZ(wires=[1])], - ] - grouped_coeffs_sol = [[4.21], [1.43, 0.97]] grouped_coeffs = optimize_measurements( observables, coefficients, grouping="qwc", colouring_method="rlf" )[2] - assert len(grouped_coeffs) == len(grouped_coeffs) + assert len(grouped_coeffs) == len(grouped_coeffs_sol) assert all( np.allclose(grouped_coeffs[i], grouped_coeffs_sol[i]) @@ -131,8 +124,6 @@ def test_optimize_measurements_qwc_term_multiple_times(self, obs): """ coefficients = [1.43, 4.21] - diagonalized_groupings_sol = [obs] - grouped_coeffs_sol = [[1.43, 4.21]] grouped_coeffs = optimize_measurements( diff --git a/tests/pauli/test_conversion.py b/tests/pauli/test_conversion.py index 8119ad3ce8f..d42642a8e8d 100644 --- a/tests/pauli/test_conversion.py +++ b/tests/pauli/test_conversion.py @@ -52,7 +52,7 @@ def test_hide_identity_true(self): """Tests that there are no Identity observables in the tensor products when hide_identity=True""" H = np.array(np.diag([0, 0, 0, 1])) - coeff, obs_list = qml.pauli_decompose(H, hide_identity=True).terms() + _, obs_list = qml.pauli_decompose(H, hide_identity=True).terms() tensors = filter(lambda obs: isinstance(obs, Tensor), obs_list) for tensor in tensors: @@ -63,7 +63,7 @@ def test_hide_identity_true(self): def test_hide_identity_true_all_identities(self): """Tests that the all identity operator remains even with hide_identity = True.""" H = np.eye(4) - coeff, obs_list = qml.pauli_decompose(H, hide_identity=True).terms() + _, obs_list = qml.pauli_decompose(H, hide_identity=True).terms() tensors = filter(lambda obs: isinstance(obs, Tensor), obs_list) for tensor in tensors: @@ -76,14 +76,14 @@ def test_observable_types(self, hamiltonian, hide_identity): the identity matrix, and Pauli matrices.""" allowed_obs = (Tensor, Identity, PauliX, PauliY, PauliZ) - decomposed_coeff, decomposed_obs = qml.pauli_decompose(hamiltonian, hide_identity).terms() - assert all([isinstance(o, allowed_obs) for o in decomposed_obs]) + _, decomposed_obs = qml.pauli_decompose(hamiltonian, hide_identity).terms() + assert all(isinstance(o, allowed_obs) for o in decomposed_obs) @pytest.mark.parametrize("hamiltonian", test_hamiltonians) def test_result_length(self, hamiltonian): """Tests that tensors are composed of a number of terms equal to the number of qubits.""" - decomposed_coeff, decomposed_obs = qml.pauli_decompose(hamiltonian).terms() + _, decomposed_obs = qml.pauli_decompose(hamiltonian).terms() n = int(np.log2(len(hamiltonian))) tensors = filter(lambda obs: isinstance(obs, Tensor), decomposed_obs) @@ -130,12 +130,12 @@ def test_wire_error(self): with pytest.raises( ValueError, match="number of wires 1 is not compatible with number of qubits 2" ): - h = qml.pauli_decompose(hamiltonian, wire_order=wire_order) + qml.pauli_decompose(hamiltonian, wire_order=wire_order) with pytest.raises( ValueError, match="number of wires 1 is not compatible with number of qubits 2" ): - ps = qml.pauli_decompose(hamiltonian, pauli=True, wire_order=wire_order) + qml.pauli_decompose(hamiltonian, pauli=True, wire_order=wire_order) class TestPauliSentence: diff --git a/tests/pauli/test_pauli_arithmetic.py b/tests/pauli/test_pauli_arithmetic.py index 54baaaa2ae4..2b50f997949 100644 --- a/tests/pauli/test_pauli_arithmetic.py +++ b/tests/pauli/test_pauli_arithmetic.py @@ -12,9 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. """Unit Tests for the PauliWord and PauliSentence classes""" +# pylint: disable=too-many-public-methods import pickle -import pytest from copy import copy, deepcopy +import pytest from scipy import sparse import pennylane as qml @@ -119,14 +120,14 @@ def test_str(self, pw, str_rep): (pw3, pw4, pw3, 1.0), ) - @pytest.mark.parametrize("pw1, pw2, result_pw, coeff", tup_pws_mult) - def test_mul(self, pw1, pw2, result_pw, coeff): - copy_pw1 = copy(pw1) - copy_pw2 = copy(pw2) + @pytest.mark.parametrize("word1, word2, result_pw, coeff", tup_pws_mult) + def test_mul(self, word1, word2, result_pw, coeff): + copy_pw1 = copy(word1) + copy_pw2 = copy(word2) - assert pw1 * pw2 == (result_pw, coeff) - assert copy_pw1 == pw1 # check for mutation of the pw themselves - assert copy_pw2 == pw2 + assert word1 * word2 == (result_pw, coeff) + assert copy_pw1 == word1 # check for mutation of the pw themselves + assert copy_pw2 == word2 tup_pws_mat_wire = ( (pw1, [2, 0, 1], np.kron(np.kron(matY, matI), matX)), @@ -269,13 +270,13 @@ def test_set_items(self): tup_ps_str = ( ( ps1, - "1.23 * X(1) @ Y(2)\n" "+ 4j * X(a) @ X(b) @ Z(c)\n" "+ -0.5 * Z(0) @ Z(b) @ Z(c)", + "1.23 * X(1) @ Y(2)\n+ 4j * X(a) @ X(b) @ Z(c)\n+ -0.5 * Z(0) @ Z(b) @ Z(c)", ), ( ps2, - "-1.23 * X(1) @ Y(2)\n" "+ (-0-4j) * X(a) @ X(b) @ Z(c)\n" "+ 0.5 * Z(0) @ Z(b) @ Z(c)", + "-1.23 * X(1) @ Y(2)\n+ (-0-4j) * X(a) @ X(b) @ Z(c)\n+ 0.5 * Z(0) @ Z(b) @ Z(c)", ), - (ps3, "-0.5 * Z(0) @ Z(b) @ Z(c)\n" "+ 1 * I"), + (ps3, "-0.5 * Z(0) @ Z(b) @ Z(c)\n+ 1 * I"), (ps4, "1 * I"), (ps5, "0 * I"), ) @@ -353,18 +354,18 @@ def test_copy(self, ps): ), ) - @pytest.mark.parametrize("ps1, ps2, res", tup_ps_mult) - def test_mul(self, ps1, ps2, res): + @pytest.mark.parametrize("string1, string2, res", tup_ps_mult) + def test_mul(self, string1, string2, res): """Test that the correct result of multiplication is produced.""" - copy_ps1 = copy(ps1) - copy_ps2 = copy(ps2) + copy_ps1 = copy(string1) + copy_ps2 = copy(string2) - simplified_product = ps1 * ps2 + simplified_product = string1 * string2 simplified_product.simplify() assert simplified_product == res - assert ps1 == copy_ps1 - assert ps2 == copy_ps2 + assert string1 == copy_ps1 + assert string2 == copy_ps2 tup_ps_add = ( # computed by hand (ps1, ps1, PauliSentence({pw1: 2.46, pw2: 8j, pw3: -1})), @@ -373,18 +374,18 @@ def test_mul(self, ps1, ps2, res): (ps2, ps5, ps2), ) - @pytest.mark.parametrize("ps1, ps2, result", tup_ps_add) - def test_add(self, ps1, ps2, result): + @pytest.mark.parametrize("string1, string2, result", tup_ps_add) + def test_add(self, string1, string2, result): """Test that the correct result of addition is produced.""" - copy_ps1 = copy(ps1) - copy_ps2 = copy(ps2) + copy_ps1 = copy(string1) + copy_ps2 = copy(string2) - simplified_product = ps1 + ps2 + simplified_product = string1 + string2 simplified_product.simplify() assert simplified_product == result - assert ps1 == copy_ps1 - assert ps2 == copy_ps2 + assert string1 == copy_ps1 + assert string2 == copy_ps2 ps_match = ( (ps4, "Can't get the matrix of an empty PauliWord."), @@ -592,9 +593,9 @@ def test_hamiltonian_wire_order(self): def test_pickling(self): """Check that paulisentences can be pickled and unpickled.""" - pw1 = PauliWord({2: "X", 3: "Y", 4: "Z"}) - pw2 = PauliWord({2: "Y", 3: "Z"}) - ps = PauliSentence({pw1: 1.5, pw2: -0.5}) + word1 = PauliWord({2: "X", 3: "Y", 4: "Z"}) + word2 = PauliWord({2: "Y", 3: "Z"}) + ps = PauliSentence({word1: 1.5, word2: -0.5}) serialization = pickle.dumps(ps) new_ps = pickle.loads(serialization) diff --git a/tests/pauli/test_pauli_utils.py b/tests/pauli/test_pauli_utils.py index f1c00eb095d..68f58c9cfb3 100644 --- a/tests/pauli/test_pauli_utils.py +++ b/tests/pauli/test_pauli_utils.py @@ -14,6 +14,7 @@ """ Unit tests for the :mod:`pauli` utility functions in ``pauli/utils.py``. """ +# pylint: disable=too-few-public-methods,too-many-public-methods import numpy as np import pytest @@ -196,7 +197,6 @@ def test_observables_to_binary_matrix_n_qubits_arg(self): def test_is_qwc(self): """Determining if two Pauli words are qubit-wise commuting.""" - n_qubits = 3 wire_map = {0: 0, "a": 1, "b": 2} p1_vec = pauli_to_binary(PauliX(0) @ PauliY("a"), wire_map=wire_map) p2_vec = pauli_to_binary(PauliX(0) @ Identity("a") @ PauliX("b"), wire_map=wire_map) @@ -540,7 +540,7 @@ def test_one_qubit_pauli_group_integer_wire_map(self): expected_pg_1 = [Identity(0), PauliZ(0), PauliX(0), PauliY(0)] pg_1 = list(pauli_group(1)) - assert all([expected.compare(obtained) for expected, obtained in zip(expected_pg_1, pg_1)]) + assert all(expected.compare(obtained) for expected, obtained in zip(expected_pg_1, pg_1)) def test_one_qubit_pauli_group_valid_float_input(self): """Test that the single-qubit Pauli group is constructed correctly when a float @@ -548,7 +548,7 @@ def test_one_qubit_pauli_group_valid_float_input(self): expected_pg_1 = [Identity(0), PauliZ(0), PauliX(0), PauliY(0)] pg_1 = list(pauli_group(1.0)) - assert all([expected.compare(obtained) for expected, obtained in zip(expected_pg_1, pg_1)]) + assert all(expected.compare(obtained) for expected, obtained in zip(expected_pg_1, pg_1)) def test_one_qubit_pauli_group_string_wire_map(self): """Test that the single-qubit Pauli group is constructed correctly with a wire @@ -562,12 +562,7 @@ def test_one_qubit_pauli_group_string_wire_map(self): PauliY("qubit"), ] pg_1_wires = list(pauli_group(1, wire_map=wire_map)) - assert all( - [ - expected.compare(obtained) - for expected, obtained in zip(expected_pg_1_wires, pg_1_wires) - ] - ) + assert all(exp.compare(ob) for exp, ob in zip(expected_pg_1_wires, pg_1_wires)) def test_two_qubit_pauli_group(self): """Test that the two-qubit Pauli group is constructed correctly.""" @@ -594,7 +589,7 @@ def test_two_qubit_pauli_group(self): ] pg_2 = list(pauli_group(2, wire_map=wire_map)) - assert all([expected.compare(obtained) for expected, obtained in zip(expected_pg_2, pg_2)]) + assert all(expected.compare(obtained) for expected, obtained in zip(expected_pg_2, pg_2)) @pytest.mark.parametrize( "pauli_word_1,pauli_word_2,wire_map,expected_product", @@ -810,10 +805,8 @@ def test_qwc_rotation(self, pauli_ops, qwc_rot_sol): qwc_rot = qwc_rotation(pauli_ops) assert all( - [ - self.are_identical_rotation_gates(qwc_rot[i], qwc_rot_sol[i]) - for i in range(len(qwc_rot)) - ] + self.are_identical_rotation_gates(qwc_rot[i], qwc_rot_sol[i]) + for i in range(len(qwc_rot)) ) invalid_qwc_rotation_inputs = [ @@ -902,16 +895,12 @@ def test_diagonalize_qwc_pauli_words(self, qwc_grouping, qwc_sol_tuple): qwc_rot_sol, diag_qwc_grouping_sol = qwc_sol_tuple assert all( - [ - self.are_identical_rotation_gates(qwc_rot[i], qwc_rot_sol[i]) - for i in range(len(qwc_rot)) - ] + self.are_identical_rotation_gates(qwc_rot[i], qwc_rot_sol[i]) + for i in range(len(qwc_rot)) ) assert all( - [ - are_identical_pauli_words(diag_qwc_grouping[i], diag_qwc_grouping_sol[i]) - for i in range(len(diag_qwc_grouping)) - ] + are_identical_pauli_words(diag_qwc_grouping[i], diag_qwc_grouping_sol[i]) + for i in range(len(diag_qwc_grouping)) ) not_qwc_groupings = [ @@ -943,6 +932,7 @@ class TestObservableHF: ) def test_pauli_mult(self, p1, p2, p_ref): r"""Test that _pauli_mult returns the correct operator.""" + # pylint: disable=protected-access result = qml.pauli.utils._pauli_mult(p1, p2) assert result == p_ref @@ -1063,12 +1053,14 @@ class TestTapering: @pytest.mark.parametrize(("terms", "num_qubits", "result"), terms_bin_mat_data) def test_binary_matrix(self, terms, num_qubits, result): r"""Test that _binary_matrix returns the correct result.""" + # pylint: disable=protected-access binary_matrix = qml.pauli.utils._binary_matrix(terms, num_qubits) assert (binary_matrix == result).all() @pytest.mark.parametrize(("terms", "num_qubits", "result"), terms_bin_mat_data) def test_binary_matrix_from_pws(self, terms, num_qubits, result): r"""Test that _binary_matrix_from_pws returns the correct result.""" + # pylint: disable=protected-access pws_lst = [list(qml.pauli.pauli_sentence(t))[0] for t in terms] binary_matrix = qml.pauli.utils._binary_matrix_from_pws(pws_lst, num_qubits) assert (binary_matrix == result).all() diff --git a/tests/qchem/of_tests/conftest.py b/tests/qchem/of_tests/conftest.py index 4c7a8852184..e94c97d0a8d 100644 --- a/tests/qchem/of_tests/conftest.py +++ b/tests/qchem/of_tests/conftest.py @@ -1,5 +1,20 @@ +# Copyright 2018-2023 Xanadu Quantum Technologies Inc. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +""" +Pytest configuration file for PennyLane quantum chemistry open fermion test suite. +""" import shutil -import subprocess import pytest import pennylane as qml @@ -30,3 +45,25 @@ def tol(): def custom_wires(request): """Custom wire mapping for Pennylane<->OpenFermion conversion""" return request.param + + +@pytest.fixture(scope="session", name="openfermion_support") +def fixture_openfermion_support(): + """Fixture to determine whether openfermion and openfermionpyscf are installed.""" + # pylint: disable=unused-import + try: + import openfermion + import openfermionpyscf + + openfermion_support = True + except ModuleNotFoundError: + openfermion_support = False + + return openfermion_support + + +@pytest.fixture() +def skip_if_no_openfermion_support(openfermion_support): + """Fixture to skip a test if openfermion or openfermionpyscf are not installed.""" + if not openfermion_support: + pytest.skip("Skipped, no openfermion(pyscf) support") diff --git a/tests/qchem/of_tests/test_convert.py b/tests/qchem/of_tests/test_convert.py index 4b1ab941436..6c2f0f008ab 100644 --- a/tests/qchem/of_tests/test_convert.py +++ b/tests/qchem/of_tests/test_convert.py @@ -15,6 +15,7 @@ Unit tests for functions needed for converting observables obtained from external libraries to a PennyLane observable. """ +# pylint: disable=too-many-arguments,protected-access import os import sys @@ -25,7 +26,6 @@ from pennylane import qchem from pennylane.operation import enable_new_opmath, disable_new_opmath -# TODO: Bring pytest skip to relevant tests. openfermion = pytest.importorskip("openfermion") openfermionpyscf = pytest.importorskip("openfermionpyscf") @@ -52,20 +52,21 @@ def catch_warn_ExpvalCost(ansatz, hamiltonian, device, **kwargs): list(range(100, 120)), {13 - i: "abcdefghijklmn"[i] for i in range(14)}, ], + name="custom_wires", ) -def custom_wires(request): +def custom_wires_fixture(request): """Custom wire mapping for Pennylane<->OpenFermion conversion""" return request.param -@pytest.fixture(scope="session") -def tol(): +@pytest.fixture(scope="session", name="tol") +def tol_fixture(): """Numerical tolerance for equality tests.""" return {"rtol": 0, "atol": 1e-8} @pytest.mark.parametrize( - ("mol_name", "terms_ref"), + ("_", "terms_ref"), [ ("empty", None), ("singlewire", {((0, "Z"),): (0.155924093421341 + 0j)}), @@ -341,7 +342,7 @@ def tol(): ), ], ) -def test_observable_conversion(mol_name, terms_ref, custom_wires, monkeypatch): +def test_observable_conversion(_, terms_ref, custom_wires, monkeypatch): r"""Test the correctness of the QubitOperator observable conversion from OpenFermion to Pennylane. @@ -408,8 +409,8 @@ def test_operation_conversion(pl_op, of_op, wire_order): assert of_op == converted_pl_op converted_of_op = qml.qchem.convert._openfermion_to_pennylane(of_op) - converted_of_op_coeffs, converted_of_op_terms = converted_of_op - assert all([isinstance(term, pauli_ops_and_tensor) for term in converted_of_op_terms]) + _, converted_of_op_terms = converted_of_op + assert all(isinstance(term, pauli_ops_and_tensor) for term in converted_of_op_terms) assert np.allclose( qml.matrix(qml.dot(*pl_op), wire_order=wire_order), qml.matrix(qml.dot(*converted_of_op), wire_order=wire_order), @@ -420,8 +421,8 @@ def test_operation_conversion(pl_op, of_op, wire_order): converted_of_op = qml.qchem.convert._openfermion_to_pennylane(of_op) disable_new_opmath() - converted_of_op_coeffs, converted_of_op_terms = converted_of_op - assert all([isinstance(term, pauli_ops_and_prod) for term in converted_of_op_terms]) + _, converted_of_op_terms = converted_of_op + assert all(isinstance(term, pauli_ops_and_prod) for term in converted_of_op_terms) assert np.allclose( qml.matrix(qml.dot(*pl_op), wire_order=wire_order), @@ -456,10 +457,8 @@ def test_convert_format_not_supported(terms_ref, lib_name, monkeypatch): @pytest.mark.parametrize("op", invalid_ops) def test_not_xyz_pennylane_to_openfermion(op): r"""Test if the conversion complains about non Pauli matrix observables""" - with pytest.raises( - ValueError, - match=f"Expected a Pennylane operator with a valid Pauli word representation,", - ): + _match = "Expected a Pennylane operator with a valid Pauli word representation," + with pytest.raises(ValueError, match=_match): qml.qchem.convert._pennylane_to_openfermion( np.array([0.1 + 0.0j, 0.0]), [ @@ -504,7 +503,7 @@ def test_types_consistency(): for i, op in enumerate(ops): assert op.name == ops_ref[i].name - assert type(op) == type(ops_ref[i]) + assert isinstance(op, type(ops_ref[i])) of_pl_ops = ( @@ -577,8 +576,8 @@ def test_import_operator(of_op, pl_h, pl_op, wires): @pytest.mark.parametrize( ("qubit_op", "tol"), [ - (op_1, 1e08), - (op_2, 1e010), + (op_1, 1e-8), + (op_2, 1e-10), ], ) def test_exception_import_operator(qubit_op, tol): @@ -650,7 +649,7 @@ def test_pennylane_to_openfermion_no_decomp(): @pytest.mark.parametrize( - ("mol_name", "terms_ref", "expected_cost"), + ("_", "terms_ref", "expected_cost"), [ ("empty", None, 0), ( @@ -677,7 +676,7 @@ def test_pennylane_to_openfermion_no_decomp(): ], ) def test_integration_observable_to_vqe_cost( - monkeypatch, mol_name, terms_ref, expected_cost, custom_wires, tol + monkeypatch, _, terms_ref, expected_cost, custom_wires, tol ): r"""Test if `import_operator()` integrates with `ExpvalCost()` in pennylane""" @@ -730,9 +729,7 @@ def test_process_wires(custom_wires, n_wires): if not isinstance(custom_wires, dict): assert wires == qml.qchem.convert._process_wires(custom_wires[:n_wires], n_wires) else: - assert wires == qml.qchem.convert._process_wires( - {k: v for k, v in custom_wires.items()}, n_wires - ) + assert wires == qml.qchem.convert._process_wires(custom_wires, n_wires) def test_process_wires_raises(): diff --git a/tests/qchem/of_tests/test_decompose.py b/tests/qchem/of_tests/test_decompose.py index 2515c5896ea..ccb4f431439 100644 --- a/tests/qchem/of_tests/test_decompose.py +++ b/tests/qchem/of_tests/test_decompose.py @@ -1,15 +1,27 @@ +# Copyright 2018-2023 Xanadu Quantum Technologies Inc. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +""" +Unit tests for the ``decompose`` function. +""" +# pylint: disable=too-many-arguments import os -import sys import numpy as np import pytest from pennylane import qchem -# TODO: Bring pytest skip to relevant tests. -openfermion = pytest.importorskip("openfermion") -openfermionpyscf = pytest.importorskip("openfermionpyscf") - ref_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "test_ref_files") @@ -513,6 +525,7 @@ ), ], ) +@pytest.mark.usefixtures("skip_if_no_openfermion_support") def test_transformation(name, core, active, mapping, coeffs_ref, pauli_strings_ref, tol): r"""Test the correctness of the decomposed Hamiltonian for the (:math: `H_2, H_2O, LiH`) molecules using Jordan-Wigner and Bravyi-Kitaev transformations.""" @@ -528,6 +541,7 @@ def test_transformation(name, core, active, mapping, coeffs_ref, pauli_strings_r assert pauli_strings == pauli_strings_ref +@pytest.mark.usefixtures("skip_if_no_openfermion_support") def test_not_available_transformation(): r"""Test that an error is raised if the chosen fermionic-to-qubit transformation is neither 'jordan_wigner' nor 'bravyi_kitaev'.""" diff --git a/tests/qchem/of_tests/test_dipole_of.py b/tests/qchem/of_tests/test_dipole_of.py index 123af08c101..22b5a201f63 100644 --- a/tests/qchem/of_tests/test_dipole_of.py +++ b/tests/qchem/of_tests/test_dipole_of.py @@ -1,15 +1,25 @@ -import os -import sys +# Copyright 2018-2023 Xanadu Quantum Technologies Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +""" +Unit tests for the ``dipole_of`` function. +""" +# pylint: disable=too-many-arguments import numpy as np import pytest import pennylane as qml -# TODO: Bring pytest skip to relevant tests. -openfermion = pytest.importorskip("openfermion") -openfermionpyscf = pytest.importorskip("openfermionpyscf") - h2 = ["H", "H"] x_h2 = np.array([0.0, 0.0, -0.661, 0.0, 0.0, 0.661]) coeffs_h2 = [] @@ -197,6 +207,7 @@ (h2o, x_h2o, 0, range(4), [4, 5], "bravyi_kitaev", coeffs_h2o, ops_h2o), ], ) +@pytest.mark.usefixtures("skip_if_no_openfermion_support") def test_dipole_obs(symbols, coords, charge, core, active, mapping, coeffs, ops, tol, tmpdir): r"""Tests the correctness of the dipole observable computed by the ``dipole`` function.""" @@ -227,6 +238,7 @@ def test_dipole_obs(symbols, coords, charge, core, active, mapping, coeffs, ops, (h3p, x_h3p, 1, np.array([1, 1, 0, 0, 0, 0]), np.array([0.95655073, 0.55522528, 0.0])), ], ) +@pytest.mark.usefixtures("skip_if_no_openfermion_support") def test_dipole(symbols, coords, charge, hf_state, exp_dipole, tol, tmpdir): r"""Tests the correctness of the computed dipole moment.""" @@ -236,11 +248,12 @@ def test_dipole(symbols, coords, charge, hf_state, exp_dipole, tol, tmpdir): dip_obs = qml.qchem.dipole_of(symbols, coords, charge=charge, outpath=tmpdir.strpath) - def circuit(param, wires): + def circuit(params, wires): + # pylint: disable=unused-argument qml.BasisState(hf_state, wires=wires) with pytest.warns(UserWarning, match="is deprecated,"): - dipole = np.array([qml.ExpvalCost(circuit, obs, dev)(0.0) for obs in dip_obs]) + dipole = np.array([qml.ExpvalCost(circuit, obs, dev)(None) for obs in dip_obs]) assert np.allclose(dipole, exp_dipole, **tol) @@ -252,6 +265,7 @@ def circuit(param, wires): (["H", "Ca"], x_h2, 1, "only first- or second-row elements of the periodic table"), ], ) +@pytest.mark.usefixtures("skip_if_no_openfermion_support") def test_exceptions_dipole(symbols, coords, mult, msg_match): """Test exceptions of the ``dipole`` function.""" diff --git a/tests/qchem/of_tests/test_meanfield.py b/tests/qchem/of_tests/test_meanfield.py index 1077bd97902..bde99c5aefa 100644 --- a/tests/qchem/of_tests/test_meanfield.py +++ b/tests/qchem/of_tests/test_meanfield.py @@ -1,19 +1,31 @@ +# Copyright 2018-2023 Xanadu Quantum Technologies Inc. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +""" +Unit tests for the ``meanfield`` function. +""" import os -import sys import numpy as np import pytest from pennylane import qchem -# TODO: Bring pytest skip to relevant tests. -openfermion = pytest.importorskip("openfermion") -openfermionpyscf = pytest.importorskip("openfermionpyscf") - name = "h2" symbols, coordinates = (["H", "H"], np.array([0.0, 0.0, -0.66140414, 0.0, 0.0, 0.66140414])) +@pytest.mark.usefixtures("skip_if_no_openfermion_support") @pytest.mark.parametrize(("package", "basis"), [("PySCF", "sto-3g"), ("PySCF", "6-31g")]) def test_path_to_file(package, basis, tmpdir): r"""Test the correctness of the full path to the file containing the meanfield @@ -28,9 +40,12 @@ def test_path_to_file(package, basis, tmpdir): assert res_path == exp_path +@pytest.mark.usefixtures("skip_if_no_openfermion_support") @pytest.mark.parametrize("package", ["PySCF"]) def test_hf_calculations(package, tmpdir, tol): r"""Test the correctness of the HF calculation""" + import openfermion + n_atoms = 2 n_electrons = 2 n_orbitals = 2 @@ -69,6 +84,7 @@ def test_hf_calculations(package, tmpdir, tol): assert np.allclose(molecule.two_body_integrals, two_body_integrals, **tol) +@pytest.mark.usefixtures("skip_if_no_openfermion_support") def test_not_available_qc_package(tmpdir): r"""Test that an error is raised if the input quantum chemistry package is not PySCF""" @@ -79,6 +95,7 @@ def test_not_available_qc_package(tmpdir): ) +@pytest.mark.usefixtures("skip_if_no_openfermion_support") def test_dimension_consistency(tmpdir): r"""Test that an error is raised if the size of the 'coordinates' array is not equal to ``3*len(symbols)``""" diff --git a/tests/qchem/of_tests/test_molecular_hamiltonian.py b/tests/qchem/of_tests/test_molecular_hamiltonian.py index 3ddb0985ebb..588a84452f6 100644 --- a/tests/qchem/of_tests/test_molecular_hamiltonian.py +++ b/tests/qchem/of_tests/test_molecular_hamiltonian.py @@ -1,6 +1,20 @@ -import sys -import warnings +# Copyright 2018-2023 Xanadu Quantum Technologies Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +""" +Unit tests for molecular Hamiltonians. +""" +# pylint: disable=too-many-arguments import pytest from pennylane import Identity, PauliX, PauliY, PauliZ @@ -11,12 +25,8 @@ from pennylane.pauli import pauli_sentence from pennylane.operation import enable_new_opmath, disable_new_opmath -# TODO: Bring pytest skip to relevant tests. -openfermion = pytest.importorskip("openfermion") -openfermionpyscf = pytest.importorskip("openfermionpyscf") - -symbols = ["C", "C", "N", "H", "H", "H", "H", "H"] -coordinates = np.array( +test_symbols = ["C", "C", "N", "H", "H", "H", "H", "H"] +test_coordinates = np.array( [ 0.68219113, -0.85415621, @@ -63,6 +73,7 @@ (2, 1, "pyscf", 2, 2, "BRAVYI_kitaev"), ], ) +@pytest.mark.usefixtures("skip_if_no_openfermion_support") def test_building_hamiltonian( charge, mult, @@ -78,7 +89,7 @@ def test_building_hamiltonian( quantum simulation. The latter is tested for different values of the molecule's charge and for active spaces with different size""" - args = (symbols, coordinates) + args = (test_symbols, test_coordinates) kwargs = { "charge": charge, "mult": mult, @@ -232,8 +243,8 @@ def test_differentiable_hamiltonian(symbols, geometry, h_ref_data, op_arithmetic assert np.allclose(np.sort(list(h_args_ps.values())), h_ref_sorted_coeffs) assert np.allclose(np.sort(list(h_noargs_ps.values())), h_ref_sorted_coeffs) - assert all([val.requires_grad is True for val in h_args_ps.values()]) - assert all([val.requires_grad is False for val in h_noargs_ps.values()]) + assert all(val.requires_grad is True for val in h_args_ps.values()) + assert all(val.requires_grad is False for val in h_noargs_ps.values()) else: assert np.allclose(np.sort(h_args.coeffs), np.sort(h_ref.coeffs)) @@ -246,8 +257,8 @@ def test_differentiable_hamiltonian(symbols, geometry, h_ref_data, op_arithmetic Hamiltonian(np.ones(len(h_ref.coeffs)), h_ref.ops) ) - assert h_args.coeffs.requires_grad == True - assert h_noargs.coeffs.requires_grad == False + assert h_args.coeffs.requires_grad is True + assert h_noargs.coeffs.requires_grad is False @pytest.mark.parametrize("op_arithmetic", [False, True]) @@ -268,6 +279,7 @@ def test_differentiable_hamiltonian(symbols, geometry, h_ref_data, op_arithmetic ), ], ) +@pytest.mark.usefixtures("skip_if_no_openfermion_support") def test_custom_wiremap_hamiltonian_pyscf( symbols, geometry, method, wiremap, tmpdir, op_arithmetic ): @@ -275,7 +287,7 @@ def test_custom_wiremap_hamiltonian_pyscf( if op_arithmetic: enable_new_opmath() - hamiltonian, qubits = qchem.molecular_hamiltonian( + hamiltonian, _ = qchem.molecular_hamiltonian( symbols=symbols, coordinates=geometry, method=method, @@ -312,7 +324,7 @@ def test_custom_wiremap_hamiltonian_dhf(symbols, geometry, wiremap, args, tmpdir if op_arithmetic: enable_new_opmath() - hamiltonian, qubits = qchem.molecular_hamiltonian( + hamiltonian, _ = qchem.molecular_hamiltonian( symbols=symbols, coordinates=geometry, wires=wiremap, @@ -362,13 +374,13 @@ def test_diff_hamiltonian_error(symbols, geometry): r"""Test that molecular_hamiltonian raises an error with unsupported mapping.""" with pytest.raises(ValueError, match="Only 'jordan_wigner' mapping is supported"): - qchem.molecular_hamiltonian(symbols, geometry, method="dhf", mapping="bravyi_kitaev")[0] + qchem.molecular_hamiltonian(symbols, geometry, method="dhf", mapping="bravyi_kitaev") with pytest.raises(ValueError, match="Only 'dhf' and 'pyscf' backends are supported"): - qchem.molecular_hamiltonian(symbols, geometry, method="psi4")[0] + qchem.molecular_hamiltonian(symbols, geometry, method="psi4") with pytest.raises(ValueError, match="Openshell systems are not supported"): - qchem.molecular_hamiltonian(symbols, geometry, mult=3)[0] + qchem.molecular_hamiltonian(symbols, geometry, mult=3) @pytest.mark.parametrize("op_arithmetic", [False, True]) @@ -395,12 +407,13 @@ def test_diff_hamiltonian_error(symbols, geometry): ), ], ) +@pytest.mark.usefixtures("skip_if_no_openfermion_support") def test_real_hamiltonian(symbols, geometry, method, args, tmpdir, op_arithmetic): r"""Test that the generated Hamiltonian has real coefficients.""" if op_arithmetic: enable_new_opmath() - hamiltonian, qubits = qchem.molecular_hamiltonian( + hamiltonian, _ = qchem.molecular_hamiltonian( symbols=symbols, coordinates=geometry, method=method, diff --git a/tests/qchem/of_tests/test_observable_of.py b/tests/qchem/of_tests/test_observable_of.py index 87d7834a948..30e240391ec 100644 --- a/tests/qchem/of_tests/test_observable_of.py +++ b/tests/qchem/of_tests/test_observable_of.py @@ -1,3 +1,20 @@ +# Copyright 2018-2023 Xanadu Quantum Technologies Inc. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +""" +Unit tests for the ``observable`` function for openfermion operators. +""" +# pylint: disable=too-many-arguments import sys import pytest @@ -5,7 +22,6 @@ import pennylane as qml from pennylane import qchem -# TODO: Bring pytest skip to relevant tests. openfermion = pytest.importorskip("openfermion") openfermionpyscf = pytest.importorskip("openfermionpyscf") @@ -115,6 +131,7 @@ def test_observable(fermion_ops, init_term, mapping, terms_exp, custom_wires, mo `QubitOperator. The equality checking is implemented in the `qchem` module itself as it could be something useful to the users as well. """ + # pylint: disable=protected-access res_obs = qchem.observable( fermion_ops, init_term=init_term, mapping=mapping, wires=custom_wires @@ -150,6 +167,7 @@ def test_exceptions_observable(fermion_ops, mapping, msg_match): def test_import_of(monkeypatch): """Test if an ImportError is raised by _import_of function.""" + # pylint: disable=protected-access with monkeypatch.context() as m: m.setitem(sys.modules, "openfermion", None) diff --git a/tests/qchem/of_tests/test_one_particle.py b/tests/qchem/of_tests/test_one_particle.py index 4e4dae972a3..4fa951aeaa7 100644 --- a/tests/qchem/of_tests/test_one_particle.py +++ b/tests/qchem/of_tests/test_one_particle.py @@ -1,15 +1,27 @@ +# Copyright 2018-2023 Xanadu Quantum Technologies Inc. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +""" +Unit tests for the ``one_particle`` function of FermionOperator +in openfermion. +""" import os -import sys import numpy as np import pytest from pennylane import qchem -# TODO: Bring pytest skip to relevant tests. -openfermion = pytest.importorskip("openfermion") -openfermionpyscf = pytest.importorskip("openfermionpyscf") - ref_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "test_ref_files") t_op_1 = { @@ -126,9 +138,11 @@ (None, [0, 1, 2, 3, 4, 5], t_op_4), ], ) +@pytest.mark.usefixtures("skip_if_no_openfermion_support") def test_table_one_particle(core, active, t_op_exp): r"""Test the correctness of the FermionOperator built by the `'one_particle'` function of the `obs` module""" + import openfermion hf = openfermion.MolecularData(filename=os.path.join(ref_dir, "h2o_psi4")) @@ -151,6 +165,7 @@ def test_table_one_particle(core, active, t_op_exp): (table_2D, None, [2, 6], "Indices of active orbitals must be between 0 and"), ], ) +@pytest.mark.usefixtures("skip_if_no_openfermion_support") def test_exceptions_one_particle(t_me, core, active, msg_match): """Test that the function `'one_particle'` throws an exception if the matrix elements array is not a 2D array or if the indices diff --git a/tests/qchem/of_tests/test_two_particle.py b/tests/qchem/of_tests/test_two_particle.py index adab2d7fd48..d94443d28fc 100644 --- a/tests/qchem/of_tests/test_two_particle.py +++ b/tests/qchem/of_tests/test_two_particle.py @@ -1,15 +1,27 @@ +# Copyright 2018-2023 Xanadu Quantum Technologies Inc. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +""" +Unit tests for the ``two_particle`` function of FermionOperator +in openfermion. +""" import os -import sys import numpy as np import pytest from pennylane import qchem -# TODO: Bring pytest skip to relevant tests. -openfermion = pytest.importorskip("openfermion") -openfermionpyscf = pytest.importorskip("openfermionpyscf") - ref_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "test_ref_files") v_op_1 = { @@ -239,8 +251,10 @@ ("h2o_psi4", [0, 1, 2], [3, 4, 6], v_op_4), ], ) +@pytest.mark.usefixtures("skip_if_no_openfermion_support") def test_table_two_particle(name, core, active, v_op_exp): r"""Test the FermionOperator built by the function `two_particle` of the `obs` module""" + import openfermion hf_data = openfermion.MolecularData(filename=os.path.join(ref_dir, name)) @@ -263,6 +277,7 @@ def test_table_two_particle(name, core, active, v_op_exp): (v_me_4D, None, [2, 6], "Indices of active orbitals must be between 0 and"), ], ) +@pytest.mark.usefixtures("skip_if_no_openfermion_support") def test_exceptions_two_particle(v_me, core, active, msg_match): """Test that the function `'two_particle'` throws an exception if the dimension of the matrix elements array is not a 4D array or diff --git a/tests/qchem/test_basis_set.py b/tests/qchem/test_basis_set.py index eed82d54e68..2d64c04017e 100644 --- a/tests/qchem/test_basis_set.py +++ b/tests/qchem/test_basis_set.py @@ -14,9 +14,8 @@ """ Unit tests for generating basis set default parameters. """ +# pylint: disable=too-many-arguments import sys - -# pylint: disable=no-self-use import pytest from pennylane import numpy as np @@ -27,7 +26,7 @@ class TestBasis: """Tests for generating basis set default parameters""" @pytest.mark.parametrize( - ("basis_name", "atom_name", "l", "alpha", "coeff", "r"), + ("_", "__", "l", "alpha", "coeff", "r"), [ ( "sto-3g", @@ -40,7 +39,7 @@ class TestBasis: ), ], ) - def test_basisfunction(self, basis_name, atom_name, l, alpha, coeff, r): + def test_basisfunction(self, _, __, l, alpha, coeff, r): """Test that BasisFunction class creates basis function objects correctly.""" basis_function = qchem.BasisFunction(l, alpha, coeff, r) diff --git a/tests/qchem/test_dipole.py b/tests/qchem/test_dipole.py index 2167f0e31f5..42e249b89a6 100644 --- a/tests/qchem/test_dipole.py +++ b/tests/qchem/test_dipole.py @@ -14,6 +14,7 @@ """ Unit tests for functions needed for computing the dipole. """ +# pylint: disable=too-many-arguments import pytest import pennylane as qml @@ -250,18 +251,17 @@ def test_dipole_moment(symbols, geometry, core, charge, active, coeffs, ops): @pytest.mark.parametrize( - ("symbols", "geometry", "charge", "core", "active"), + ("symbols", "geometry", "core", "active"), [ ( ["H", "H"], np.array([[0.0, 0.0, 0.0], [2.0, 0.0, 0.0]], requires_grad=False), - 0, None, None, ), ], ) -def test_dipole_moment_631g_basis(symbols, geometry, core, charge, active): +def test_dipole_moment_631g_basis(symbols, geometry, core, active): r"""Test that the dipole moment is constructed properly with basis sets having different numbers of primitive Gaussian functions.""" alpha = [ @@ -278,7 +278,7 @@ def test_dipole_moment_631g_basis(symbols, geometry, core, charge, active): @pytest.mark.parametrize( - ("symbols", "geometry", "charge", "core", "active", "d_ref"), + ("symbols", "geometry", "charge", "d_ref"), [ ( ["H", "H", "H"], @@ -286,13 +286,11 @@ def test_dipole_moment_631g_basis(symbols, geometry, core, charge, active): [[0.028, 0.054, 0.0], [0.986, 1.610, 0.0], [1.855, 0.002, 0.0]], requires_grad=False ), 1, - None, - None, [0.95655073, 0.55522528, 0.0], # x, y, z components of the dipole moment from PL-QChem ), ], ) -def test_expvalD(symbols, geometry, charge, core, active, d_ref): +def test_expvalD(symbols, geometry, charge, d_ref): r"""Test that expval(D) is correct.""" mol = qchem.Molecule(symbols, geometry, charge=charge) args = [] diff --git a/tests/qchem/test_factorization.py b/tests/qchem/test_factorization.py index 0428366d901..ea68984e9b8 100644 --- a/tests/qchem/test_factorization.py +++ b/tests/qchem/test_factorization.py @@ -14,7 +14,7 @@ """ Unit tests for functions needed for two-electron integral tensor factorization. """ - +# pylint: disable=too-many-arguments import pytest import pennylane as qml @@ -326,7 +326,7 @@ def test_basis_rotation_output( assert np.allclose(np.sort(coeff), np.sort(coeffs_ref[i])) for j, op in enumerate(ops): - ops_ref_str = [qml.pauli.pauli_word_to_string(t) for t in ops_ref[i]] + ops_ref_str = [qml.pauli.pauli_word_to_string(t) for t in ops_ref[j]] for o in op: assert qml.pauli.pauli_word_to_string(o) in ops_ref_str @@ -370,7 +370,7 @@ def test_basis_rotation_utransform(core, one_electron, two_electron): A new Hamiltonian is generated from these operators and is compared with the original Hamiltonian. """ - c_group, o_group, u_transform = qml.qchem.basis_rotation(one_electron, two_electron) + *_, u_transform = qml.qchem.basis_rotation(one_electron, two_electron) a_cr = [ # fermionic creation operators np.array( @@ -699,7 +699,9 @@ def test_basis_rotation_utransform(core, one_electron, two_electron): def test_chemist_transform( two_body_tensor, spatial_basis, one_body_correction, chemist_two_body_coeffs ): - r"""Test that `_chemist_transform` builds correct two-body tensors in chemist notation with correct one-body corrections""" + r"""Test that `_chemist_transform` builds correct two-body tensors in + chemist notation with correct one-body corrections""" + # pylint: disable=protected-access one_body_corr, chemist_two_body = qml.qchem.factorization._chemist_transform( two_body_tensor=two_body_tensor, spatial_basis=spatial_basis ) diff --git a/tests/qchem/test_hamiltonians.py b/tests/qchem/test_hamiltonians.py index 750e20bf7e2..cae72e91bc1 100644 --- a/tests/qchem/test_hamiltonians.py +++ b/tests/qchem/test_hamiltonians.py @@ -14,6 +14,7 @@ """ Unit tests for functions needed for computing the Hamiltonian. """ +# pylint: disable=too-many-arguments,too-few-public-methods import pytest import pennylane as qml diff --git a/tests/qchem/test_hartree_fock.py b/tests/qchem/test_hartree_fock.py index 3db579f6283..a0bcf2b5685 100644 --- a/tests/qchem/test_hartree_fock.py +++ b/tests/qchem/test_hartree_fock.py @@ -14,6 +14,7 @@ """ Unit tests for Hartree-Fock functions. """ +# pylint: disable=too-many-arguments,too-few-public-methods import pytest import pennylane as qml @@ -34,7 +35,7 @@ def test_scf_leaves_random_seed_unchanged(): args = [alpha] initial_numpy_state = np.random.get_state() - v_fock, coeffs, fock_matrix, h_core, rep_tensor = qchem.scf(mol)(*args) + qchem.scf(mol)(*args) final_numpy_state = np.random.get_state() assert initial_numpy_state[0] == final_numpy_state[0] diff --git a/tests/qchem/test_integrals.py b/tests/qchem/test_integrals.py index 97c4f85b4e7..82b80ceb2e2 100644 --- a/tests/qchem/test_integrals.py +++ b/tests/qchem/test_integrals.py @@ -14,6 +14,7 @@ """ Unit tests for functions needed to computing integrals over basis functions. """ +# pylint: disable=too-many-arguments,too-few-public-methods,protected-access import pytest import pennylane as qml diff --git a/tests/qchem/test_matrices.py b/tests/qchem/test_matrices.py index 1bd3683864c..89a13e54048 100644 --- a/tests/qchem/test_matrices.py +++ b/tests/qchem/test_matrices.py @@ -14,6 +14,7 @@ """ Unit tests for functions needed for computing matrices. """ +# pylint: disable=too-many-arguments,too-few-public-methods import pytest import pennylane as qml diff --git a/tests/qchem/test_molecule.py b/tests/qchem/test_molecule.py index faa2b960d37..5191f3445f7 100644 --- a/tests/qchem/test_molecule.py +++ b/tests/qchem/test_molecule.py @@ -14,7 +14,7 @@ """ Unit tests for the molecule object. """ -# pylint: disable=no-self-use +# pylint: disable=too-many-arguments import pytest from pennylane import numpy as np diff --git a/tests/qchem/test_spin.py b/tests/qchem/test_spin.py index fdf064f3ada..43bf636424b 100644 --- a/tests/qchem/test_spin.py +++ b/tests/qchem/test_spin.py @@ -107,6 +107,7 @@ def test_spin2_matrix_elements(n_spin_orbs, matrix_ref): r"""Test the calculation of the matrix elements of the two-particle spin operator :math:`\hat{s}_1 \cdot \hat{s}_2` implemented by the function `'_spin2_matrix_elements'`""" + # pylint: disable=protected-access sz = np.where(np.arange(n_spin_orbs) % 2 == 0, 0.5, -0.5) diff --git a/tests/qchem/test_structure.py b/tests/qchem/test_structure.py index 0738f4e02ca..8fb7affd4dd 100644 --- a/tests/qchem/test_structure.py +++ b/tests/qchem/test_structure.py @@ -14,11 +14,12 @@ """ Unit tests for the functions of the structure module. """ +# pylint: disable=too-many-arguments import os import sys -import pytest import functools as ft from unittest.mock import patch +import pytest import pennylane as qml from pennylane import qchem @@ -73,37 +74,33 @@ def test_reading_xyz_file(tmpdir): "electrons", "orbitals", "delta_sz", - "n_singles", - "n_doubles", "singles_exp", "doubles_exp", ), [ - (1, 5, 0, 2, 0, [[0, 2], [0, 4]], []), - (1, 5, 1, 0, 0, [], []), - (1, 5, -1, 2, 0, [[0, 1], [0, 3]], []), - (2, 5, 0, 3, 2, [[0, 2], [0, 4], [1, 3]], [[0, 1, 2, 3], [0, 1, 3, 4]]), - (2, 5, 1, 2, 1, [[1, 2], [1, 4]], [[0, 1, 2, 4]]), - (2, 5, -1, 1, 0, [[0, 3]], []), - (2, 5, 2, 0, 0, [], []), - (3, 6, 1, 1, 0, [[1, 4]], []), + (1, 5, 0, [[0, 2], [0, 4]], []), + (1, 5, 1, [], []), + (1, 5, -1, [[0, 1], [0, 3]], []), + (2, 5, 0, [[0, 2], [0, 4], [1, 3]], [[0, 1, 2, 3], [0, 1, 3, 4]]), + (2, 5, 1, [[1, 2], [1, 4]], [[0, 1, 2, 4]]), + (2, 5, -1, [[0, 3]], []), + (2, 5, 2, [], []), + (3, 6, 1, [[1, 4]], []), ( 3, 6, -1, - 4, - 4, [[0, 3], [0, 5], [2, 3], [2, 5]], [[0, 1, 3, 5], [0, 2, 3, 4], [0, 2, 4, 5], [1, 2, 3, 5]], ), - (3, 6, -2, 0, 1, [], [[0, 2, 3, 5]]), - (3, 4, 0, 1, 0, [[1, 3]], []), - (3, 4, 1, 0, 0, [], []), - (3, 4, -1, 2, 0, [[0, 3], [2, 3]], []), - (3, 4, 2, 0, 0, [], []), + (3, 6, -2, [], [[0, 2, 3, 5]]), + (3, 4, 0, [[1, 3]], []), + (3, 4, 1, [], []), + (3, 4, -1, [[0, 3], [2, 3]], []), + (3, 4, 2, [], []), ], ) -def test_excitations(electrons, orbitals, delta_sz, n_singles, n_doubles, singles_exp, doubles_exp): +def test_excitations(electrons, orbitals, delta_sz, singles_exp, doubles_exp): r"""Test the correctness of the generated configurations""" singles, doubles = qchem.excitations(electrons, orbitals, delta_sz) @@ -422,7 +419,7 @@ def test_consistent_pubchem_mol_data(identifier, identifier_type): ("In=1S/H3N/h1H3/p+1", "InChI", "Specified identifier doesn't seem to match type"), ("14798039", "CAS", "Specified identifier doesn't seem to match type"), ("beh2+", "name", "Specified molecule does not exist in the PubChem Database"), - (0, "CID", "Provided CID \(or Identifier\) is None"), + (0, "CID", r"Provided CID \(or Identifier\) is None"), ], ) def test_inconsistent_pubchem_mol_data(identifier, identifier_type, message_match): diff --git a/tests/qchem/test_tapering.py b/tests/qchem/test_tapering.py index 2b776c710a4..3c201b3172f 100644 --- a/tests/qchem/test_tapering.py +++ b/tests/qchem/test_tapering.py @@ -14,9 +14,8 @@ """ Unit tests for functions needed for qubit tapering. """ +# pylint: disable=too-many-arguments import functools -from lib2to3.pytree import convert -from pennylane.ops.functions.eigvals import eigvals import pytest import scipy @@ -24,7 +23,6 @@ import pennylane as qml from pennylane import numpy as np from pennylane.pauli import pauli_sentence -from pennylane.pauli.utils import _binary_matrix from pennylane.qchem.tapering import ( _kernel, _reduced_row_echelon, @@ -34,7 +32,6 @@ taper_operation, _split_pauli_sentence, _taper_pauli_sentence, - _build_generator, ) from pennylane.operation import enable_new_opmath, disable_new_opmath @@ -219,12 +216,11 @@ def test_generate_paulis(generators, num_qubits, result): @pytest.mark.parametrize( - ("symbols", "geometry", "num_qubits", "res_generators"), + ("symbols", "geometry", "res_generators"), [ ( ["H", "H"], np.array([[0.0, 0.0, 0.0], [0.0, 0.0, 1.40104295]], requires_grad=False), - 4, [ qml.Hamiltonian([1.0], [qml.PauliZ(0) @ qml.PauliZ(1)]), qml.Hamiltonian([1.0], [qml.PauliZ(0) @ qml.PauliZ(2)]), @@ -233,7 +229,7 @@ def test_generate_paulis(generators, num_qubits, result): ), ], ) -def test_symmetry_generators(symbols, geometry, num_qubits, res_generators): +def test_symmetry_generators(symbols, geometry, res_generators): r"""Test that symmetry_generators returns the correct result.""" mol = qml.qchem.Molecule(symbols, geometry) @@ -428,8 +424,8 @@ def test_optimal_sector(symbols, geometry, charge, generators, num_electrons, re @pytest.mark.parametrize( ("num_electrons", "msg_match"), [ - (0, f"The number of active electrons must be greater than zero"), - (5, f"Number of active orbitals cannot be smaller than number of active electrons"), + (0, "The number of active electrons must be greater than zero"), + (5, "Number of active orbitals cannot be smaller than number of active electrons"), ], ) def test_exceptions_optimal_sector(symbols, geometry, generators, num_electrons, msg_match): @@ -587,10 +583,8 @@ def test_taper_obs(symbols, geometry, charge, op_arithmetic): # calculate the HF energy <\psi_{HF}| H |\psi_{HF}> for tapered and untapered Hamiltonian o = np.array([1, 0]) l = np.array([0, 1]) - state = functools.reduce(lambda i, j: np.kron(i, j), [l if s else o for s in hf_state]) - state_tapered = functools.reduce( - lambda i, j: np.kron(i, j), [l if s else o for s in hf_state_tapered] - ) + state = functools.reduce(np.kron, [l if s else o for s in hf_state]) + state_tapered = functools.reduce(np.kron, [l if s else o for s in hf_state_tapered]) observables = [ hamiltonian, @@ -695,10 +689,8 @@ def test_taper_excitations( o = np.array([1, 0]) l = np.array([0, 1]) - state = functools.reduce(lambda i, j: np.kron(i, j), [l if s else o for s in hf_state]) - state_tapered = functools.reduce( - lambda i, j: np.kron(i, j), [l if s else o for s in hf_tapered] - ) + state = functools.reduce(np.kron, [l if s else o for s in hf_state]) + state_tapered = functools.reduce(np.kron, [l if s else o for s in hf_tapered]) singles, doubles = qml.qchem.excitations(num_electrons, num_wires) exc_fnc = [qml.SingleExcitation, qml.DoubleExcitation] @@ -718,7 +710,7 @@ def test_taper_excitations( if op_tap: excited_state = np.matmul(qml.matrix(op_all, wire_order=range(len(hf_state))), state) ob_tap_mat = functools.reduce( - lambda i, j: np.matmul(i, j), + np.matmul, [qml.matrix(op, wire_order=range(len(hf_tapered))) for op in op_tap], ) excited_state_tapered = np.matmul(ob_tap_mat, state_tapered) @@ -848,13 +840,9 @@ def test_consistent_taper_ops(operation, op_gen): if taper_op1: observables = [ hamiltonian, # for energy - functools.reduce( - lambda i, j: i + j, [qml.PauliZ(wire) for wire in hamiltonian.wires] - ), # for local-cost 1 - functools.reduce( - lambda i, j: i + j, - [qml.PauliZ(wire) @ qml.PauliZ(wire + 1) for wire in hamiltonian.wires], - ), # for local-cost 2 + sum(qml.PauliZ(wire) for wire in hamiltonian.wires), # for local-cost 1 + # for local-cost 2 + sum(qml.PauliZ(wire) @ qml.PauliZ(wire + 1) for wire in hamiltonian.wires), ] tapered_obs = [ qml.taper(observale, generators, paulixops, paulix_sector) for observale in observables @@ -865,13 +853,11 @@ def test_consistent_taper_ops(operation, op_gen): generators, paulixops, paulix_sector, mol.n_electrons, len(hamiltonian.wires) ) o, l = np.array([1, 0]), np.array([0, 1]) - state = functools.reduce(lambda i, j: np.kron(i, j), [l if s else o for s in hf_state]) - state_tapered = functools.reduce( - lambda i, j: np.kron(i, j), [l if s else o for s in hf_tapered] - ) + state = functools.reduce(np.kron, [l if s else o for s in hf_state]) + state_tapered = functools.reduce(np.kron, [l if s else o for s in hf_tapered]) evolved_state = np.matmul(qml.matrix(operation, wire_order=range(len(hf_state))), state) ob_tap_mat = functools.reduce( - lambda i, j: np.matmul(i, j), + np.matmul, [qml.matrix(op, wire_order=range(len(hf_tapered))) for op in taper_op1], ) evolved_state_tapered = np.matmul(ob_tap_mat, state_tapered) @@ -1085,23 +1071,17 @@ def test_inconsistent_callable_ops(operation, op_wires, op_gen, message_match): ) -@pytest.mark.parametrize( - ("ps_size", "max_size"), - [ - (190, 49), - (40, 13), - ], -) +@pytest.mark.parametrize(("ps_size", "max_size"), [(190, 49), (40, 13)]) def test_split_pauli_sentence(ps_size, max_size): """Test that _split_pauli_sentence splits the PauliSentence objects into correct chunks.""" - pauli_sentence = qml.pauli.PauliSentence( + sentence = qml.pauli.PauliSentence( {qml.pauli.PauliWord({i: "X", i + 1: "Y", i + 2: "Z"}): i for i in range(ps_size)} ) split_sentence = {} - for ps in _split_pauli_sentence(pauli_sentence, max_size=max_size): + for ps in _split_pauli_sentence(sentence, max_size=max_size): assert len(ps) <= max_size split_sentence = {**split_sentence, **ps} - assert pauli_sentence == qml.pauli.PauliSentence(split_sentence) + assert sentence == qml.pauli.PauliSentence(split_sentence) diff --git a/tests/qinfo/test_entropies.py b/tests/qinfo/test_entropies.py index 30ab02e0188..3981d0ac058 100644 --- a/tests/qinfo/test_entropies.py +++ b/tests/qinfo/test_entropies.py @@ -13,7 +13,7 @@ # limitations under the License. """Unit tests for differentiable quantum entropies. """ - +# pylint: disable=too-many-arguments import pytest import pennylane as qml @@ -556,13 +556,13 @@ def test_qnode_grad(self, param, interface): with the autograd interface""" dev = qml.device("default.qubit", wires=2) - @qml.qnode(dev, interface="autograd", diff_method="backprop") + @qml.qnode(dev, interface=interface, diff_method="backprop") def circuit1(param): qml.RY(param, wires=0) qml.CNOT(wires=[0, 1]) return qml.state() - @qml.qnode(dev, interface="autograd", diff_method="backprop") + @qml.qnode(dev, interface=interface, diff_method="backprop") def circuit2(param): qml.RY(param, wires=0) qml.CNOT(wires=[0, 1]) @@ -598,13 +598,13 @@ def test_qnode_grad_tf(self, param, interface): dev = qml.device("default.qubit", wires=2) - @qml.qnode(dev, interface="tf", diff_method="backprop") + @qml.qnode(dev, interface=interface, diff_method="backprop") def circuit1(param): qml.RY(param, wires=0) qml.CNOT(wires=[0, 1]) return qml.state() - @qml.qnode(dev, interface="tf", diff_method="backprop") + @qml.qnode(dev, interface=interface, diff_method="backprop") def circuit2(param): qml.RY(param, wires=0) qml.CNOT(wires=[0, 1]) @@ -638,24 +638,18 @@ def test_qnode_grad_torch(self, param, interface): dev = qml.device("default.qubit", wires=2) - @qml.qnode(dev, interface="torch", diff_method="backprop") + @qml.qnode(dev, interface=interface, diff_method="backprop") def circuit1(param): qml.RY(param, wires=0) qml.CNOT(wires=[0, 1]) return qml.state() - @qml.qnode(dev, interface="torch", diff_method="backprop") + @qml.qnode(dev, interface=interface, diff_method="backprop") def circuit2(param): qml.RY(param, wires=0) qml.CNOT(wires=[0, 1]) return qml.state() - first_expected = ( - np.sin(param[0] / 2) - * np.cos(param[0] / 2) - * (np.log(np.tan(param[0] / 2) ** 2) - np.log(np.tan(param[1] / 2) ** 2)) - ) - expected = [ np.sin(param[0] / 2) * np.cos(param[0] / 2) @@ -695,7 +689,7 @@ def circuit2(param): msg = "The two states must have the same number of wires" with pytest.raises(qml.QuantumFunctionError, match=msg): - rel_ent_circuit = qml.qinfo.relative_entropy(circuit1, circuit2, [0], [0, 1]) + qml.qinfo.relative_entropy(circuit1, circuit2, [0], [0, 1]) @pytest.mark.parametrize("device", ["default.qubit", "default.mixed", "lightning.qubit"]) def test_full_wires(self, device): @@ -717,7 +711,7 @@ def circuit2(param): x, y = np.array(0.3), np.array(0.7) # test that the circuit executes - actual = rel_ent_circuit(x, y) + rel_ent_circuit(x, y) @pytest.mark.parametrize("device", ["default.qubit", "default.mixed", "lightning.qubit"]) def test_qnode_no_args(self, device): @@ -739,7 +733,7 @@ def circuit2(): rel_ent_circuit = qml.qinfo.relative_entropy(circuit1, circuit2, [0], [1]) # test that the circuit executes - actual = rel_ent_circuit() + rel_ent_circuit() @pytest.mark.parametrize("device", ["default.qubit", "default.mixed", "lightning.qubit"]) def test_qnode_kwargs(self, device): diff --git a/tests/qinfo/test_fidelity.py b/tests/qinfo/test_fidelity.py index 2fcd50086d2..d89107689d3 100644 --- a/tests/qinfo/test_fidelity.py +++ b/tests/qinfo/test_fidelity.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. """Unit tests for differentiable quantum fidelity transform.""" - +# pylint: disable=too-many-public-methods import pytest import pennylane as qml @@ -162,19 +162,23 @@ def circuit1(x, y): @pytest.mark.parametrize("wire", wires) def test_fidelity_qnodes_rx_pauliz(self, device, param, wire): """Test the fidelity between Rx and PauliZ circuits.""" - dev = qml.device(device, wires=1) + dev = qml.device(device, wires=[wire]) + print(dev.wires) @qml.qnode(dev) def circuit0(x): - qml.RX(x, wires=0) + qml.RX(x, wires=wire) return qml.state() @qml.qnode(dev) def circuit1(): - qml.PauliZ(wires=0) + qml.PauliZ(wires=wire) return qml.state() + # todo: Once #4318 is closed, will need to change the wires0, wires1 arguments + # to the commented version fid = qml.qinfo.fidelity(circuit0, circuit1, wires0=[0], wires1=[0])((param)) + # fid = qml.qinfo.fidelity(circuit0, circuit1, wires0=[wire], wires1=[wire])((param)) expected_fid = expected_fidelity_rx_pauliz(param) assert qml.math.allclose(fid, expected_fid) @@ -472,8 +476,7 @@ def circuit1(): @pytest.mark.jax @pytest.mark.parametrize("param", parameters) @pytest.mark.parametrize("wire", wires) - @pytest.mark.parametrize("interface", interfaces) - def test_fidelity_qnodes_rx_pauliz_jax_jit(self, param, wire, interface): + def test_fidelity_qnodes_rx_pauliz_jax_jit(self, param, wire): """Test the fidelity between Rx and PauliZ circuits with Jax jit.""" import jax diff --git a/tests/qinfo/test_fisher.py b/tests/qinfo/test_fisher.py index 5e75886ce7a..b8ea2f4c361 100644 --- a/tests/qinfo/test_fisher.py +++ b/tests/qinfo/test_fisher.py @@ -17,9 +17,9 @@ # pylint: disable=no-self-use, import-outside-toplevel, no-member, import-error, too-few-public-methods, bad-continuation import pytest +import numpy as np import pennylane as qml import pennylane.numpy as pnp -import numpy as np from pennylane.qinfo import classical_fisher, quantum_fisher @@ -72,11 +72,9 @@ def test_construction_of_compute_cfim(self, n_params, n_wires): assert np.allclose(res, res.T) assert all( - [ - res[i, j] == np.sum(dp[:, i] * dp[:, j] / p) - for i in range(n_params) - for j in range(n_params) - ] + res[i, j] == np.sum(dp[:, i] * dp[:, j] / p) + for i in range(n_params) + for j in range(n_params) ) @pytest.mark.parametrize("n_params", np.arange(1, 10)) diff --git a/tests/qinfo/test_purity.py b/tests/qinfo/test_purity.py index dcd476df62b..66ed5bd8cbc 100644 --- a/tests/qinfo/test_purity.py +++ b/tests/qinfo/test_purity.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. """Unit tests for purities.""" - +# pylint: disable=too-many-arguments import pytest import pennylane as qml @@ -233,6 +233,8 @@ def test_IsingXX_qnode_purity_jax_jit(self, device, param, wires, is_partial, in import jax import jax.numpy as jnp + jax.config.update("jax_enable_x64", True) + dev = qml.device(device, wires=2) @qml.qnode(dev, interface=interface) diff --git a/tests/qinfo/test_reduced_dm.py b/tests/qinfo/test_reduced_dm.py index a637dc59d1b..578cca4a442 100644 --- a/tests/qinfo/test_reduced_dm.py +++ b/tests/qinfo/test_reduced_dm.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. """Unit tests for the (reduced) density matrix transform.""" - +# pylint: disable=too-many-arguments import pytest import pennylane as qml @@ -37,18 +37,16 @@ "jax", ] wires_list = [[0], [1], [0, 1], [1, 0]] -check_state = [False, True] class TestDensityMatrixQNode: """Tests for the (reduced) density matrix for QNodes returning states.""" - @pytest.mark.parametrize("check", check_state) @pytest.mark.parametrize("device", devices) @pytest.mark.parametrize("interface", interfaces) @pytest.mark.parametrize("angle", angle_values) @pytest.mark.parametrize("wires", wires_list) - def test_density_matrix_from_qnode(self, device, wires, angle, interface, check, tol): + def test_density_matrix_from_qnode(self, device, wires, angle, interface, tol): """Test the density matrix from matrix for single wires.""" dev = qml.device(device, wires=2) @@ -65,20 +63,21 @@ def expected_density_matrix(x, wires): return [[np.sin(x / 2) ** 2, 0], [0, np.cos(x / 2) ** 2]] if wires == [1]: return [[np.cos(x / 2) ** 2, 0], [0, np.sin(x / 2) ** 2]] - elif wires == [0, 1]: + if wires == [0, 1]: return [ [0, 0, 0, 0], [0, np.sin(x / 2) ** 2, 0.0 - np.cos(x / 2) * np.sin(x / 2) * 1j, 0], [0, 0.0 + np.cos(x / 2) * np.sin(x / 2) * 1j, np.cos(x / 2) ** 2, 0], [0, 0, 0, 0], ] - elif wires == [1, 0]: + if wires == [1, 0]: return [ [0, 0, 0, 0], [0, np.cos(x / 2) ** 2, 0.0 + np.cos(x / 2) * np.sin(x / 2) * 1j, 0], [0, 0.0 - np.cos(x / 2) * np.sin(x / 2) * 1j, np.sin(x / 2) ** 2, 0], [0, 0, 0, 0], ] + return None assert np.allclose(expected_density_matrix(angle, wires), density_matrix, atol=tol, rtol=0) @@ -115,8 +114,6 @@ def circuit(x): def test_density_matrix_qnode_tf_jit(self): """Test jitting the density matrix from state vector function with Tf.""" - import tensorflow as tf - dev = qml.device("default.qubit", wires=2) @qml.qnode(dev, interface="tf") @@ -135,9 +132,8 @@ def circuit(x): c_dtypes = [np.complex64, np.complex128] @pytest.mark.parametrize("c_dtype", c_dtypes) - @pytest.mark.parametrize("check", check_state) @pytest.mark.parametrize("wires", wires_list) - def test_density_matrix_c_dtype(self, wires, check, tol, c_dtype): + def test_density_matrix_c_dtype(self, wires, c_dtype): """Test different complex dtype.""" dev = qml.device("default.qubit", wires=2, c_dtype=c_dtype) diff --git a/tests/resource/test_first_quantization.py b/tests/resource/test_first_quantization.py index 818e497db81..ce6a7e493e7 100644 --- a/tests/resource/test_first_quantization.py +++ b/tests/resource/test_first_quantization.py @@ -15,6 +15,7 @@ Unit tests for functions needed for estimating the number of logical qubits and non-Clifford gates for quantum algorithms in first quantization using a plane-wave basis. """ +# pylint: disable=too-many-arguments,protected-access import pytest import pennylane as qml from pennylane import numpy as np diff --git a/tests/resource/test_measurement.py b/tests/resource/test_measurement.py index 869e5ccf3ed..db300c6e914 100644 --- a/tests/resource/test_measurement.py +++ b/tests/resource/test_measurement.py @@ -26,30 +26,30 @@ @pytest.mark.parametrize( - ("coefficients", "error", "shots", "variances"), + ("coefficients", "err", "shots_", "var"), [ (coeffs, error, shots, variances), ], ) -def test_estimate_shots(coefficients, error, shots, variances): +def test_estimate_shots(coefficients, err, shots_, var): r"""Test that the estimate_shots function returns the correct number of measurements.""" - m_novar = qml.resource.estimate_shots(coefficients, error=error) - m_var = qml.resource.estimate_shots(coefficients, variances=variances, error=error) + m_novar = qml.resource.estimate_shots(coefficients, error=err) + m_var = qml.resource.estimate_shots(coefficients, variances=var, error=err) - assert m_novar == shots - assert m_var == shots + assert m_novar == shots_ + assert m_var == shots_ @pytest.mark.parametrize( - ("coefficients", "error", "shots", "variances"), + ("coefficients", "err", "shots_", "var"), [ (coeffs, error, shots, variances), ], ) -def test_estimate_error(coefficients, error, shots, variances): +def test_estimate_error(coefficients, err, shots_, var): r"""Test that the estimate_error function returns the correct error.""" - e_novar = qml.resource.estimate_error(coefficients, shots=shots) - e_var = qml.resource.estimate_error(coefficients, variances=variances, shots=shots) + e_novar = qml.resource.estimate_error(coefficients, shots=shots_) + e_var = qml.resource.estimate_error(coefficients, variances=var, shots=shots_) - assert np.allclose(e_novar, error) - assert np.allclose(e_var, error) + assert np.allclose(e_novar, err) + assert np.allclose(e_var, err) diff --git a/tests/resource/test_second_quantization.py b/tests/resource/test_second_quantization.py index c55a793637e..b1a9db7a5c4 100644 --- a/tests/resource/test_second_quantization.py +++ b/tests/resource/test_second_quantization.py @@ -14,6 +14,7 @@ """ Unit tests for functions needed for resource estimation with the double factorization method. """ +# pylint: disable=too-many-arguments import pytest import pennylane as qml @@ -123,25 +124,15 @@ def test_df_factorization(one, two, n, factors, eigvals, eigvecs, rank_r, rank_m assert np.allclose(est.rank_max, rank_max) -@pytest.mark.parametrize( - ("one", "two", "lamb"), - [ - (one_h2, two_h2, 1.6570514682587973), - ], -) -def test_df_norm(one, two, lamb): +@pytest.mark.parametrize(("one", "two", "lamb"), [(one_h2, two_h2_ph, 1.6570518796336895)]) +def test_df_lamb(one, two, lamb): r"""Test that DoubleFactorization class returns a correct norm.""" est = qml.resource.DoubleFactorization(one, two) assert np.allclose(est.lamb, lamb) -@pytest.mark.parametrize( - ("one", "two", "g_cost", "q_cost"), - [ - (one_h2, two_h2, 876953, 113), - ], -) +@pytest.mark.parametrize(("one", "two", "g_cost", "q_cost"), [(one_h2, two_h2, 876953, 113)]) def test_df_costs(one, two, g_cost, q_cost): r"""Test that DoubleFactorization class returns correct costs.""" est = qml.resource.DoubleFactorization(one, two, chemist_notation=True) @@ -150,12 +141,8 @@ def test_df_costs(one, two, g_cost, q_cost): assert np.allclose(est.qubits, q_cost) -@pytest.mark.parametrize( - ("norm", "error", "cost_ref"), - [ # cost_ref is computed manually - (72.49779513025341, 0.001, 113880), - ], -) +# cost_ref is computed manually +@pytest.mark.parametrize(("norm", "error", "cost_ref"), [(72.49779513025341, 0.001, 113880)]) def test_estimation_cost(norm, error, cost_ref): r"""Test that estimation_cost returns the correct values.""" cost = qml.resource.DoubleFactorization.estimation_cost(norm, error) @@ -163,15 +150,7 @@ def test_estimation_cost(norm, error, cost_ref): assert cost == cost_ref -@pytest.mark.parametrize( - ("norm", "error"), - [ - (5.28, 0.0), - (5.28, -1.0), - (-5.28, 0.01), - (0.0, 0.01), - ], -) +@pytest.mark.parametrize(("norm", "error"), [(5.28, 0.0), (5.28, -1.0), (-5.28, 0.01), (0.0, 0.01)]) def test_estimation_cost_error(norm, error): r"""Test that estimation_cost raises an error with incorrect inputs.""" with pytest.raises(ValueError, match="must be greater than zero"): @@ -211,6 +190,7 @@ def test_estimation_cost_error(norm, error): ) def test_qrom_cost(constants, cost_ref, k_ref): r"""Test that _qrom_cost returns the correct values.""" + # pylint: disable=protected-access cost, k = qml.resource.DoubleFactorization._qrom_cost(constants) assert cost == cost_ref @@ -353,20 +333,9 @@ def test_qubit_cost_error(n, norm, error, rank_r, rank_m, rank_max, br, alpha, b ("one", "two", "eigvals", "lamb_ref"), [ ( - np.array([[-1.25330961e00, 4.01900735e-14], [4.01900735e-14, -4.75069041e-01]]), + one_h2, # two-electron integral is arranged in chemist notation - np.array( - [ - [ - [[6.74755872e-01, -4.60742555e-14], [-4.60742555e-14, 6.63711349e-01]], - [[-4.61020111e-14, 1.81210478e-01], [1.81210478e-01, -4.26325641e-14]], - ], - [ - [[-4.60464999e-14, 1.81210478e-01], [1.81210478e-01, -4.25215418e-14]], - [[6.63711349e-01, -4.28546088e-14], [-4.24105195e-14, 6.97651447e-01]], - ], - ] - ), + two_h2, np.tensor( [[-0.10489852, 0.10672343], [-0.42568824, 0.42568824], [-0.82864211, -0.81447282]] ), diff --git a/tests/tests_passing_pylint.txt b/tests/tests_passing_pylint.txt index 9606665e1ff..f6437e464ca 100644 --- a/tests/tests_passing_pylint.txt +++ b/tests/tests_passing_pylint.txt @@ -20,29 +20,23 @@ tests/legacy/test_pulse_gradient_old.py tests/math/** tests/numpy/** tests/measurements/** -tests/ops/functions/test_bind_new_parameters.py -tests/ops/functions/test_dot.py -tests/ops/functions/test_evolve.py +tests/ops/functions/** tests/ops/op_math/** -tests/ops/qubit/test_matrix_ops.py -tests/ops/qubit/test_special_unitary.py -tests/ops/qubit/test_state_prep.py -tests/ops/qutrit/test_qutrit_observables.py -tests/ops/qutrit/test_qutrit_parametric_ops.py -tests/ops/qutrit/test_qutrit_state_prep.py -tests/optimize/test_riemannian_gradient_optimizer.py +tests/ops/qubit/** +tests/ops/qutrit/** +tests/ops/** +tests/optimize/** tests/pulse/** -tests/pauli/test_pauli_interface.py -tests/qchem/test_givens_rotations.py -tests/qinfo/test_trace_distance.py +tests/pauli/grouping/** +tests/pauli/** +tests/qchem/** +tests/qinfo/** tests/qnn/** +tests/resource/** tests/tape/test_qscript.py tests/templates/test_state_preparations/test_qutrit_basis_state_prep.py tests/templates/test_subroutines/test_basis_rotation.py tests/templates/test_subroutines/test_qsvt.py -tests/resource/test_resource.py -tests/test_grad.py -tests/test_typing.py tests/transforms/test_experimental/** tests/transforms/test_convert_to_numpy_parameters.py tests/transforms/test_decompositions.py