def apply_twoqubit_gate(self, gateU, qubit1, qubit2): """ Applies a unitary gate to the two specified qubits. Arguments: gateU unitary to apply as Qobj qubit1 the first qubit qubit2 the second qubit """ # Construct the overall unitary overallU = qp.gate_expand_2toN(gateU, self.activeQubits, qubit1, qubit2) # Qutip distinguishes between system dimensionality and matrix dimensionality # so we need to make sure it knows we are talking about multiple qubits k = int(math.log2(overallU.shape[0])) dimL = [] for j in range(k): dimL.append(2) overallU.dims = [dimL, dimL] self.qubitReg.dims = [dimL, dimL] # Apply the unitary self.qubitReg = overallU * self.qubitReg * overallU.dag()
def apply_double_gate(self, gate, control_name, target_name): if not isinstance(gate, qutip.Qobj): raise TypeError("Gate has to be of type Qobject.") self._lock() control = self._qubit_names.index(control_name) target = self._qubit_names.index(target_name) gate = qutip.gate_expand_2toN(gate, self.N, control, target) self.data = gate * self.data * gate.dag() self._unlock()
def _expand_gate(op: qutip.Qobj, from_qubits: int, to_qubits: int, targets: List[int]): assert len(targets) == from_qubits if from_qubits == 1: return qutip.gate_expand_1toN(op, to_qubits, targets[0]) elif from_qubits == 2: return qutip.gate_expand_2toN(op, to_qubits, targets=targets) else: raise ValueError('Unsupported from_qubits value')
def as_large_qobj_operator(self, num_qubits: int) -> qutip.Qobj: if self.typ.num_qubits == 2: return qutip.gate_expand_2toN(self.as_qobj_operator(), num_qubits, targets=self.qubits) elif self.typ.num_qubits == 1: return qutip.gate_expand_1toN(self.as_qobj_operator(), num_qubits, self.qubits[0]) else: raise NotImplemented('Not implemented for large gates')
def crz(theta, N=None, control=0, target=1): if (control == 1 and target == 0) and N is None: N = 2 if N is not None: return gate_expand_2toN(crz(theta), N, control, target) else: return Qobj([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, np.exp(1j * theta / 2), 0], [0, 0, 0, np.exp(-1j * theta / 2)]], dims=[[2, 2], [2, 2]])
def cy(N=None, control=0, target=1): if (control == 1 and target == 0) and N is None: N = 2 if N is not None: return gate_expand_2toN(cy(), N, control, target) else: return Qobj([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, -1.j], [0, 0, 1.j, 0]], dims=[[2, 2], [2, 2]])
def cu3(theta3, N=None, control=0, target=1): if (control == 1 and target == 0) and N is None: N = 2 if N is not None: return gate_expand_2toN(cu3(theta3), N, control, target) else: return Qobj([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, np.cos(theta3[0] * 0.5) * np.exp(1j * theta3[1] * 0.5) * np.exp(1j * theta3[2] * 0.5), -np.sin(theta3[0] * 0.5) * np.exp(1j * theta3[1] * 0.5) * np.exp(-1j * theta3[2] * 0.5)], [0, 0, np.sin(theta3[0] * 0.5) * np.exp(-1j * theta3[1] * 0.5) * np.exp(1j * theta3[2] * 0.5), np.cos(theta3[0] * 0.5) * np.exp(-1j * theta3[1] * 0.5) * np.exp(-1j * theta3[2] * 0.5)]], dims=[[2, 2], [2, 2]])