RZ: wrong number(s) of dimensions in parameters. Parameters with ndims (2,) passed, (0,) expected

I tried to modify the quantum kernel Demo, but the following problem occurred. I haven’t played Pennylane for a long time, and I didn’t even know that the parameters (“params” in code) now have dimensions. It has always been a one-dimensional vector before. There is also no documentation for the current parameter explaining why it automatically becomes a multidimensional vector. Please give a reasonable explanation of the custom parameter dimension.

def QuantumKernel(x, params, wires):
    """The embedding ansatz"""
    i = 0
    for j, wire in enumerate(wires):
        qml.RZ(params[j], wires=[wire])
        qml.Hadamard(wires=[wire])
        qml.U1(2*x[i], wires=[wire])
        i += 1
    for i in range(len(x)):
        for j in np.arange(i + 1, len(x), 1):
            qml.CNOT(wires=[i,j])
            qml.U1(2*(np.pi - x[i])*(np.pi - x[j]), wires=j)
            qml.CNOT(wires=[i,j])

init_params = random_params(num_wires=X.shape[1], num_layers=1)
print(init_params, init_params.dtype)
kernel_value = kernel(X[0], X[0], init_params)
print(kernel_value)
qml.drawer.use_style('black_white')
fig, ax = qml.draw_mpl(kernel_circuit, show_all_wires=True)(X[0], X[0], init_params)
fig.set_size_inches((10, 5))
#print(f"The kernel value between the first and second datapoint is {kernel_value:.3f}")
init_kernel = lambda x1, x2: kernel(x1, x2, init_params)
print(X)
K_init = qml.kernels.square_kernel_matrix(X, init_kernel, assume_normalized_kernel=True)

with np.printoptions(precision=3, suppress=True):
    print(K_init)

[[[5.79224151 0.81098457 1.42666494]
[3.92941447 0.87498623 4.73891606]]] float64

ValueError Traceback (most recent call last)
Input In [102], in <cell line: 3>()
1 init_params = random_params(num_wires=X.shape[1], num_layers=1)
2 print(init_params, init_params.dtype)
----> 3 kernel_value = kernel(X[0], X[0], init_params)
4 print(kernel_value)
5 qml.drawer.use_style(‘black_white’)

Input In [100], in kernel(x1, x2, params)
42 def kernel(x1, x2, params):
—> 43 return kernel_circuit(x1, x2, params)[0]

File d:\miniconda3\lib\site-packages\pennylane\qnode.py:610, in QNode.call(self, *args, **kwargs)
607 set_shots(self._original_device, override_shots)(self._update_gradient_fn)()
609 # construct the tape
–> 610 self.construct(args, kwargs)
612 cache = self.execute_kwargs.get(“cache”, False)
613 using_custom_cache = (
614 hasattr(cache, “getitem”)
615 and hasattr(cache, “setitem”)
616 and hasattr(cache, “delitem”)
617 )

File d:\miniconda3\lib\site-packages\pennylane\qnode.py:525, in QNode.construct(self, args, kwargs)
522 self._tape = qml.tape.QuantumTape()
524 with self.tape:
–> 525 self._qfunc_output = self.func(*args, **kwargs)
526 self._tape._qfunc_output = self._qfunc_output
528 params = self.tape.get_parameters(trainable_only=False)

Input In [100], in kernel_circuit(x1, x2, params)
36 @qml.qnode(dev)
37 def kernel_circuit(x1, x2, params):
—> 38 QuantumKernel(x1, params, wires)
39 adjoint_ansatz(x2, params, wires)
40 return qml.probs(wires=wires)

Input In [100], in QuantumKernel(x, params, wires)
8 i = 0
9 for j, wire in enumerate(wires):
—> 10 qml.RZ(params[j], wires=[wire])
11 qml.Hadamard(wires=[wire])
12 qml.U1(2*x[i], wires=[wire])

File d:\miniconda3\lib\site-packages\pennylane\ops\qubit\parametric_ops.py:253, in RZ.init(self, phi, wires, do_queue, id)
252 def init(self, phi, wires, do_queue=True, id=None):
–> 253 super().init(phi, wires=wires, do_queue=do_queue, id=id)

File d:\miniconda3\lib\site-packages\pennylane\operation.py:1521, in Operation.init(self, wires, do_queue, id, *params)
1518 def init(self, *params, wires=None, do_queue=True, id=None):
1520 self._inverse = False
-> 1521 super().init(*params, wires=wires, do_queue=do_queue, id=id)
1523 # check the grad_recipe validity
1524 if self.grad_recipe is None:
1525 # Make sure grad_recipe is an iterable of correct length instead of None

File d:\miniconda3\lib\site-packages\pennylane\operation.py:894, in Operator.init(self, wires, do_queue, id, *params)
888 if self.num_wires not in {AllWires, AnyWires} and len(self._wires) != self.num_wires:
889 raise ValueError(
890 f"{self.name}: wrong number of wires. "
891 f"{len(self._wires)} wires given, {self.num_wires} expected."
892 )
–> 894 self._check_batching(params)
896 self.data = list(params) #: list[Any]: parameters of the operator
898 if do_queue:

File d:\miniconda3\lib\site-packages\pennylane\operation.py:935, in Operator.check_batching(self, params)
930 ndims_matches = [
931 (ndim == exp_ndim, ndim == exp_ndim + 1)
932 for ndim, exp_ndim in zip(ndims, self.ndim_params)
933 ]
934 if not all(correct or batched for correct, batched in ndims_matches):
–> 935 raise ValueError(
936 f"{self.name}: wrong number(s) of dimensions in parameters. "
937 f"Parameters with ndims {ndims} passed, {self.ndim_params} expected."
938 )
940 first_dims = [
941 qml.math.shape§[0] for (
, batched), p in zip(ndims_matches, params) if batched
942 ]
943 if not qml.math.allclose(first_dims, first_dims[0]):

ValueError: RZ: wrong number(s) of dimensions in parameters. Parameters with ndims (2,) passed, (0,) expected.

Hi @RX1, it’s great to see that you’re playing with PennyLane again!

‘params’ has always had a dimension. In fact, since you define the initial parameters (init_params), you are defining the dimension of params. However, not any dimension of init_params works, and this is why you’re getting the error.

The RZ gate only takes 2 parameters: an angle and a wire (or set of wires). If init_params[0] isn’t a number, then you will get an error.

In your case I can see that init_params[0] is a matrix so the RZ gate throws an error. My recommendation is to take a look at the shape of your data to make sure that it aligns with the shape of the original dataset in the demo. This will help reduce problems.