The number of circuit execution in parameter-shift

I’m studying a fantastic recent update of PennyLane.

Release notes — PennyLane 0.16.0 documentation

In the version, qml.specs was introduced.
From the release note,

dev = qml.device('default.qubit', wires=4)

@qml.qnode(dev, diff_method='parameter-shift')
def circuit(x, y):
    qml.RX(x[0], wires=0)
    qml.Toffoli(wires=(0, 1, 2))
    qml.CRY(x[1], wires=(0, 1))
    qml.Rot(x[2], x[3], y, wires=0)
    return qml.expval(qml.PauliZ(0)), qml.expval(qml.PauliX(1))

x = np.array([0.05, 0.1, 0.2, 0.3], requires_grad=True)
y = np.array(0.4, requires_grad=False)
specs_func = qml.specs(circuit)
specs_func(x, y)

The result is,

{...
 'num_observables': 2,
 'num_diagonalizing_gates': 1,
 'num_used_wires': 3,
 'depth': 4,
 'num_trainable_params': 4,
 'num_parameter_shift_executions': 11,
 ...}

My question is , how the “num_parameter_shift_executions” has been calculated?
Since the number of parameters is 4, the number of foward prop would be 2 x num. of params.

Thanks for the question @Kuma-quant .

The example was chosen in part because of the peculiarities of controlled rotation gates. qml.CRY has a four-term parameter-shift rule, so it contributes four executions.

  • the forward pass contributes 1
  • RX contributes 2
  • CRY contributes 4
  • Rot contributes 4, two for each trainable parameter

1+2+4+4 = 11

You can double check this by running qml.grad(circuit)(x,y) and inspecting dev.num_executions before and afterward.

Thanks!
I got it.

The four term parameter-shift rule was also found in,
qml.CRY — PennyLane 0.16.0 documentation

Thank you for your kind advice.

Thanks @Kuma-quant! Feel free to reach out again if you have any more questions.