示例#1
0
 def measure(self, qubit_name, non_destructive):
     res = None
     M_0 = qutip.fock(2, 0).proj()
     M_1 = qutip.fock(2, 1).proj()
     self._lock()
     target = self._qubit_names.index(qubit_name)
     if self.N > 1:
         M_0 = qutip.gate_expand_1toN(M_0, self.N, target)
         M_1 = qutip.gate_expand_1toN(M_1, self.N, target)
     pr_0 = qutip.expect(M_0, self.data)
     pr_1 = qutip.expect(M_1, self.data)
     outcome = int(np.random.choice([0, 1], 1, p=[pr_0, pr_1]))
     if outcome == 0:
         self.data = M_0 * self.data * M_0.dag() / pr_0
         res = 0
     else:
         # M_1 = qutip.gate_expand_1toN(M_1, self.N, target)
         self.data = M_1 * self.data * M_1.dag() / pr_1
         res = 1
     if non_destructive is False:
         i_list = [x for x in range(self.N)]
         i_list.remove(target)
         self._qubit_names.remove(qubit_name)
         self.N = self.N - 1
         if len(i_list) > 0:
             self.data = self.data.ptrace(i_list)
         else:
             self.data = qutip.Qobj()
     self._unlock()
     return res
示例#2
0
 def _apply(self, unitary: qt.Qobj, ids: List[int]):
     if len(ids) == 1:
         matrix = qt.gate_expand_1toN(
             unitary, self.capacity, ids[0]
         )
     else:
         raise ValueError("Only single-bit unitary matrices are supported.")
     self.register_state = matrix * self.register_state
示例#3
0
 def apply_single_gate(self, gate, qubit_name):
     if not isinstance(gate, qutip.Qobj):
         raise TypeError("Gate has to be of type Qobject.")
     self._lock()
     target = self._qubit_names.index(qubit_name)
     gate = qutip.gate_expand_1toN(gate, self.N, 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')
示例#5
0
 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')
示例#6
0
def u3(theta3, N=None, target=0):
    if N is not None:
        return gate_expand_1toN(u3(theta3), N, target)

    else:
        mat = np.array([[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)],
                   [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)]], dtype='complex128')

        return Qobj(mat, dims=[[2],[2]])
示例#7
0
    def measure_qubit_inplace(self, qubitNum):
        """
        Measures the desired qubit in the standard basis. This returns the classical outcome. The quantum register
        is in the post-measurment state corresponding to the obtained outcome.

        Arguments:
        qubitNum	qubit to be measured
        """

        # Check we have such a qubit...
        if (qubitNum + 1) > self.activeQubits:
            raise quantumError("No such qubit to be measured.")

        # Construct the two measurement operators, and put them at the right position
        v0 = qp.basis(2, 0)
        P0 = v0 * v0.dag()
        M0 = qp.gate_expand_1toN(P0, self.activeQubits, qubitNum)

        v1 = qp.basis(2, 1)
        P1 = v1 * v1.dag()
        M1 = qp.gate_expand_1toN(P1, self.activeQubits, qubitNum)

        # Compute the success probabilities
        obj = M0 * self.qubitReg
        p0 = obj.tr().real
        obj = M1 * self.qubitReg
        p1 = obj.tr().real

        # Sample the measurement outcome from these probabilities
        outcome = int(np.random.choice([0, 1], 1, p=[p0, p1]))

        # Compute the post-measurement state, getting rid of the measured qubit
        if outcome == 0:
            self.qubitReg = M0 * self.qubitReg * M0.dag() / p0
        else:
            self.qubitReg = M1 * self.qubitReg * M1.dag() / p1

        # return measurement outcome
        return outcome
示例#8
0
 def measure(self) -> bool:
     projectors = [
         qt.gate_expand_1toN(
             qt.basis(2, outcome) * qt.basis(2, outcome).dag(),
             self.parent.capacity,
             self.id
         )
         for outcome in (0, 1)
     ]
     post_measurement_states = [
         projector * self.parent.register_state
         for projector in projectors
     ]
     probabilities = [
         post_measurement_state.norm() ** 2
         for post_measurement_state in post_measurement_states
     ]
     sample = np.random.choice([0, 1], p=probabilities)
     self.parent.register_state = post_measurement_states[sample].unit()
     return int(sample)
示例#9
0
    def apply_onequbit_gate(self, gateU, qubitNum):
        """
        Applies a unitary gate to the specified qubit.

        Arguments:
        gateU   	unitary to apply as Qobj
        qubitNum 	the number of the qubit this gate is applied to
        """

        # Compute the overall unitary, identity everywhere with gateU at position qubitNum
        overallU = qp.gate_expand_1toN(gateU, self.activeQubits, qubitNum)

        # 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()
示例#10
0
def h(N=None, target=0):

    if N is not None:
        return gate_expand_1toN(h(), N, target)
    else:
        return Qobj(np.array([[1.0, 1.0], [1.0, -1.0]], dtype='complex128') / np.sqrt(2.0), dims=[[2],[2]])
示例#11
0
def z(N=None, target=0):
    if N is not None:
        return gate_expand_1toN(z(), N, target)
    else:
        return Qobj(np.array([[1., 0.0], [0.0, -1.]], dtype='complex128'), dims=[[2],[2]])
示例#12
0
def y(N=None, target=0):

    if N is not None:
        return gate_expand_1toN(y(), N, target)
    else:
        return Qobj(np.array([[0., -1j], [1j, 0.]], dtype='complex128'), dims=[[2],[2]])