コード例 #1
0
    def get_possible_decoding_strats(self):
        num_qubits = len(self.gstate)
        # print("num_qubits", num_qubits)
        # get all possible 2^N stabilizers.
        # TODO: to be improved checking only "smart" stabilizers.
        all_stabs = list(q.from_generators(self.gstate.stab_gens))
        poss_stabs_list = []
        for stab_ix1 in range(1, (2 ** num_qubits) - 1):
            for stab_ix2 in range(stab_ix1, 2 ** num_qubits):
                stab1 = all_stabs[stab_ix1].op
                stab2 = all_stabs[stab_ix2].op
                ## checks which qubits have anticommuting Paulis
                anticomm_qbts = [qbt for qbt in range(num_qubits) if single_qubit_commute(stab1, stab2, qbt)]

                ## checks that there are exactly two qubits with anticommuting Paulis: the input and an output
                if len(anticomm_qbts) == 2 and self.in_qubit in anticomm_qbts:
                    measurement = [stab1[qbt] if stab1[qbt] != 'I' else stab2[qbt] for qbt in range(num_qubits)]
                    other_meas_qubits = [qbt for qbt in range(num_qubits)
                                         if measurement[qbt] != 'I' and qbt not in anticomm_qbts]
                    meas_weight = num_qubits - measurement.count('I')
                    Z_weight = measurement.count('Z') / (meas_weight + 1)
                    poss_stabs_list.append(
                        [anticomm_qbts, other_meas_qubits, [stab1, stab2], measurement, meas_weight, Z_weight])
                    # print(stab1, stab2, anticomm_qbts, other_meas_qubits, measurement, meas_weight)
        # ## order them such that we always prefer mstrategies with smaller weight, and with more Zs in the
        # non-trivial paulis.
        poss_stabs_list.sort(key=lambda x: x[4] - x[5])
        return poss_stabs_list
コード例 #2
0
def get_possible_stabs_meas(gstate, in_qubit=0):
    num_qubits = len(gstate)
    # print("num_qubits", num_qubits)

    # get all possible 2^N stabilizers.
    # TODO: to be improved checking only "smart" stabilizers.
    all_stabs = list(q.from_generators(gstate.stab_gens))

    poss_stabs_list = []
    for stab_ix1 in range(1, (2 ** num_qubits) - 1):
        for stab_ix2 in range(stab_ix1, 2 ** num_qubits):
            stab1 = all_stabs[stab_ix1].op
            stab2 = all_stabs[stab_ix2].op
            ## checks which qubits have anticommuting Paulis
            anticomm_qbts = [qbt for qbt in range(num_qubits) if single_qubit_commute(stab1, stab2, qbt)]

            ## checks that there are exactly two qubits with anticommuting Paulis: the input and an output
            if len(anticomm_qbts) == 2 and in_qubit in anticomm_qbts:
                measurement = [stab1[qbt] if stab1[qbt] is not 'I' else stab2[qbt] for qbt in range(num_qubits)]
                other_meas_qubits = [qbt for qbt in range(num_qubits)
                                     if measurement[qbt] is not 'I' and qbt not in anticomm_qbts]
                meas_weight = num_qubits - measurement.count('I')
                poss_stabs_list.append([anticomm_qbts, other_meas_qubits, [stab1, stab2], measurement, meas_weight])
                # print(stab1, stab2, anticomm_qbts, other_meas_qubits, measurement, meas_weight)

    poss_stabs_list.sort(key=lambda x: x[4])

    return poss_stabs_list
コード例 #3
0
def ind_meas_EC_decoder(graph_state, ind_meas_op, in_qubit, include_direct_meas=False, max_error_num=None):
    if ind_meas_op not in ('X', 'Y', 'Z'):
        raise ValueError('The indirect measument Pauli operator needs to be one of (X, Y, Z)')
    ### gets all stabs for a graph
    all_stabs = [this_op.op for this_op in q.from_generators(graph_state.stab_gens)]
    all_stabs.remove('I' * len(all_stabs[0]))
    ### filter stabilizers to get only those for indirect measurement
    filtered_stabs_ind_meas = filter_stabs_input_op_compatible(all_stabs, ind_meas_op, in_qubit)
    ### identify all possible indirect measurement families
    meas_families = find_single_op_ind_meas_EC_families(filtered_stabs_ind_meas, ind_meas_op, in_qubit)
    # print(meas_families)
    ## select best family
    best_meas = max(meas_families, key=lambda x: len(meas_families[x][1]))
    best_fam = meas_families[best_meas]
    ## run decoder:  build syndromes lookup table and return it
    return calculate_syndromes_dictionary_single_ind_meas(best_meas, best_fam[0], best_fam[1], in_qubit,
                                                          include_direct_meas=include_direct_meas,
                                                          max_error_num=max_error_num)
