示例#1
0
    def transcoding_cliffords(self, other):
        r"""
        Returns an iterator onto all :class:`qecc.Clifford` objects which 
        take states specified by ``self``, and
        return states specified by ``other``.

        :arg other: :class:`qecc.StabilizerCode`
        """
        #Preliminaries:

        stab_in = self.group_generators
        stab_out = other.group_generators
        xs_in = self.logical_xs
        xs_out = other.logical_xs
        zs_in = self.logical_zs
        zs_out = other.logical_zs

        nq_in = len(stab_in[0])
        nq_out = len(stab_out[0])
        nq_anc = abs(nq_in - nq_out)

        #Decide left side:
        if nq_in < nq_out:
            stab_left = stab_out
            xs_left = xs_out
            zs_left = zs_out
            stab_right = stab_in
            xs_right = xs_in
            zs_right = zs_in
        else:
            stab_right = stab_out
            xs_right = xs_out
            zs_right = zs_out
            stab_left = stab_in
            xs_left = xs_in
            zs_left = zs_in

        cliff_xouts_left = stab_left + xs_left
        cliff_zouts_left = [Unspecified] * len(stab_left) + zs_left

        cliff_left = next(
            c.Clifford(cliff_xouts_left,
                       cliff_zouts_left).constraint_completions())
        list_left = cliff_left.xout + cliff_left.zout

        for mcset in p.mutually_commuting_sets(n_elems=len(stab_left) -
                                               len(stab_right),
                                               n_bits=nq_anc):
            temp_xouts_right = p.pad(stab_right, lower_right=mcset) + [
                elem & p.eye_p(nq_anc) for elem in xs_right
            ]
            temp_zouts_right = [Unspecified] * len(stab_left) + [
                elem & p.eye_p(nq_anc) for elem in zs_right
            ]
        for completion in c.Clifford(
                temp_xouts_right, temp_zouts_right).constraint_completions():
            if nq_in < nq_out:
                yield c.gen_cliff(completion.xout + completion.zout, list_left)
            else:
                yield c.gen_cliff(list_left, completion.xout + completion.zout)
示例#2
0
 def encoding_cliffords(self):
     r"""
     Returns an iterator onto all Clifford operators that encode into this
     stabilizer code, starting from an input register such that the state to
     be encoded is a state of the first :math:`k` qubits, and such that the
     rest of the qubits in the input register are initialized to
     :math:`\left|0\right\rangle`.
     
     :yields: instances ``C`` of :class:`qecc.Clifford` such that
         ``C(q.StabilizerCode.unencoded_state(k, n - k))`` equals this code.
     """
     C = c.Clifford(self.logical_xs + ([Unspecified] * self.n_constraints),
                    self.logical_zs + self.group_generators)
     return C.constraint_completions()
示例#3
0
    def as_clifford(self):
        """
        Converts a Pauli into a Clifford which changes the signs of input
        Paulis. 
        :returns: A Clifford representing conjugation by this Pauli
        operator.
        :rtype: :class:`qecc.Clifford`
        """
        Xs, Zs = elem_gens(len(self))
        for P in chain(Xs, Zs):
            if com(self, P) == 1:
                P.mul_phase(2)

        return cc.Clifford(Xs, Zs)
示例#4
0
    def star_decoder(self, for_enc=None, as_dict=False):
        r"""
        Returns a tuple of a decoding Clifford and a :class:`qecc.PauliList`
        specifying the recovery operation to perform as a function of the result
        of a :math:`Z^{\otimes{n - k}}` measurement on the ancilla register.
        
        For syndromes corresponding to errors of weight greater than the distance,
        the relevant element of the recovery list will be set to
        :obj:`qecc.Unspecified`.
        
        :param for_enc: If not ``None``, specifies to use a given Clifford
            operator as the encoder, instead of the first element yielded by
            :meth:`encoding_cliffords`.
        :param bool as_dict: If ``True``, returns a dictionary from recovery
            operators to syndromes that indicate that recovery.
        """
        def error_to_pauli(error):
            if error == p.I.as_clifford():
                return "I"
            if error == p.X.as_clifford():
                return "X"
            if error == p.Y.as_clifford():
                return "Y"
            if error == p.Z.as_clifford():
                return "Z"

        if for_enc is None:
            encoder = next(self.encoding_cliffords())
        else:
            encoder = for_enc
        decoder = encoder.inv()

        errors = pc.PauliList(p.eye_p(self.nq)) + pc.PauliList(
            p.paulis_by_weight(self.nq, self.n_correctable))

        syndrome_dict = defaultdict(lambda: Unspecified)
        syndrome_meas = [
            p.elem_gen(self.nq, idx, 'Z')
            for idx in range(self.nq_logical, self.nq)
        ]

        for error in errors:
            effective_gate = decoder * error.as_clifford() * encoder
            # FIXME: the following line emulates measurement until we have a real
            #        measurement simulation method.
            syndrome = tuple(
                [effective_gate(meas).ph / 2 for meas in syndrome_meas])

            recovery = "".join([
                # FIXME: the following is a broken hack to get the phases on the logical qubit register.
                error_to_pauli(
                    c.Clifford([effective_gate.xout[idx][idx]],
                               [effective_gate.zout[idx][idx]]))
                for idx in range(self.nq_logical)
            ])

            # For degenerate codes, the syndromes can collide, so long as we
            # correct the same way for each.
            if syndrome in syndrome_dict and syndrome_dict[
                    syndrome] != recovery:
                raise RuntimeError(
                    'Syndrome {} has collided.'.format(syndrome))

            syndrome_dict[syndrome] = recovery

        if as_dict:
            outdict = dict()
            keyfn = lambda syndrome_recovery: syndrome_recovery[1]
            data = sorted(list(syndrome_dict.items()), key=keyfn)
            for recovery, syndrome_group in it.groupby(data, keyfn):
                outdict[recovery] = [syn[0] for syn in syndrome_group]

            return decoder, outdict

        else:
            recovery_list = pc.PauliList(
                syndrome_dict[syndrome]
                for syndrome in it.product(list(range(2)),
                                           repeat=self.n_constraints))

            return decoder, recovery_list