Hi there,
With the 0.32 update, there is the feature to reset wires with mid-circuit measurements, but I’m not following the usage entirely.
In the example on the ‘measurements’ page of the pennylane docs, 3 wires are used to reset the ‘1’ wire. When I try this with 2 wires, I get an error as below.
For large circuits that already have many wires, where one might like to reset an ancilla wire instead of using another, this seems that this is just adding another wire. I am wondering if there is a way to reset a wire without needing an extra wire in the device (or if this is the intended behaviour).
@qml.qnode(qml.device("default.qubit", wires=2))
def func():
qml.PauliX(1)
m_0 = qml.measure(1, reset=True)
return qml.probs(wires=[1])
func()
Resulting in:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
File ~/qdrive/anaconda3/envs/penny/lib/python3.10/site-packages/pennylane/wires.py:239, in Wires.index(self, wire)
238 try:
--> 239 return self._labels.index(wire)
240 except ValueError as e:
ValueError: tuple.index(x): x not in tuple
The above exception was the direct cause of the following exception:
WireError Traceback (most recent call last)
Cell In[14], line 7
5 #qml.PauliX(1)
6 return qml.probs(wires=[1])
----> 7 func()
File ~/qdrive/anaconda3/envs/penny/lib/python3.10/site-packages/pennylane/qnode.py:989, in QNode.__call__(self, *args, **kwargs)
986 self.execute_kwargs.pop("mode")
988 # pylint: disable=unexpected-keyword-arg
--> 989 res = qml.execute(
990 (self._tape,),
991 device=self.device,
992 gradient_fn=self.gradient_fn,
993 interface=self.interface,
994 transform_program=self.transform_program,
995 gradient_kwargs=self.gradient_kwargs,
996 override_shots=override_shots,
997 **self.execute_kwargs,
998 )
1000 res = res[0]
1002 # convert result to the interface in case the qfunc has no parameters
File ~/qdrive/anaconda3/envs/penny/lib/python3.10/site-packages/pennylane/interfaces/execution.py:636, in execute(tapes, device, gradient_fn, interface, transform_program, grad_on_execution, gradient_kwargs, cache, cachesize, max_diff, override_shots, expand_fn, max_expansion, device_batch_transform)
634 # Exiting early if we do not need to deal with an interface boundary
635 if no_interface_boundary_required:
--> 636 results = inner_execute(tapes)
637 results = batch_fn(results)
638 return program_post_processing(results)
File ~/qdrive/anaconda3/envs/penny/lib/python3.10/site-packages/pennylane/interfaces/execution.py:255, in _make_inner_execute.<locals>.inner_execute(tapes, **_)
253 if numpy_only:
254 tapes = tuple(qml.transforms.convert_to_numpy_parameters(t) for t in tapes)
--> 255 return cached_device_execution(tapes)
File ~/qdrive/anaconda3/envs/penny/lib/python3.10/site-packages/pennylane/interfaces/execution.py:377, in cache_execute.<locals>.wrapper(tapes, **kwargs)
372 return (res, []) if return_tuple else res
374 else:
375 # execute all unique tapes that do not exist in the cache
376 # convert to list as new device interface returns a tuple
--> 377 res = list(fn(tuple(execution_tapes.values()), **kwargs))
379 final_res = []
381 for i, tape in enumerate(tapes):
File ~/qdrive/anaconda3/envs/penny/lib/python3.10/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 ~/qdrive/anaconda3/envs/penny/lib/python3.10/site-packages/pennylane/_qubit_device.py:629, in QubitDevice.batch_execute(self, circuits)
624 for circuit in circuits:
625 # we need to reset the device here, else it will
626 # not start the next computation in the zero state
627 self.reset()
--> 629 res = self.execute(circuit)
630 results.append(res)
632 if self.tracker.active:
File ~/qdrive/anaconda3/envs/penny/lib/python3.10/site-packages/pennylane/_qubit_device.py:337, in QubitDevice.execute(self, circuit, **kwargs)
334 self.check_validity(circuit.operations, circuit.observables)
336 # apply all circuit operations
--> 337 self.apply(circuit.operations, rotations=self._get_diagonalizing_gates(circuit), **kwargs)
339 # generate computational basis samples
340 if self.shots is not None or circuit.is_sampled:
File ~/qdrive/anaconda3/envs/penny/lib/python3.10/site-packages/pennylane/devices/default_qubit.py:294, in DefaultQubit.apply(self, operations, rotations, **kwargs)
292 self._state = self._apply_parametrized_evolution(self._state, operation)
293 else:
--> 294 self._state = self._apply_operation(self._state, operation)
296 # store the pre-rotated state
297 self._pre_rotated_state = self._state
File ~/qdrive/anaconda3/envs/penny/lib/python3.10/site-packages/pennylane/devices/default_qubit.py:331, in DefaultQubit._apply_operation(self, state, operation)
329 if str(operation.name) in self._apply_ops: # cast to string because of Tensor
330 shift = int(self._ndim(state) > self.num_wires)
--> 331 axes = [ax + shift for ax in self.wires.indices(wires)]
332 return self._apply_ops[operation.name](state, axes)
334 matrix = self._asarray(self._get_unitary_matrix(operation), dtype=self.C_DTYPE)
File ~/qdrive/anaconda3/envs/penny/lib/python3.10/site-packages/pennylane/wires.py:265, in Wires.indices(self, wires)
262 if not isinstance(wires, Iterable):
263 return [self.index(wires)]
--> 265 return [self.index(w) for w in wires]
File ~/qdrive/anaconda3/envs/penny/lib/python3.10/site-packages/pennylane/wires.py:265, in <listcomp>(.0)
262 if not isinstance(wires, Iterable):
263 return [self.index(wires)]
--> 265 return [self.index(w) for w in wires]
File ~/qdrive/anaconda3/envs/penny/lib/python3.10/site-packages/pennylane/wires.py:241, in Wires.index(self, wire)
239 return self._labels.index(wire)
240 except ValueError as e:
--> 241 raise WireError(f"Wire with label {wire} not found in {self}.") from e
WireError: Wire with label 2 not found in <Wires = [0, 1]>.
Using Python 3.10.11 and pennylane 0.32.0