コード例 #4
0
 def get_indirect_meas_stabs(self):
     num_qubits = len(self.gstate)
     # print("num_qubits", num_qubits)
     # get all possible 2^N stabilizers.
     # TODO: to be improved checking only "smart" stabilizers.
     all_stabs = q.from_generators(self.gstate.stab_gens)
     poss_stabs_list = []
     for this_stab0 in all_stabs:
         this_stab = this_stab0.op
         if this_stab[self.in_qubit] == self.indmeas_pauli:
             meas_weight = num_qubits - this_stab.count('I')
             Z_weight = this_stab.count('Z') / (meas_weight + 1)
             meas_qubits = [qbt for qbt in range(num_qubits)
                            if ((qbt != self.in_qubit) and (this_stab[qbt] != 'I'))]
             ### order them such that we always prefer mstrategies with smaller weight, and with more Zs in the non-trivial paulis.
             poss_stabs_list.append([this_stab, meas_qubits, meas_weight, Z_weight])
     poss_stabs_list.sort(key=lambda x: x[2] - x[3])
     return poss_stabs_list
コード例 #5
0
def teleportation_EC_decoder(graph_state, in_qubit, pref_pauli='Z', max_error_num=None):
    num_qbts = len(graph_state)
    ### gets all stabs for a graph
    all_stabs = [this_op.op for this_op in q.from_generators(graph_state.stab_gens)]
    all_stabs.remove('I' * len(all_stabs[0]))
    ### identify all possible teleportation measurement families
    meas_families = find_all_ind_meas_strats(all_stabs, in_qubit, pref_pauli=pref_pauli)
    # print('All families:')
    # print(meas_families, len(meas_families))
    ## select best family
    if meas_families:
        best_meas = max(meas_families, key=lambda x: len(meas_families[x][1]) + (
            0 if len(meas_families[x][1]) == 0 else count_target_pauli_in_stabs(meas_families[x][1], pref_pauli) / (
                    num_qbts * len(meas_families[x][1]))))
        best_fam = meas_families[best_meas]
        # print('best_meas', best_meas)
        # print('best_fam', best_fam)
        return calculate_syndromes_dictionary_teleport(best_meas, best_fam[0][1][0], best_fam[0][1][1], best_fam[1],
                                                       best_fam[0][0][0], best_fam[0][0][1], max_error_num=max_error_num)
    else:
        return False
コード例 #6
0
    # gstate = graphstate_from_nodes_and_edges(graph_nodes, graph_edges)

    ### Generate random graph
    # graph = gen_random_connected_graph(6)
    # gstate = GraphState(graph)

    #########################################################################################
    ################################### SINGLE TEST - DECODING ##############################
    #########################################################################################
    gstate.image(input_qubits=[in_qubit])
    plt.show()

    ind_meas_op = 'Y'

    ### gets all stabs for a graph
    all_stabs = [this_op.op for this_op in q.from_generators(gstate.stab_gens)]
    all_stabs.remove('I' * len(all_stabs[0]))
    print(all_stabs)

    ### filter stabilizers to get only those for indirect measurement
    # filtered_stabs_ind_meas = filter_stabs_input_op_only(all_stabs, ind_meas_op, in_qubit)
    filtered_stabs_ind_meas = filter_stabs_input_op_compatible(
        all_stabs, ind_meas_op, in_qubit)
    print(filtered_stabs_ind_meas)

    ### identify all possible indirect measurement families
    meas_families = find_ind_meas_EC_families(filtered_stabs_ind_meas,
                                              ind_meas_op, in_qubit)
    print(meas_families)

    ## select best family
