# Compute\_decomposition() got multiple values for argument 'wires' and using qml.ctrl with functions

**URL:** <https://discuss.pennylane.ai/t/compute-decomposition-got-multiple-values-for-argument-wires-and-using-qml-ctrl-with-functions/4695>\
**Category:** PennyLane Help\
**Created:** [June 6, 2024, 6:02pm UTC](https://discuss.pennylane.ai/t/compute-decomposition-got-multiple-values-for-argument-wires-and-using-qml-ctrl-with-functions/4695 "2024-06-06T18:02:54Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![sv2954](https://avatars.discourse-cdn.com/v4/letter/s/71c47a/32.png) [@sv2954](https://discuss.pennylane.ai/u/sv2954)\
**Post date:** [June 6, 2024, 6:02pm UTC](https://discuss.pennylane.ai/t/compute-decomposition-got-multiple-values-for-argument-wires-and-using-qml-ctrl-with-functions/4695/1 "2024-06-06T18:02:54Z")

</div>

I’m trying to make the layers in my parameterized circuit controlled by others qubits so I’m making my own operator for it, only to find that the compute\_decomposition() method throwing me errors and I don’t know how to fix it.

```auto
# Put code here
# Quantum simulator
dev = qml.device("lightning.qubit", wires=list(range(num_qubits+class_qubits+6)))
# Enable CUDA device if available
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

class Layer(qml.operation.Operation):
    
    num_wires = qml.operation.AnyWires
    par_domain = 'R'
    grad_method = 'A'
    # control_wires = [4,5]
    def __init__ (self, thetas, wires, id= None):
        # print(thetas)
        print(qml.wires.Wires(wires))
        super(). __init__ (thetas[0], thetas[1], thetas[2], thetas[3], wires = qml.wires.Wires(wires), id = id)

    
    @property
    def num_params(self):
        return 4
    

    @staticmethod
    def compute_decomposition(thetas, wires):
        return [qml.RX(thetas[0], wires[0]),
        qml.RZ(thetas[1], wires[1]),
        qml.RX(thetas[2], wires[2]),
        qml.CNOT(wires[:2]),
        qml.MultiRZ(thetas[3], [wires[0], wires[1], wires[2]]),
        qml.CNOT([wires[1], wires[2]]),
        qml.CY([wires[0],wires[2]])]

@qml.qnode(dev, diff_method="parameter-shift")
def quantum_circuit(noise, params):
    const = 4
    measurements = []
    # for i in range((num_qubits+num_ancilla)):
    qml.Rot(noise[0], noise[1], noise[2], wires=0)
    qml.Rot(noise[3], noise[4], noise[5], wires=1)
    qml.Rot(noise[6], noise[7], noise[8], wires=2)
    qml.Barrier()
    # Repeated layer
    qml.ctrl(Layer(params[0:4], wires = [0,1,2]), control = [4,5], control_values = (0,0))
    qml.ctrl(Layer(params[4:8], wires = [0,1,2]), control = [4,5], control_values = (0,1))
    qml.ctrl(Layer(params[8:12], wires = [0,1,2]), control = [4,5], control_values = (1,0))
    qml.ctrl(Layer(params[12:16], wires =[0,1,2]), control = [4,5], control_values = (1,1))
    qml.Barrier()
    return qml.probs(wires = list(range(num_qubits)))

I'm not really sure how the above was any different than the examples in the documents, but when I run that example there is no issue. Maybe I'm missing something. I appreciate the help!
```

---

<div class="post-metadata">

**Author:** ![CatalinaAlbornoz](https://yyz2.discourse-cdn.com/flex012/user_avatar/discuss.pennylane.ai/catalinaalbornoz/32/1196_2.png) [@CatalinaAlbornoz](https://discuss.pennylane.ai/u/CatalinaAlbornoz)\
**Post date:** [June 6, 2024, 10:53pm UTC](https://discuss.pennylane.ai/t/compute-decomposition-got-multiple-values-for-argument-wires-and-using-qml-ctrl-with-functions/4695/2 "2024-06-06T22:53:11Z")

</div>

Hi @sv2954 , welcome to the Forum! Could you please post:

- The output of qml.about()
- Your full error message. Even if it’s long it’s helpful to see the origin of the problem. Thanks!
- What you’re using for noise and params (so that I can try to run your circuit)

---

<div class="post-metadata">

**Author:** ![sv2954](https://avatars.discourse-cdn.com/v4/letter/s/71c47a/32.png) [@sv2954](https://discuss.pennylane.ai/u/sv2954)\
**Post date:** [June 7, 2024, 1:12am UTC](https://discuss.pennylane.ai/t/compute-decomposition-got-multiple-values-for-argument-wires-and-using-qml-ctrl-with-functions/4695/3 "2024-06-07T01:12:06Z")

</div>

qml.about()

```auto
# Put code here

Name: PennyLane
Version: 0.36.0
Summary: PennyLane is a cross-platform Python library for quantum computing, quantum machine learning, and quantum chemistry. Train a quantum computer the same way as a neural network.
Home-page: https://github.com/PennyLaneAI/pennylane
Author: 
Author-email: 
License: Apache License 2.0
Location: /opt/homebrew/lib/python3.10/site-packages
Requires: appdirs, autograd, autoray, cachetools, networkx, numpy, pennylane-lightning, requests, rustworkx, scipy, semantic-version, toml, typing-extensions
Required-by: PennyLane_Lightning

Platform info: macOS-13.0-arm64-arm-64bit
Python version: 3.10.9
Numpy version: 1.24.1
Scipy version: 1.10.0
Installed devices:
- default.clifford (PennyLane-0.36.0)
- default.gaussian (PennyLane-0.36.0)
- default.mixed (PennyLane-0.36.0)
- default.qubit (PennyLane-0.36.0)
- default.qubit.autograd (PennyLane-0.36.0)
- default.qubit.jax (PennyLane-0.36.0)
- default.qubit.legacy (PennyLane-0.36.0)
- default.qubit.tf (PennyLane-0.36.0)
- default.qubit.torch (PennyLane-0.36.0)
- default.qutrit (PennyLane-0.36.0)
- default.qutrit.mixed (PennyLane-0.36.0)
- null.qubit (PennyLane-0.36.0)
- lightning.qubit (PennyLane_Lightning-0.36.0)

Error Message:
line 49
     46 noise = [0,0,0,0,0,0,0,0,0,0,0,0]
  47 weights = [0,1,0,1,2,3,1,2,1,2,0,1,0,1,2,3,1,2,1,2,4,4,4,4,4,4, 0,1,0,1,2,3,1,2,1,2,0,1,0,1,2,3,1,2,1,2,4,4,4,4,4,4]
---> 49 quantum_circuit(noise,weights)
     50 # qml.draw_mpl(mini_circuit)(noise, weights)
     51 # qml.draw_mpl(mini_circuit2)(weights[:3*4])
     52 # qml.draw_mpl(mini_circuit3)(weights[:3*4])
     53 # plt.show()

File /opt/homebrew/lib/python3.10/site-packages/pennylane/workflow/qnode.py:1098, in QNode. __call__ (self, *args, **kwargs)
   1095 self._update_gradient_fn(shots=override_shots, tape=self._tape)
   1097 try:
-> 1098 res = self._execution_component(args, kwargs, override_shots=override_shots)
   1099 finally:
   1100 if old_interface == "auto":

File /opt/homebrew/lib/python3.10/site-packages/pennylane/workflow/qnode.py:1052, in QNode._execution_component(self, args, kwargs, override_shots)
   1049 full_transform_program.prune_dynamic_transform()
   1051 # pylint: disable=unexpected-keyword-arg
-> 1052 res = qml.execute(
   1053 (self._tape,),
   1054 device=self.device,
   1055 gradient_fn=self.gradient_fn,
   1056 interface=self.interface,
   1057 transform_program=full_transform_program,
   1058 config=config,
   1059 gradient_kwargs=self.gradient_kwargs,
   1060 override_shots=override_shots,
   1061 **self.execute_kwargs,
   1062 )
   1063 res = res[0]
   1065 # convert result to the interface in case the qfunc has no parameters

File /opt/homebrew/lib/python3.10/site-packages/pennylane/workflow/execution.py:600, in execute(tapes, device, gradient_fn, interface, transform_program, config, grad_on_execution, gradient_kwargs, cache, cachesize, max_diff, override_shots, expand_fn, max_expansion, device_batch_transform, device_vjp)
    595 if not device_batch_transform:
    596 warnings.warn(
    597 "device batch transforms cannot be turned off with the new device interface.",
    598 UserWarning,
    599 )
--> 600 tapes, post_processing = transform_program(tapes)
    601 else:
    602 # TODO: Remove once old device are removed
    603 tapes, program_post_processing = transform_program(tapes)

File /opt/homebrew/lib/python3.10/site-packages/pennylane/transforms/core/transform_program.py:509, in TransformProgram. __call__ (self, tapes)
    507 if self._argnums is not None and self._argnums[i] is not None:
    508 tape.trainable_params = self._argnums[i][j]
--> 509 new_tapes, fn = transform(tape, *targs, **tkwargs)
    510 execution_tapes.extend(new_tapes)
    512 fns.append(fn)

File /opt/homebrew/lib/python3.10/site-packages/pennylane/devices/preprocess.py:340, in decompose(tape, stopping_condition, stopping_condition_shots, skip_initial_state_prep, decomposer, max_expansion, name)
    334 try:
    335 # don't decompose initial operations if its StatePrepBase
    336 prep_op = (
    337 [tape[0]] if isinstance(tape[0], StatePrepBase) and skip_initial_state_prep else []
    338 )
--> 340 new_ops = [
    341 final_op
    342 for op in tape.operations[bool(prep_op) :]
    343 for final_op in _operator_decomposition_gen(
    344 op,
    345 stopping_condition,
    346 decomposer=decomposer,
    347 max_expansion=max_expansion,
    348 name=name,
    349 )
    350 ]
    351 except RecursionError as e:
    352 raise DeviceError(
    353 "Reached recursion limit trying to decompose operations. "
    354 "Operator decomposition may have entered an infinite loop."
    355 ) from e

File /opt/homebrew/lib/python3.10/site-packages/pennylane/devices/preprocess.py:340, in <listcomp>(.0)
    334 try:
    335 # don't decompose initial operations if its StatePrepBase
    336 prep_op = (
    337 [tape[0]] if isinstance(tape[0], StatePrepBase) and skip_initial_state_prep else []
    338 )
--> 340 new_ops = [
    341 final_op
    342 for op in tape.operations[bool(prep_op) :]
    343 for final_op in _operator_decomposition_gen(
    344 op,
    345 stopping_condition,
    346 decomposer=decomposer,
    347 max_expansion=max_expansion,
    348 name=name,
    349 )
    350 ]
    351 except RecursionError as e:
    352 raise DeviceError(
    353 "Reached recursion limit trying to decompose operations. "
    354 "Operator decomposition may have entered an infinite loop."
    355 ) from e

File /opt/homebrew/lib/python3.10/site-packages/pennylane/devices/preprocess.py:62, in _operator_decomposition_gen(op, acceptance_function, decomposer, max_expansion, current_depth, name)
     60 else:
     61 try:
---> 62 decomp = decomposer(op)
     63 current_depth += 1
     64 except qml.operation.DecompositionUndefinedError as e:

File /opt/homebrew/lib/python3.10/site-packages/pennylane/devices/preprocess.py:328, in decompose.<locals>.decomposer(op)
    327 def decomposer(op):
--> 328 return op.decomposition()

File /opt/homebrew/lib/python3.10/site-packages/pennylane/operation.py:1285, in Operator.decomposition(self)
   1273 def decomposition(self) -> List["Operator"]:
   1274 r"""Representation of the operator as a product of other operators.
   1275 
   1276 .. math:: O = O_1 O_2 \dots O_n
   (...)
   1283 list[Operator]: decomposition of the operator
   1284 """
-> 1285 return self.compute_decomposition(
   1286 *self.parameters, wires=self.wires, **self.hyperparameters
   1287 )

TypeError: Layer.compute_decomposition() got multiple values for argument 'wires'
```

---

<div class="post-metadata">

**Author:** ![CatalinaAlbornoz](https://yyz2.discourse-cdn.com/flex012/user_avatar/discuss.pennylane.ai/catalinaalbornoz/32/1196_2.png) [@CatalinaAlbornoz](https://discuss.pennylane.ai/u/CatalinaAlbornoz)\
**Post date:** [June 8, 2024, 1:57am UTC](https://discuss.pennylane.ai/t/compute-decomposition-got-multiple-values-for-argument-wires-and-using-qml-ctrl-with-functions/4695/4 "2024-06-08T01:57:19Z")

</div>

Thanks for adding this info @sv2954 .

It looks like the workflow isn’t designed to use a layer as an operator. I understand that you want to apply the controlled operation of a layer but I think there may be a better way to accomplish this.

Let me think of a solution and get back to you next week.

---

<div class="post-metadata">

**Author:** ![CatalinaAlbornoz](https://yyz2.discourse-cdn.com/flex012/user_avatar/discuss.pennylane.ai/catalinaalbornoz/32/1196_2.png) [@CatalinaAlbornoz](https://discuss.pennylane.ai/u/CatalinaAlbornoz)\
**Post date:** [June 11, 2024, 1:13am UTC](https://discuss.pennylane.ai/t/compute-decomposition-got-multiple-values-for-argument-wires-and-using-qml-ctrl-with-functions/4695/5 "2024-06-11T01:13:23Z")

</div>

Hi @sv2954 ,

It looks like you were overcomplicating things a bit.  
The issue was in how you were using [qml.ctrl](https://docs.pennylane.ai/en/stable/code/api/pennylane.ctrl.html). Notice that you can apply the control to a function but then you need to pass the function arguments **outside** of the control. In the example below the function takes a wire as the argument. However to find the controlled version of the function you only pass the name of the function. The arguments go outside.

```auto
def func(arg):
        qml.RX(theta, wires=arg)

qml.ctrl(func, control=[control_wires])(function_argument)

```

Here’s and example working for what you were looking to do.

```auto
import pennylane as qml

dev = qml.device("lightning.qubit", wires=8)

def Layer(thetas, wires):
  qml.RX(thetas[0], wires[0])
  qml.RZ(thetas[1], wires[1])
  qml.RX(thetas[2], wires[2])
  qml.CNOT(wires[:2])
  qml.MultiRZ(thetas[3], [wires[0], wires[1], wires[2]])
  qml.CNOT([wires[1], wires[2]])
  qml.CY([wires[0],wires[2]])

@qml.qnode(dev, diff_method="parameter-shift")
def quantum_circuit(noise, params):
    const = 4
    measurements = []
    qml.Rot(noise[0], noise[1], noise[2], wires=0)
    qml.Rot(noise[3], noise[4], noise[5], wires=1)
    qml.Rot(noise[6], noise[7], noise[8], wires=2)
    qml.Barrier()
    # Repeated layer
    qml.ctrl(Layer, control = [4,5], control_values = (0,0))(params[0:4], wires = [0,1,2])
    qml.ctrl(Layer, control = [4,5], control_values = (0,1))(params[4:8], wires = [0,1,2])
    qml.ctrl(Layer, control = [4,5], control_values = (1,0))(params[8:12], wires = [0,1,2])
    qml.ctrl(Layer, control = [4,5], control_values = (1,1))(params[12:16], wires =[0,1,2])
    qml.Barrier()
    return qml.probs()

noise = [0,0,0,0,0,0,0,0,0,0,0,0]
weights = [0,1,0,1,2,3,1,2,1,2,0,1,0,1,2,3,1,2,1,2,4,4,4,4,4,4, 0,1,0,1,2,3,1,2,1,2,0,1,0,1,2,3,1,2,1,2,4,4,4,4,4,4]

qml.draw_mpl(quantum_circuit)(noise, weights)
quantum_circuit(noise, weights)

```

I hope this helps you!
