KeyError: tensor(0, requires_grad=True)

I’m having the following problem when running my code, it’s an error that occurs when drawing a quantum circuit diagram.

KeyError                                  Traceback (most recent call last)
Input In [7], in <cell line: 50>()
     43     return qml.expval(qml.PauliZ(2 * wire))
     49 qml.drawer.use_style('black_white')
---> 50 fig, ax = qml.draw_mpl(Circ, show_all_wires=True)(X[0], X[1], params_init)
     51 fig.set_size_inches((10, 5))

File d:\miniconda3\lib\site-packages\pennylane\drawer\draw.py:446, in draw_mpl.<locals>.wrapper(*args, **kwargs_qnode)
    442     qnode.expansion_strategy = original_expansion_strategy
    444 _wire_order = wire_order or qnode.device.wires
--> 446 return tape_mpl(
    447     qnode.qtape,
    448     wire_order=_wire_order,
    449     show_all_wires=show_all_wires,
    450     decimals=decimals,
    451     style=style,
    452     **kwargs,
    453 )

File d:\miniconda3\lib\site-packages\pennylane\drawer\tape_mpl.py:353, in tape_mpl(tape, wire_order, show_all_wires, decimals, style, **kwargs)
    351     use_style(style)
    352 try:
--> 353     return _tape_mpl(
    354         tape, wire_order=wire_order, show_all_wires=show_all_wires, decimals=decimals, **kwargs
    355     )
    356 finally:
    357     if style and has_mpl:
    358         # we don't want to mess with how it modifies whether the interface is interactive
    359         # but we want to restore everything else

File d:\miniconda3\lib\site-packages\pennylane\drawer\tape_mpl.py:106, in _tape_mpl(tape, wire_order, show_all_wires, decimals, **kwargs)
    102 fontsize = kwargs.get("fontsize", None)
    104 wire_map = convert_wire_order(tape, wire_order=wire_order, show_all_wires=show_all_wires)
--> 106 layers = drawable_layers(tape.operations, wire_map=wire_map)
    108 n_layers = len(layers)
    109 n_wires = len(wire_map)

File d:\miniconda3\lib\site-packages\pennylane\drawer\drawable_layers.py:101, in drawable_layers(ops, wire_map)
     99     op_occupied_wires = mapped_wires
    100 else:
--> 101     mapped_wires = {wire_map[wire] for wire in op.wires}
    102     # get all integers from the minimum to the maximum
    103     min_wire = min(mapped_wires)

File d:\miniconda3\lib\site-packages\pennylane\drawer\drawable_layers.py:101, in <setcomp>(.0)
     99     op_occupied_wires = mapped_wires
    100 else:
--> 101     mapped_wires = {wire_map[wire] for wire in op.wires}
    102     # get all integers from the minimum to the maximum
    103     min_wire = min(mapped_wires)

KeyError: tensor(0, requires_grad=True)

@isaacdevlugt
@Maria_Schuld
@CatalinaAlbornoz

Hello!

We could use more information in order to reproduce the error and see what’s going on. Could you send us the code of the circuit that you’d like to plot?

Cheers,

Alvaro

Sorry, there is no intention to publicize the code yet, but it would be great to be able to point out the problem in private.

