docstr: Tests that per parameter 2R+1 function calls are used for an update step.
docstr_tok: ["Tests","that","per","parameter","2R+1","function","calls","are","used","for","an","update","step","."]
code: 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."""
      # pylint: disable=too-many-arguments
      num_calls = 0
  
      @functools.wraps(fun)
      def _fun(*args, **kwargs):
          nonlocal num_calls
          num_calls += 1
          return fun(*args, **kwargs)
  
      opt = RotosolveOptimizer(substep_optimizer, substep_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
      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)
      opt.step(_fun, *param, nums_frequency=nums_freq)
      assert num_calls == exp_num_calls
  
imports: import functools
  import pytest
  from scipy.optimize import shgo
  import pennylane
  from pennylane import numpy
  from pennylane.utils import _flatten, unflatten
  from pennylane.optimize import RotosolveOptimizer
label_desc: Use image node_id 1 for calling the TestWithClassicalFunction obj's underlying member method code with example usage: obj.test_number_of_function_calls(fun, x_min, param, nums_freq, exp_num_calls, substep_optimizer, substep_kwargs) and returns: fun