I aim to perform post-selection on the first outcome of the third qubit. Subsequently, I wish to execute a partial trace on this third subsystem. However, I am facing a limitation: post-selection is only feasible with default.qubit, which, unfortunately, does not support the use of noisy channels. How can I effectively carry out post-selection with ‘‘default.mixed’’?’
import pennylane as qml
from pennylane import numpy as np
dev=qml.device('default.mixed',wires=3)
p=0.1
def circuit1(params):
qml.Hadamard(wires=0)
qml.CNOT(wires=[0,1])
qml.U3(params[0],params[1],params[2],wires=1)
qml.U3(params[3],params[4],params[5],wires=2)
qml.CNOT(wires=[2,1])
qml.RZ(params[6],wires=1)
qml.RY(params[7],wires=2)
qml.CNOT(wires=[1,2])
qml.RY(params[8],wires=2)
qml.CNOT(wires=[2,1])
qml.U3(params[9],params[10],params[11],wires=1)
qml.U3(params[12],params[13],params[14],wires=2)
qml.PhaseDamping(p,wires=1)
qml.PhaseDamping(p,wires=2)
qml.adjoint(qml.U3(params[12],params[13],params[14],wires=2))
qml.adjoint(qml.U3(params[9],params[10],params[11],wires=1))
qml.adjoint(qml.CNOT(wires=[2,1]))
qml.adjoint(qml.RY(params[8],wires=2))
qml.adjoint(qml.CNOT(wires=[1,2]))
qml.adjoint(qml.RY(params[7],wires=2))
qml.adjoint(qml.RZ(params[6],wires=1))
qml.adjoint(qml.CNOT(wires=[2,1]))
qml.adjoint(qml.U3(params[3],params[4],params[5],wires=2))
qml.adjoint(qml.U3(params[0],params[1],params[2],wires=1))
params = np.array(range(0, 15))
circuit_drawer = qml.draw_mpl(circuit1)(params)
pr = np.kron(np.eye(4), np.array([[1, 0], [0, 0]]))
@qml.qnode(dev)
def circuit2(params):
np.dot(np.dot(pr.conj().T,circuit1(params)), pr)#Post selection
return qml.density_matrix(wires=[0,1])
error message
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[13], line 1
----> 1 print(circuit2(params))
File ~\anaconda3\Lib\site-packages\pennylane\qnode.py:976, in QNode.__call__(self, *args, **kwargs)
973 kwargs["shots"] = _get_device_shots(self._original_device)
975 # construct the tape
--> 976 self.construct(args, kwargs)
978 cache = self.execute_kwargs.get("cache", False)
979 using_custom_cache = (
980 hasattr(cache, "__getitem__")
981 and hasattr(cache, "__setitem__")
982 and hasattr(cache, "__delitem__")
983 )
File ~\anaconda3\Lib\site-packages\pennylane\qnode.py:862, in QNode.construct(self, args, kwargs)
859 self.interface = qml.math.get_interface(*args, *list(kwargs.values()))
861 with qml.queuing.AnnotatedQueue() as q:
--> 862 self._qfunc_output = self.func(*args, **kwargs)
864 self._tape = QuantumScript.from_queue(q, shots)
866 params = self.tape.get_parameters(trainable_only=False)
Cell In[12], line 3, in circuit2(params)
1 @qml.qnode(dev)
2 def circuit2(params):
----> 3 np.dot(np.dot(pr.conj().T,circuit1(params)), pr)
4 return qml.density_matrix(wires=[0,1])
File ~\anaconda3\Lib\site-packages\pennylane\numpy\wrapper.py:117, in tensor_wrapper.<locals>._wrapped(*args, **kwargs)
114 tensor_kwargs["requires_grad"] = _np.any([i.requires_grad for i in tensor_args])
116 # evaluate the original object
--> 117 res = obj(*args, **kwargs)
119 if isinstance(res, _np.ndarray):
120 # only if the output of the object is a ndarray,
121 # then convert to a PennyLane tensor
122 res = tensor(res, **tensor_kwargs)
File ~\anaconda3\Lib\site-packages\autograd\tracer.py:48, in primitive.<locals>.f_wrapped(*args, **kwargs)
46 return new_box(ans, trace, node)
47 else:
---> 48 return f_raw(*args, **kwargs)
File <__array_function__ internals>:180, in dot(*args, **kwargs)
File ~\anaconda3\Lib\site-packages\pennylane\numpy\tensor.py:155, in tensor.__array_ufunc__(self, ufunc, method, *inputs, **kwargs)
151 args = [i.unwrap() if hasattr(i, "unwrap") else i for i in inputs]
153 # call the ndarray.__array_ufunc__ method to compute the result
154 # of the vectorized ufunc
--> 155 res = super().__array_ufunc__(ufunc, method, *args, **kwargs)
157 if isinstance(res, Operator):
158 return res
TypeError: unsupported operand type(s) for *: 'float' and 'DensityMatrixMP'