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
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
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
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
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')
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
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