Esempio n. 1
0
def pta_ad(n, t, t1):
    """
    Produces the kraus matrices for the pta channel
    :param n: number of qubit
    :param t: time step for evolution
    :param t1: relaxation time
    :return: returns a 3 dimensinal array of pta kraus matrices
    """
    gamma = 1 - np.exp(-t / t1)
    px = py = gamma / 4.0
    pz = 1.0 / 2.0 - py - np.sqrt(1 - gamma) / 2
    pi = 1 - (px + py + pz)
    A = np.zeros((pow(4, n), pow(2, n), pow(2, n)), dtype=complex)  # 3 dimensional array to store kraus matrices
    ptaOperators = {
        '0': np.sqrt(pi) * g.id(),
        '1': np.sqrt(px) * g.x(),
        '2': np.sqrt(py) * g.y(),
        '3': np.sqrt(pz) * g.z()
    }

    # get labels
    labels = op.createlabel(n, 4)

    for i in range(len(labels)):
        temp = 1
        for digit in labels[i]:
            temp = np.kron(temp, ptaOperators[digit])
        A[i] = temp
    return A
Esempio n. 2
0
def kraus_pta(n, t, t1, t2):
    """
    Produces the kraus matrices for the pta channel
    :param n: number of qubit
    :param t: time step for evolution
    :param t1: relaxation time
    :param t2: dephasing time
    :return: returns a 3 dimensinal array of pta kraus matrices
    """
    gamma = 1 - np.exp(-t / t1)
    t_phi = Decimal(1 / t2) - Decimal(1 / (2 * t1))
    # lambda1 = np.exp(-t/t1)*(1-np.exp(-2*(t/t_phi)))
    px = py = gamma / 4.0
    pz = 1.0 / 2.0 - py - np.exp(-t / (2 * t1)) * np.exp(-(t / t_phi)) / 2
    pi = 1 - (px + py + pz)
    print('px: ', py, 'pz: ', pz, 'pi: ', pi)
    A = np.zeros((pow(4, n), pow(2, n), pow(2, n)), dtype=complex)  # 3 dimensional array to store kraus matrices
    ptaOperators = {
        '0': np.sqrt(pi) * g.id(),
        '1': np.sqrt(px) * g.x(),
        '2': np.sqrt(py) * g.y(),
        '3': np.sqrt(pz) * g.z()
    }

    # get labels
    labels = op.createlabel(n, 4)

    for i in range(len(labels)):
        temp = 1
        for digit in labels[i]:
            temp = np.kron(temp, ptaOperators[digit])
        A[i] = temp
    return A
Esempio n. 3
0
    def __init__(self, string, n, no_measurment_qubits=1, left_justified=False):
        """
        :param string: This should be a string of 1's and 0's where 1 is the |1> and
        0 is |0>
        :param n: The number of qubits in the system
        :param no_measurment_qubits:  The number of qubits that will be measured
        :return: Returns the

        Description of class variables
        state: This is the density matrix of the system
        classical_states: This is a dictionary of computational basis states that should have
        has its keys labels of computational basis states and values the corresponding
        probabilities
        no_measurement_qubits: The number of qubits you intend to measure
        classical_states_history: Has a key values all possible measurement syndromes and keeps a record of their
        probabilities
        single_kraus: These are the kraus operators used for a single qubit. They are used to create kraus operators
        for the n qubit system
        partial_bath: This is aa boolean variable. If true some qubits the last m qubits on the left will not decohere
        no_non_ideal_qubits: These are the number of qubits, k that will decohere.  m+k must equal to n the number of
        qubits in the system
        hamiltonian: The hamiltonian of the system
        T: The total evolution time of the system
        state: The state of the quantum system for n qubits
        """
        self.oper_dict = {'0': g.b1(), '1': g.b4(), '2': g.id()}

        self.state = op.superkron(self.oper_dict, val=1, string=string)
        self.n = n
        self.no_measurement_qubits = no_measurment_qubits
        self.measurement_string = op.createlabel(self.no_measurement_qubits, 2)
        for i in range(len(self.measurement_string)):
            if left_justified:
                self.measurement_string[i] = self.measurement_string[i].ljust(self.n, '2')
            else:
                self.measurement_string[i] = self.measurement_string[i].rjust(self.n, '2')
        # self.projectors = {i.replace('2', ''): op.superkron(self.oper_dict, val=1, string=i) for i in
        #                    self.measurement_string}
        self.classical_states = {i.replace('2', ''): 0 for i in self.measurement_string}
        self.classical_states_history = {i.replace('2', ''): [] for i in self.measurement_string}
        self.hamiltonian = None
        self.dt = None
        self.U = None
        self.xlabel = ''
        self.ylabel = ''
        self.T = None
        self.kraus_operators = []
        self.expect_values = {}
        self.yield_kraus = None
        self.single_kraus = None
        self.partial_bath= False
        self.no_non_ideal_qubits = 0
