def pauli_measurement_on_stab_list(pauli_measurement, stab_list, outcome=0):
    """
    Updates a list of stabilizers after a measurement is performed
    """
    if not (outcome == 0 or outcome == 1):
        raise ValueError("Measurement outcome value can be only 0 or 1.")

    if not isinstance(pauli_measurement, q.Pauli):
        pauli_meas = q.Pauli(pauli_measurement)
    else:
        pauli_meas = pauli_measurement

    for check_stab in stab_list:
        if not isinstance(check_stab, q.Pauli):
            raise ValueError(
                "All input stabilizers need to be qecc.Pauli objects.")

    new_pauli_list = copy(stab_list)
    for stab_ix, this_stab in enumerate(stab_list):
        if q.com(pauli_meas, this_stab) == 1:
            anticomm_pauli = this_stab
            anticomm_pauli.ph = (anticomm_pauli.ph + 2 * outcome) % 4
            new_pauli_list[stab_ix].op = pauli_meas.op
            new_pauli_list[stab_ix].ph = (pauli_meas.ph + 2 * outcome) % 4
            break

    for other_stabs_ix in range(stab_ix, len(stab_list)):
        this_stab = stab_list[other_stabs_ix]
        if q.com(pauli_meas, this_stab) == 1:
            new_pauli_list[other_stabs_ix] = anticomm_pauli * this_stab

    return new_pauli_list
def single_local_clifford(cgate, pauli, qb_idx):
    """
    Rules for operating an individual Clifford gate on a single Pauli matrix
    """
    if cgate not in CliffordGateList:
        raise ValueError("Clifford gate needs to be in:", CliffordGateList)
    if not isinstance(pauli, q.Pauli):
        raise ValueError("Pauli operator needs to be a qecc.Pauli object.")

    pauli_op = pauli.op[qb_idx]
    new_op = list(pauli.op)
    new_phase = pauli.ph

    if cgate == 'H':
        if pauli_op == 'X':
            new_op[qb_idx] = 'Z'
        if pauli_op == 'Z':
            new_op[qb_idx] = 'X'
        if pauli_op == 'Y':
            new_phase = (new_phase + 2) % 4

    if cgate == "S":
        if pauli_op == 'X':
            new_op[qb_idx] = 'Y'
        if pauli_op == 'Y':
            new_op[qb_idx] = 'X'
            new_phase = (new_phase + 2) % 4
    new_pauli = q.Pauli("".join(new_op), phase=new_phase)
    return new_pauli
Ejemplo n.º 3
0
def one_shot():
    """
        For the initial part of the in-class demo. Takes a single Pauli and computes
        one random circuit from the eps-approximate 2-design and applies it to the Pauli.
    """

    print "\n====================================================================="
    print "Choosing a single random circuit from an epsilon-approximate 2-design"
    print "=====================================================================\n"

    pauli_string = raw_input("Please enter an initial Pauli (e.g. XXYZ): ")
    epsilon = float(raw_input("Enter a value for epsilon: "))

    pauli = q.Pauli(pauli_string)
    new_pauli = pauli
    new_circuit = []
    
    for i in range(0, int(log(1/epsilon)) + 1): 
        new_pauli, circuit = uniformization(new_pauli)
        new_circuit.extend(circuit)

    print "\nResultant pauli is " 
    print new_pauli
    print "\nApplied circuit was "
    print_circuit(new_circuit, pauli.nq)

    print "\n\n\n"
Ejemplo n.º 4
0
def distribution():
    print "\n====================================================================="
    print "Generate statistics for the distribution of Paulis after successive "
    print "application of circuits chosen randomly from the 2-design"
    print "=====================================================================\n"

    pauli_string = raw_input("Please enter an initial Pauli (e.g. XXYZ): ")
    trials = raw_input("Please enter the number of circuits to generate: ")
    epsilon = float(raw_input("Enter a value for epsilon: "))
    pauli = q.Pauli(pauli_string)
    
    circuit_file = open("circuit_file" + "_" + pauli.op + "_" + trials + "_" + str(epsilon) + ".out", 'w')
    pauli_file = open("pauli_file" + "_" + pauli.op + "_" + trials + "_" + str(epsilon) + ".out", 'w')
     
    paulis = []
    pauli_counts = []
    circuits = []
    circuit_counts = []

    for i in range(0, int(trials)):
        next_circuit = []
        new_pauli = pauli

        for j in range(0, int(log(1/epsilon)) + 1):
            new_pauli, circuit = uniformization(new_pauli)
            next_circuit.extend(circuit)

        if next_circuit not in circuits:
            circuits.append(next_circuit)
            circuit_counts.append(1)
        else:
            circuit_counts[circuits.index(next_circuit)] += 1

        if new_pauli.op not in paulis:
            paulis.append(new_pauli.op)
            pauli_counts.append(1)
        else:
    	    pauli_counts[paulis.index(new_pauli.op)] += 1

    for i in range(0, len(circuits)):
        print_circuit_to_file(circuits[i], pauli.nq, circuit_file)
        circuit_file.write('Count: ' + str(circuit_counts[i]) + '\n\n')
                                 
    circuit_file.write("Total number of different circuits: " + str(len(circuits)) + '\n')

    pauli_probs = [pauli_counts[i]*1.0 / sum(pauli_counts) for i in range(0, len(paulis))]

    for i in range(0, len(paulis)):
        pauli_file.write(paulis[i] + "\t" + str(pauli_probs[i]))
        pauli_file.write('\n')

    pauli_file.write('\n'+"KL divergence is " + str( entropy(pauli_probs, [1.0/len(paulis)]*len(paulis)) ) )