コード例 #7
0
    def get_teleportation_strats(self):
        ### gets all stabs for a graph
        all_stabs = [
            this_op.op for this_op in q.from_generators(self.gstate.stab_gens)
        ]
        all_stabs.remove('I' * self.n_qbts)

        all_meas = {}
        for stab_ix1 in range((2**self.n_qbts) - 1):
            for stab_ix2 in range(stab_ix1 + 1, (2**self.n_qbts) - 1):
                stab1 = all_stabs[stab_ix1]
                stab2 = all_stabs[stab_ix2]
                ## checks which qubits have anticommuting Paulis
                anticomm_qbts = [
                    qbt for qbt in range(self.n_qbts)
                    if single_qubit_commute(stab1, stab2, qbt)
                ]
                # print()
                # print(stab_ix1, stab1, stab_ix2, stab2, anticomm_qbts)
                # checks that there are exactly two qubits with anticommuting Paulis: the input and an output
                if len(anticomm_qbts) == 2 and self.in_qubit in anticomm_qbts:
                    out_qubit = [
                        x for x in anticomm_qbts if x != self.in_qubit
                    ][0]
                    compatible_stabs = filter_stabs_given_qubits_ops(
                        all_stabs, {
                            anticomm_qbts[0]: 'I',
                            anticomm_qbts[1]: 'I'
                        })
                    non_inout_qubits = [
                        ix for ix in range(self.n_qbts)
                        if ix not in anticomm_qbts
                    ]
                    non_inout_paulis = [
                        stab1[ix] if stab1[ix] != 'I' else stab2[ix]
                        for ix in non_inout_qubits
                    ]
                    # non_inout_measlist = dict((x, non_inout_paulis[ix]) for x, ix in non_inout_qubits)
                    compatible_stabs = filter_stabs_compatible_qubits_ops(
                        compatible_stabs,
                        dict(zip(non_inout_qubits, non_inout_paulis)))
                    # print('good inout, compatible_stabs:', compatible_stabs)

                    poss_ops_list = [['I'] if (ix in anticomm_qbts) else []
                                     for ix in range(self.n_qbts)]
                    free_qubits = []
                    for ix in range(self.n_qbts):
                        if ix not in anticomm_qbts:
                            if (stab1[ix] != 'I' or stab2[ix] != 'I'):
                                poss_ops_list[ix] = [
                                    stab1[ix]
                                    if stab1[ix] != 'I' else stab2[ix]
                                ]
                            else:
                                poss_ops_list[ix] = ['I']
                                free_qubits.append(ix)
                    # print('free_qubits', free_qubits)

                    for this_stab in compatible_stabs:
                        for ix, this_op in enumerate(this_stab):
                            if ix in free_qubits:
                                if this_op not in poss_ops_list[ix]:
                                    poss_ops_list[ix].append(this_op)
                    # print('poss_ops_list', poss_ops_list)
                    this_strat_all_meas = (''.join(ops)
                                           for ops in product(*poss_ops_list))

                    # this_strat_all_meas = list(this_strat_all_meas)
                    # print(this_strat_all_meas)

                    for this_meas in this_strat_all_meas:
                        meas_comp_stabs = filter_stabs_measurement_compatible(
                            compatible_stabs, this_meas)
                        ## Uses these stabilizers for this measurement if this_meas is not already included

                        tele_strat_weight = self.n_qbts - this_meas.count('I')
                        tele_strat_prefpauli_weight = this_meas.count(
                            self.pref_pauli) / (tele_strat_weight + 1)
                        tele_strat_val = tele_strat_weight - tele_strat_prefpauli_weight

                        if this_meas not in all_meas:
                            all_meas[this_meas] = ((out_qubit, (stab1, stab2)),
                                                   meas_comp_stabs,
                                                   tele_strat_val)
                        else:
                            # If this_meas was already included, updated its strategy to this measurement if there are equal or
                            # more compatible stabilizers than the existing case (from EC decoders), and if the weight of the
                            # logical operator is smaller (from LT decoders).
                            if len(meas_comp_stabs) >= len(
                                    all_meas[this_meas][1]):
                                if tele_strat_val < all_meas[this_meas][2]:
                                    all_meas[this_meas] = ((out_qubit,
                                                            (stab1, stab2)),
                                                           meas_comp_stabs,
                                                           tele_strat_val)
        return all_meas