Using AmplitudeEmbedding`:
>print(Circ(X[0], X[1], params_init))


KeyError                                  Traceback (most recent call last)
File d:\miniconda3\lib\site-packages\pennylane\devices\default_qubit.py:219, in DefaultQubit.map_wires(self, wires)
    218 try:
--> 219     mapped_wires = [self.wire_map[w] for w in wires]
    220 except KeyError as e:

File d:\miniconda3\lib\site-packages\pennylane\devices\default_qubit.py:219, in <listcomp>(.0)
    218 try:
--> 219     mapped_wires = [self.wire_map[w] for w in wires]
    220 except KeyError as e:

KeyError: tensor(0, requires_grad=True)

The above exception was the direct cause of the following exception:

WireError                                 Traceback (most recent call last)
Input In [21], in <cell line: 46>()
     43     Ansatz(params[(3 * wire): (4 * wire)], wire, (2 * wire))
     44     return qml.expval(qml.PauliZ(3))
---> 46 print(Circ(X[0], X[1], params_init))
     48 '''
     49 qml.drawer.use_style('black_white')
     50 fig, ax = qml.draw_mpl(Circ, show_all_wires=True)(X[0], X[1], params_init)
     51 fig.set_size_inches((10, 5))
     52 '''

File d:\miniconda3\lib\site-packages\pennylane\qnode.py:847, in QNode.__call__(self, *args, **kwargs)
    843     self._update_original_device()
    845     return res
--> 847 res = qml.execute(
    848     [self.tape],
    849     device=self.device,
    850     gradient_fn=self.gradient_fn,
    851     interface=self.interface,
    852     gradient_kwargs=self.gradient_kwargs,
    853     override_shots=override_shots,
    854     **self.execute_kwargs,
    855 )
    857 if old_interface == "auto":
    858     self.interface = "auto"

File d:\miniconda3\lib\site-packages\pennylane\interfaces\execution.py:651, in execute(tapes, device, gradient_fn, interface, mode, gradient_kwargs, cache, cachesize, max_diff, override_shots, expand_fn, max_expansion, device_batch_transform)
    647     return batch_fn(res)
    649 if gradient_fn == "backprop" or interface is None:
    650     return batch_fn(
--> 651         qml.interfaces.cache_execute(
    652             batch_execute, cache, return_tuple=False, expand_fn=expand_fn
    653         )(tapes)
    654     )
    656 # the default execution function is batch_execute
    657 execute_fn = qml.interfaces.cache_execute(batch_execute, cache, expand_fn=expand_fn)

File d:\miniconda3\lib\site-packages\pennylane\interfaces\execution.py:206, in cache_execute.<locals>.wrapper(tapes, **kwargs)
    202         return (res, []) if return_tuple else res
    204 else:
    205     # execute all unique tapes that do not exist in the cache
--> 206     res = fn(execution_tapes.values(), **kwargs)
    208 final_res = []
    210 for i, tape in enumerate(tapes):

File d:\miniconda3\lib\site-packages\pennylane\interfaces\execution.py:131, in cache_execute.<locals>.fn(tapes, **kwargs)
    129 def fn(tapes: Sequence[QuantumTape], **kwargs):  # pylint: disable=function-redefined
    130     tapes = [expand_fn(tape) for tape in tapes]
--> 131     return original_fn(tapes, **kwargs)

File d:\miniconda3\lib\contextlib.py:79, in ContextDecorator.__call__.<locals>.inner(*args, **kwds)
     76 @wraps(func)
     77 def inner(*args, **kwds):
     78     with self._recreate_cm():
---> 79         return func(*args, **kwds)

File d:\miniconda3\lib\site-packages\pennylane\_qubit_device.py:656, in QubitDevice.batch_execute(self, circuits)
    653     self.reset()
    655     # TODO: Insert control on value here
--> 656     res = self.execute(circuit)
    657     results.append(res)
    659 if self.tracker.active:

File d:\miniconda3\lib\site-packages\pennylane\_qubit_device.py:432, in QubitDevice.execute(self, circuit, **kwargs)
    429 self.check_validity(circuit.operations, circuit.observables)
    431 # apply all circuit operations
--> 432 self.apply(circuit.operations, rotations=circuit.diagonalizing_gates, **kwargs)
    434 # generate computational basis samples
    435 if self.shots is not None or circuit.is_sampled:

File d:\miniconda3\lib\site-packages\pennylane\devices\default_qubit.py:258, in DefaultQubit.apply(self, operations, rotations, **kwargs)
    252     raise DeviceError(
    253         f"Operation {operation.name} cannot be used after other Operations have already been applied "
    254         f"on a {self.short_name} device."
    255     )
    257 if isinstance(operation, QubitStateVector):
--> 258     self._apply_state_vector(operation.parameters[0], operation.wires)
    259 elif isinstance(operation, BasisState):
    260     self._apply_basis_state(operation.parameters[0], operation.wires)

File d:\miniconda3\lib\site-packages\pennylane\devices\default_qubit.py:687, in DefaultQubit._apply_state_vector(self, state, device_wires)
    678 """Initialize the internal state vector in a specified state.
    679 
    680 Args:
   (...)
    683     device_wires (Wires): wires that get initialized in the state
    684 """
    686 # translate to wire labels used by device
--> 687 device_wires = self.map_wires(device_wires)
    688 dim = 2 ** len(device_wires)
    690 state = self._asarray(state, dtype=self.C_DTYPE)

File d:\miniconda3\lib\site-packages\pennylane\devices\default_qubit.py:221, in DefaultQubit.map_wires(self, wires)
    219     mapped_wires = [self.wire_map[w] for w in wires]
    220 except KeyError as e:
--> 221     raise WireError(
    222         f"Did not find some of the wires {wires.labels} on device with wires {self.wires.labels}."
    223     ) from e
    225 return mapped_wires

WireError: Did not find some of the wires (tensor(0, requires_grad=True), tensor(1, requires_grad=True), tensor(2, requires_grad=True)) on device with wires (0, 1, 2, 3, 4, 5).
Using MottonenStatePreparation:
>print(Circ(X[0], X[1], params_init))

---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
File d:\miniconda3\lib\site-packages\pennylane\devices\default_qubit.py:219, in DefaultQubit.map_wires(self, wires)
    218 try:
--> 219     mapped_wires = [self.wire_map[w] for w in wires]
    220 except KeyError as e:

File d:\miniconda3\lib\site-packages\pennylane\devices\default_qubit.py:219, in <listcomp>(.0)
    218 try:
--> 219     mapped_wires = [self.wire_map[w] for w in wires]
    220 except KeyError as e:

KeyError: tensor(0, requires_grad=True)

The above exception was the direct cause of the following exception:

WireError                                 Traceback (most recent call last)
Input In [38], in <cell line: 48>()
     44     Ansatz(params[(3 * wire): (4 * wire)], wire, (2 * wire))
     45     return qml.expval(qml.PauliZ(3))
---> 48 print(Circ(X[0], X[1], params_init))
     50 '''
     51 qml.drawer.use_style('black_white')
     52 fig, ax = qml.draw_mpl(Circ, show_all_wires=True)(X[0], X[1], params_init)
     53 fig.set_size_inches((10, 5))
     54 '''

File d:\miniconda3\lib\site-packages\pennylane\qnode.py:847, in QNode.__call__(self, *args, **kwargs)
    843     self._update_original_device()
    845     return res
--> 847 res = qml.execute(
    848     [self.tape],
    849     device=self.device,
    850     gradient_fn=self.gradient_fn,
    851     interface=self.interface,
    852     gradient_kwargs=self.gradient_kwargs,
    853     override_shots=override_shots,
    854     **self.execute_kwargs,
    855 )
    857 if old_interface == "auto":
    858     self.interface = "auto"

File d:\miniconda3\lib\site-packages\pennylane\interfaces\execution.py:651, in execute(tapes, device, gradient_fn, interface, mode, gradient_kwargs, cache, cachesize, max_diff, override_shots, expand_fn, max_expansion, device_batch_transform)
    647     return batch_fn(res)
    649 if gradient_fn == "backprop" or interface is None:
    650     return batch_fn(
--> 651         qml.interfaces.cache_execute(
    652             batch_execute, cache, return_tuple=False, expand_fn=expand_fn
    653         )(tapes)
    654     )
    656 # the default execution function is batch_execute
    657 execute_fn = qml.interfaces.cache_execute(batch_execute, cache, expand_fn=expand_fn)

File d:\miniconda3\lib\site-packages\pennylane\interfaces\execution.py:206, in cache_execute.<locals>.wrapper(tapes, **kwargs)
    202         return (res, []) if return_tuple else res
    204 else:
    205     # execute all unique tapes that do not exist in the cache
--> 206     res = fn(execution_tapes.values(), **kwargs)
    208 final_res = []
    210 for i, tape in enumerate(tapes):

File d:\miniconda3\lib\site-packages\pennylane\interfaces\execution.py:131, in cache_execute.<locals>.fn(tapes, **kwargs)
    129 def fn(tapes: Sequence[QuantumTape], **kwargs):  # pylint: disable=function-redefined
    130     tapes = [expand_fn(tape) for tape in tapes]
--> 131     return original_fn(tapes, **kwargs)

File d:\miniconda3\lib\contextlib.py:79, in ContextDecorator.__call__.<locals>.inner(*args, **kwds)
     76 @wraps(func)
     77 def inner(*args, **kwds):
     78     with self._recreate_cm():
---> 79         return func(*args, **kwds)

File d:\miniconda3\lib\site-packages\pennylane\_qubit_device.py:656, in QubitDevice.batch_execute(self, circuits)
    653     self.reset()
    655     # TODO: Insert control on value here
--> 656     res = self.execute(circuit)
    657     results.append(res)
    659 if self.tracker.active:

File d:\miniconda3\lib\site-packages\pennylane\_qubit_device.py:432, in QubitDevice.execute(self, circuit, **kwargs)
    429 self.check_validity(circuit.operations, circuit.observables)
    431 # apply all circuit operations
--> 432 self.apply(circuit.operations, rotations=circuit.diagonalizing_gates, **kwargs)
    434 # generate computational basis samples
    435 if self.shots is not None or circuit.is_sampled:

File d:\miniconda3\lib\site-packages\pennylane\devices\default_qubit.py:269, in DefaultQubit.apply(self, operations, rotations, **kwargs)
    267                 self._debugger.snapshots[len(self._debugger.snapshots)] = state_vector
    268     else:
--> 269         self._state = self._apply_operation(self._state, operation)
    271 # store the pre-rotated state
    272 self._pre_rotated_state = self._state

File d:\miniconda3\lib\site-packages\pennylane\devices\default_qubit.py:303, in DefaultQubit._apply_operation(self, state, operation)
    300     return self._apply_diagonal_unitary(state, matrix, wires)
    301 if len(wires) <= 2:
    302     # Einsum is faster for small gates
--> 303     return self._apply_unitary_einsum(state, matrix, wires)
    305 return self._apply_unitary(state, matrix, wires)

File d:\miniconda3\lib\site-packages\pennylane\devices\default_qubit.py:829, in DefaultQubit._apply_unitary_einsum(self, state, mat, wires)
    815 r"""Apply multiplication of a matrix to subsystems of the quantum state.
    816 
    817 This function uses einsum instead of tensordot. This approach is only
   (...)
    826     array[complex]: output state
    827 """
    828 # translate to wire labels used by device
--> 829 device_wires = self.map_wires(wires)
    831 dim = 2 ** len(device_wires)
    832 batch_size = self._get_batch_size(mat, (dim, dim), dim**2)

File d:\miniconda3\lib\site-packages\pennylane\devices\default_qubit.py:221, in DefaultQubit.map_wires(self, wires)
    219     mapped_wires = [self.wire_map[w] for w in wires]
    220 except KeyError as e:
--> 221     raise WireError(
    222         f"Did not find some of the wires {wires.labels} on device with wires {self.wires.labels}."
    223     ) from e
    225 return mapped_wires

WireError: Did not find some of the wires (tensor(0, requires_grad=True),) on device with wires (0, 1, 2, 3, 4, 5).

I found that the problem comes from the AmplitudeEmbedding function and the MottonenStatePreparation function, when using the AmplitudeEmbedding function there is a problem with multiple wires not being found, while using the MottonenStatePreparation function makes fewer wires not being found, but the problem still exists

wires = np.arange(wires_start, wires_end).tolist()

Thank you for posting the solution here @RX1 !