Ejemplo n.º 5
0
    def __init__(self, stab_generators):
        # stab_gens represent the n stabilizer generators defining the n-qubit stabilizer state

        # TODO: various checks, including that if the set in stab_gens are stabilizer but not necessarily
        #  the set of minimal stabilizer generators, it extracts the generators (QECC has such function).

        # Check that stab_gens is the correct object, and ceonvert it to qecc.Pauli otherwise
        self.stab_gens = []
        for check_stab in stab_generators:
            if not isinstance(check_stab, q.Pauli):
                self.stab_gens.append(q.Pauli(check_stab))
            else:
                self.stab_gens.append(check_stab)

        self.nqbits = len(stab_generators[0])
def appl_pauli(nq, qn, g, stab):
    pau = ['I'] * nq
    pau[qn] = g
    return stab * qe.Pauli(''.join(pau))
def pauli_measurement_on_code(pauli_measurement,
                              stab_gens_list,
                              logical_ops_list,
                              outcome=0):
    """
    Updates stabilizers and logical operators after a measurement is performed
    """
    if not (outcome == 0 or outcome == 1):
        print(outcome)
        raise ValueError("Measurement outcome value can be only 0 or 1.")

    if not isinstance(pauli_measurement, q.Pauli):
        pauli_meas = q.Pauli(pauli_measurement)
    else:
        pauli_meas = pauli_measurement

    for check_stab in stab_gens_list:
        if not isinstance(check_stab, q.Pauli):
            raise ValueError(
                "All input stabilizers need to be qecc.Pauli objects.")

    for log_op_zs in logical_ops_list[0]:
        if not isinstance(log_op_zs, q.Pauli):
            raise ValueError(
                "All logical Z operators need to be qecc.Pauli objects.")

    for log_op_xs in logical_ops_list[1]:
        if not isinstance(log_op_xs, q.Pauli):
            raise ValueError(
                "All logical X operators need to be qecc.Pauli objects.")

    check_all_comm = True
    new_stab_gens_list = copy(stab_gens_list)
    for stab_ix, this_stab in enumerate(stab_gens_list):
        if q.com(pauli_meas, this_stab) == 1:
            check_all_comm = False
            anticomm_pauli = this_stab
            anticomm_pauli.ph = (anticomm_pauli.ph + 2 * outcome) % 4
            new_stab_gens_list[stab_ix].op = pauli_meas.op
            new_stab_gens_list[stab_ix].ph = (pauli_meas.ph + 2 * outcome) % 4
            break

    for other_stabs_ix in range(stab_ix, len(stab_gens_list)):
        this_stab = stab_gens_list[other_stabs_ix]
        if q.com(pauli_meas, this_stab) == 1:
            new_stab_gens_list[other_stabs_ix] = anticomm_pauli * this_stab

    new_Z_log_ops_list = copy(logical_ops_list[0])
    new_X_log_ops_list = copy(logical_ops_list[1])
    # if measurement anticommutes with some stabilizer generator, update logical operators
    if not check_all_comm:
        for logop_ix, this_logop in enumerate(logical_ops_list[0]):
            if q.com(pauli_meas, this_logop) == 1:
                new_Z_log_ops_list[logop_ix] = anticomm_pauli * this_logop
        for logop_ix, this_logop in enumerate(logical_ops_list[1]):
            if q.com(pauli_meas, this_logop) == 1:
                new_X_log_ops_list[logop_ix] = anticomm_pauli * this_logop

        return new_stab_gens_list, [new_Z_log_ops_list, new_X_log_ops_list]

    # if measurement commutes with all stabilizer generators, check that it commutes with all logical operators (i.e.
    # the measurement is a stabilizer), and if so return the same logical operators. If instead it anticommutes with
    # some logical operator, it means we measured a logical operator, and thus we collapsed the whole logical state to
    # an eigenstate of a logical operator. In this case both te stabilizer generators and logical operators would remain
    # untouched, but here we also raise an error because teleportation can no longer be performed.
    else:
        for logop_ix, this_logop in enumerate(logical_ops_list[0]):
            if (q.com(pauli_meas, logical_ops_list[0][logop_ix]) == 1) or \
                    (q.com(pauli_meas, logical_ops_list[1][logop_ix]) == 1):
                raise ValueError(
                    "Performed measurement in a logical operator: logical state is collapsed and "
                    "teleportation can no longer be performed.")
        return new_stab_gens_list, [new_Z_log_ops_list, new_X_log_ops_list]