コード例 #8
0
    def get_indirect_meas_strats(self):
        if self.indmeas_pauli not in ('X', 'Y', 'Z'):
            raise ValueError(
                'The indirect measument Pauli operator needs to be one of (X, Y, Z)'
            )
        ### gets all stabs for a graph
        all_stabs = [
            this_op.op for this_op in q.from_generators(self.gstate.stab_gens)
        ]
        all_stabs.remove('I' * self.n_qbts)
        ### filter stabilizers to get those compatible with the indirect measurement
        filtered_stabs_ind_meas_comp = filter_stabs_input_op_compatible(
            all_stabs, self.indmeas_pauli, self.in_qubit)
        # print(filtered_stabs_ind_meas_comp)
        ### further filter all stabs to get only those forming possible valid logical operators
        filtered_stabs_ind_meas_only = filter_stabs_input_op_only(
            filtered_stabs_ind_meas_comp, self.indmeas_pauli, self.in_qubit)
        ### further filter all stabs get only those forming possible valid syndromes
        filtered_stabs_ind_meas_syndr = filter_stabs_input_op_only(
            filtered_stabs_ind_meas_comp, 'I', self.in_qubit)
        # print(filtered_stabs_ind_meas_only)
        # print(filtered_stabs_ind_meas_syndr)

        all_meas = {}
        for log_op_stab in filtered_stabs_ind_meas_only:
            # print('\nlog_op_stab:', log_op_stab)
            log_op_weight = self.n_qbts - log_op_stab.count('I')
            log_op_prefpauli_weight = log_op_stab.count(
                self.pref_pauli) / (log_op_weight + 1)
            log_op_val = log_op_weight - log_op_prefpauli_weight
            ### Get only the stabilizers that are also compatible with this logical operator
            compatible_syndromes = filter_stabs_indmeas_compatible(
                filtered_stabs_ind_meas_syndr, log_op_stab, self.in_qubit)
            # print('compatible_stabs', compatible_syndromes)
            poss_ops_list = [
                [self.indmeas_pauli] if ix == self.in_qubit else []
                for ix in range(self.n_qbts)
            ]
            free_qubits = []
            ### Populate the measurement bases that are fixed and given by logical operator stabilizer
            for ix in range(self.n_qbts):
                # print('qbt_ix:', ix)
                if ix != self.in_qubit:
                    if log_op_stab[ix] != 'I':
                        # print('occupied qbt')
                        poss_ops_list[ix] = [log_op_stab[ix]]
                    else:
                        # print('free qubt')
                        free_qubits.append(ix)
            ### For all free qubits, include 'I' (loss) as a possible compatible measurement
            for ix in free_qubits:
                poss_ops_list[ix].append('I')
            # print('free_qubits:', free_qubits)
            ### Find all possible measurement bases for qubits with bases not fixed by the logical operator considered
            for this_comp_stab in compatible_syndromes:
                for ix, this_op in enumerate(this_comp_stab):
                    if ix in free_qubits:
                        if this_op not in poss_ops_list[ix]:
                            poss_ops_list[ix].append(this_op)
            ### Find all possible measurements
            this_strat_all_meas = (''.join(ops)
                                   for ops in product(*poss_ops_list))

            this_strat_all_meas = list(this_strat_all_meas)
            # print('this_strat_all_meas:', this_strat_all_meas)
            ### Update the all_meas dictionary using the measurements compatible with this logical operator.
            for this_meas in this_strat_all_meas:
                meas_comp_stabs = filter_stabs_measurement_compatible(
                    compatible_syndromes, this_meas)
                ## Uses these stabilizers for this measurement if this_meas is not already included
                if this_meas not in all_meas:
                    all_meas[this_meas] = (log_op_stab, meas_comp_stabs,
                                           log_op_val)
                # If this_meas was already included, updated its strategy to this measurement if there are equal or
                # more compatible stabilizers than the existing case (from EC decoders), and if the weight of the
                # logical operator is smaller (from LT decoders).
                else:
                    if len(meas_comp_stabs) >= len(all_meas[this_meas][1]):
                        if log_op_val < all_meas[this_meas][2]:
                            all_meas[this_meas] = (log_op_stab,
                                                   meas_comp_stabs, log_op_val)
        return all_meas