Esempio n. 4
0
def kraus_generator(n, non_ideal_qubits=0, classical_error=False, partialbath=False, opers=[]):
    """
    :param n:
    :param classical_error:
    :param opers:
    :param prob_error:
    :return:
    """
    num_operators = len(opers)
    kraus_operators = {str(i): opers[i] for i in range(len(opers))}
    if classical_error is False and partialbath is False:
        labels = op.createlabel(n, num_operators)
        for i in range(len(labels)):
            kraus = 1
            for digit in labels[i]:
                kraus = np.kron(kraus, kraus_operators[digit])
            yield kraus
    elif classical_error is False and partialbath:
        labels = op.createlabel(non_ideal_qubits, num_operators)
        for i in range(len(labels)):
            kraus = 1
            for digit in labels[i]:
                kraus = np.kron(kraus, kraus_operators[digit])
            yield kraus
Esempio n. 5
0
def generic_kraus(n, classical_error=False, opers=[], prob_error=[], generator=False):
    """
    This functions takes as an input generic operators and outputs a corresponding list of kraus operators for those
    n qubits. It also can do a classical simulation of noise by throwing down errors classically
    :param n:  The number of qubits experiencing the noise
    :param classical_error: If True the user must supply list of probabilities for list in oper
    :param opers: The list of kraus operators that appear in the sum
    :param prob_error: The list of probabilities for each operator in oper. Entries must add to 1. First operator is
    returned with probability in first position of prob_error.
    :param generator: Function becomes a generator in order to save memeory when a large number of qubits is being used
    :return:
    """

    num_operators = len(opers)

    if classical_error is False:
        A = np.zeros((pow(num_operators, n), pow(2, n), pow(2, n)),
                     dtype=complex) # 3 dimensional array to store kraus matrices
        kraus_operators = {str(i): opers[i] for i in range(len(opers))}
        labels = op.createlabel(n, num_operators)

        for i in range(len(labels)):
            temp=1
            for digit in labels[i]:
                temp = np.kron(temp, kraus_operators[digit])
            A[i] = temp
        return A

    if classical_error:
        # Returns a 3 dimensional array which stores only one kraus matrix
        A = np.zeros((pow(num_operators, 0), pow(2, n), pow(2, n)),
                     dtype=complex)  # 3 dimensional array to store kraus matrices
        if len(prob_error) != 0 or len(prob_error) != len(opers):
            if math.isclose(sum(prob_error), 1, rel_tol=1e-4):
                operators = {i: prob_error[i]*100 for i in range(len(prob_error))}
                lea_object = pmf(operators)
                picked_operator = lea_object.random()
                A[0] = opers[picked_operator]
                return A
            else:
                raise Exception('Probabilities must add to 1')
        else:
            raise Exception('prob_error list is empty or does not equal oper list')
Esempio n. 6
0
def kraus_exact(n, t, t1, t2, markovian=False, alpha=None):
    """
    Produces the kraus matrices for the exact evolution of amplitude damping with dephasing channel
        :param n: number of qubit
        :param t: time step for evolution
        :param t1: relaxation time
        :param t2: dephasing time must be smaller than t1
        :param markovian: If true the kraus matrices are for non markovian evolution and
        t2 takes the role of  t_phi
        :param alpha: The power of 1/f^{alpha} flux noise
        :return:  a 3 dimensinal array of kraus matrices with amplitude damping and dephasing

    """
    A = np.zeros((pow(3, n), pow(2, n), pow(2, n)), dtype=complex)  # 3 dimensional array to store kraus matrices
    gamma = 1 - np.exp(-t / t1)
    if markovian:
        t_phi = 1 / t2 - 1 / (2 * t1)
        lambda1 = np.exp(-t / t1) * (1 - np.exp(-2 * (t / t_phi)))
        print('We are markovian')
    else:
        print('We are non markovian')
        t_phi = t2
        lambda1 = np.exp(-t / t1) * (1 - np.exp(-2 * (t / t_phi) ** (1 + alpha)))

    krausOperators = {
        "0": np.array([[1, 0], [0, np.sqrt(1 - gamma - lambda1)]]),
        "1": np.array([[0, np.sqrt(gamma)], [0, 0]]),
        "2": np.array([[0, 0], [0, np.sqrt(lambda1)]]),
    }

    labels = op.createlabel(n, 3)

    for i in range(len(labels)):
        temp = 1
        for digit in labels[i]:
            temp = np.kron(temp, krausOperators[digit])
        A[i] = temp

    return A
Esempio n. 7
0
def kraus_ad(n, t, t1):
    """
      Produces the kraus matrices for the amplitude damping channel
        :param n: number of qubit
        :param t: time step for evolution
        :param t1: relaxation time
        :return: returns a 3 dimensinal array of amplitude damping kraus matrices
      """

    A = np.zeros((pow(2, n), pow(2, n), pow(2, n)), dtype=complex)  # 3 dimensional array to store kraus matrices
    gamma = 1 - np.exp(-t / t1)
    adOperators = {
        "0": np.array([[1, 0], [0, np.sqrt(1 - gamma)]]),
        "1": np.array([[0, np.sqrt(gamma)], [0, 0]])
    }

    labels = op.createlabel(n, 2)

    for i in range(len(labels)):
        temp = 1
        for digit in labels[i]:
            temp = np.kron(temp, adOperators[digit])
        A[i] = temp
    return A