class_docstr: Test the utility function _one_parameter_generators.
class_docstr_tok: ["Test","the","utility","function","_one_parameter_generators","."]
docstr: Test that the generators are correct for a Hamiltonian with multiple
  constant non-commuting terms.
docstr_tok: ["Test","that","the","generators","are","correct","for","a","Hamiltonian","with","multiple","constant","non-commuting","terms","."]
code: def test_with_noncommuting_const_terms_ham(self, terms, t):
      """Test that the generators are correct for a Hamiltonian with multiple
      constant non-commuting terms."""
      import jax
      import jax.numpy as jnp
  
      jax.config.update("jax_enable_x64", True)
  
      def manual_matrix(params):
          """Compute the matrix of a constant pulse with non-commuting Hamiltonian terms."""
          summands = [
              p * expand_matrix(term.matrix(), term.wires, H.wires)
              for p, term in zip(params, terms)
          ]
          exp = jnp.sum(
              jnp.array(summands),
              axis=0,
          )
          return jax.scipy.linalg.expm(-1j * T * exp)
  
      num_terms = len(terms)
      H = qml.math.dot(
          [qml.pulse.constant for _ in range(num_terms)], terms
      )
      params = [
          jnp.array(0.4),
          jnp.array(0.9),
          jnp.array(-0.5),
          jnp.array(0.28),
      ][:num_terms]
      T = t[1] - t[0]
  
      op = qml.evolve(H)(params, t)
      gens = _one_parameter_generators(op)
  
      # op has as many parameters in its parameter input list as there are terms,
      # so generators should be a tuple with as many entries as Hamiltonian terms.
      assert isinstance(gens, tuple)
      assert len(gens) == num_terms
      dim = 2 ** len(H.wires)
      params = [p.astype(jnp.complex128) for p in params]
      # Manually compute the matrix of the pulse and its derivative. Compose the two into the
      # effective generator. Omega = U* @ dU
      U = manual_matrix(params)
      expected = [
          U.conj().T @ j
          for j in jax.jacobian(manual_matrix, holomorphic=True)(params)
      ]
      for gen, expec in zip(gens, expected):
          # The effective generator should have the shape of the pulse
          assert gen.shape == (dim, dim)
          assert qml.math.allclose(gen, expec)
  
imports: import copy
  import pytest
  import numpy
  import pennylane
  from pennylane import numpy
  from pennylane.ops.qubit.special_unitary import pauli_basis_matrices, pauli_basis_strings
  from pennylane.math import expand_matrix
  from pennylane.gradients.pulse_gradient_odegen import _generate_tapes_and_coeffs, pulse_odegen, _insert_op, _nonzero_coeffs_and_words, _one_parameter_generators, _one_parameter_paulirot_coeffs, _parshift_and_contract
label_desc: Use image node_id 3 for calling the TestOneParameterGenerators obj's underlying member method code with example usage: obj.test_with_noncommuting_const_terms_ham(terms, t) and returns: jax