Ejemplo n.º 1
0
 def remove_ket1(box):
     if not isinstance(box, Ket):
         return box
     x_gates = Circuit.id(0)
     for bit in box.bitstring:
         x_gates = x_gates @ (X if bit else Circuit.id(1))
     return Ket(*(len(box.bitstring) * (0, ))) >> x_gates
Ejemplo n.º 2
0
def tensor_from_counts(counts, post_selection=None, scalar=1, normalize=True):
    """
    Parameters
    ----------
    counts : dict
        From bitstrings to counts.
    post_selection : dict, optional
        From qubit indices to bits.
    scalar : complex, optional
        Scale the output using the Born rule.
    normalize : bool, optional
        Whether to normalize the counts.

    Returns
    -------
    tensor : discopy.tensor.Tensor
        Of dimension :code:`n_qubits * (2, )` for :code:`n_qubits` the number
        of post-selected qubits.
    """
    if normalize:
        counts = probs_from_counts(counts)
    n_qubits = len(list(counts.keys()).pop())
    if post_selection:
        post_selected = dict()
        for bitstring, count in counts.items():
            if all(bitstring[qubit] == bit
                   for qubit, bit in post_selection.items()):
                post_selected.update({
                    tuple(bit for qubit, bit in enumerate(bitstring) if qubit not in post_selection):
                    count
                })
        n_qubits -= len(post_selection.keys())
        counts = post_selected
    array = np.zeros(n_qubits * (2, ))
    for bitstring, count in counts.items():
        array += count * Ket(*bitstring).array
    array = abs(scalar)**2 * array
    return Tensor(Dim(1), Dim(*(n_qubits * (2, ))), array)
Ejemplo n.º 3
0
def to_tk(self):
    def remove_ket1(box):
        if not isinstance(box, Ket):
            return box
        x_gates = Circuit.id(0)
        for bit in box.bitstring:
            x_gates = x_gates @ (X if bit else Circuit.id(1))
        return Ket(*(len(box.bitstring) * (0, ))) >> x_gates

    def swap(tk_circ, i, j):
        old = Qubit('q', i)
        tmp = Qubit('tmp', 0)
        new = Qubit('q', j)
        tk_circ.rename_units({old: tmp})
        tk_circ.rename_units({new: old})
        tk_circ.rename_units({tmp: new})

    def prepare_qubit(tk_circ, left, box, right):
        if len(right) > 0:
            renaming = dict()
            for i in range(len(left), tk_circ.n_qubits):
                old = Qubit('q', i)
                new = Qubit('q', i + len(box.cod))
                renaming.update({old: new})
            tk_circ.rename_units(renaming)
        tk_circ.add_blank_wires(len(box.cod))

    def add_gate(tk_circ, box, off):
        qubits = [off + j for j in range(len(box.dom))]
        if isinstance(box, (Rx, Rz)):
            tk_circ.__getattribute__(box.name[:2])(2 * box.phase, *qubits)
        elif isinstance(box, CRz):
            tk_circ.__getattribute__(box.name[:3])(2 * box.phase, *qubits)
        else:
            tk_circ.__getattribute__(box.name)(*qubits)

    def measure_qubit(tk_circ, left, box, right):
        if len(right) > 0:
            renaming = dict()
            for i, _ in enumerate(box.dom):
                old = Qubit('q', len(left) + i)
                tmp = Qubit('tmp', i)
                renaming.update({old: tmp})
            for i, _ in enumerate(right):
                old = Qubit('q', len(left @ box.dom) + i)
                new = Qubit('q', len(left) + i)
                renaming.update({old: new})
            tk_circ.rename_units(renaming)
            renaming = dict()
            for j, _ in enumerate(box.dom):
                tmp = Qubit('tmp', j)
                new = Qubit('q', len(left @ right) + j)
                renaming.update({tmp: new})
            tk_circ.rename_units(renaming)
        return {
            len(left @ right) + j: box.bitstring[j]
            for j, _ in enumerate(box.dom)
        }

    circuit = CircuitFunctor(ob=Quiver(len), ar=Quiver(remove_ket1))(self)
    if circuit.dom != PRO(0):
        circuit = Ket(*(len(circuit.dom) * (0, ))) >> circuit
    tk_circ = TketCircuit()
    for left, box, right in circuit.layers:
        if isinstance(box, Ket):
            prepare_qubit(tk_circ, left, box, right)
        elif isinstance(box, Bra):
            tk_circ.post_selection.update(
                measure_qubit(tk_circ, left, box, right))
        elif box == SWAP:
            swap(tk_circ, len(left), len(left) + 1)
        elif box.dom == box.cod == PRO(0):
            tk_circ.scalar *= box.array[0]
        else:
            add_gate(tk_circ, box, len(left))
    return tk_circ