def transverse_ising_model_1d(N, J=1, g=1): #Sum -JZ_iZ_i+1 + Sum gX_i """ kh: what if N = 1? """ paulistrings = [] for i in range(N - 1): st = [0] * N st[i] = 3 st[i + 1] = 3 paulistrings.append(pcp.paulistring(N, st, -J)) for i in range(N): st = [0] * N st[i] = 1 paulistrings.append(pcp.paulistring(N, st, g)) return Hamiltonian(N, paulistrings)
def generate_package_of_random_hamiltonians( N, howmanyrandomhamiltonians, uptohowmanyterms, numpyseed, maximumbeta): #Returns a list of randomly generated hamiltonians random_generator = np.random.default_rng(numpyseed) ham_list = [] for i in range(howmanyrandomhamiltonians): pauliterms = [] while len(pauliterms) < uptohowmanyterms: rint = random_generator.integers(low=0, high=4, size=N) rstring = '' for j in rint: rstring = rstring + str(j) if rstring not in pauliterms: pauliterms.append(rstring) #print(pauliterms) paulistringobjects = [] for term in pauliterms: paulistringobjects.append( pcp.paulistring( N, term, list( random_generator.random(uptohowmanyterms) * maximumbeta))) ham_list.append(Hamiltonian(N, paulistringobjects)) return ham_list
def dagger_hamiltonian(ham1): #Returns the dagger of the hamiltonian newpauliclassobjs = [] N = ham1.return_N() for pold in ham1.return_paulistrings(): newpauliclassobjs.append( pcp.paulistring(N, pold.return_string(), np.conj(pold.return_coefficient()))) return Hamiltonian(N, newpauliclassobjs)
def heisenberg_xyz_model(N, jx=1, jy=2, jz=3): #Sum jx X_i X_{i+1} + ... j_couplings = [jx, jy, jz] base_string = [0] * N paulistrings = [] if N == 1: for j in range(len(j_couplings)): if j_couplings[j] == 0: continue term = [j + 1] term = pcp.paulistring(N, term, j_couplings[j]) paulistrings.append(term) return Hamiltonian(N, paulistrings) for i in range(N - 1): for j in range(len(j_couplings)): if j_couplings[j] == 0: continue term = base_string.copy() term[i] = j + 1 term[i + 1] = j + 1 term = pcp.paulistring(N, term, j_couplings[j]) paulistrings.append(term) return Hamiltonian(N, paulistrings)
def get_fidelity_results(num_qubits, ansatzlist, times, whatKs, hamiltonian, initial_state): """ Returns a dictionary of dictionaries. The keys are the values of K that we are considering, the values are the dictionaries for that K value. For a particular K value, the corresponding dictionary is such that the keys are the time values, and the values are the fidelities at that particular time """ initial_statevector = initial_state.get_statevector() # if qstype == 'TTQS': # name = 'TTQS' # if qstype == 'QAS': # name = 'QAS' # if qstype == 'CQFF': # name = 'CQFF' collated_fidelity_vals = dict() for i in range(len(ansatzlist)): if i in whatKs: print('Calculating and saving fidelity for K = ' + str(i)) ansatz = ansatzlist[i] result_pauli_string, result_alphas = ansatz.get_alphas() result_alphas = list(zip(*result_alphas)) #transpose it so that each entry is a time value fidelity_vals = dict() for time_idx in range(len(times)): time = times[time_idx] alpha = result_alphas[time_idx] alpha = np.array(alpha) state = np.zeros(2**num_qubits) + 1j*np.zeros(2**num_qubits) for j in range(len(alpha)): # print("I'm here", result_pauli_string[j]) result_pauli_string_obj = pcp.paulistring(num_qubits, result_pauli_string[j], 1) # print(result_pauli_string_obj) result_pauli_string_matrix = result_pauli_string_obj.get_matrixform() # print("i am here", len(initial_statevector)) # print("i am here two", len(result_pauli_string_matrix)) # print("i am here three", alpha[j]) state += alpha[j] * result_pauli_string_matrix @initial_statevector hamiltonian_matrix = hamiltonian.to_matrixform() theoretical_state = expm(-1j * hamiltonian_matrix * time) @ initial_statevector # theoretical_state = final_results_from_classical_simulator[time_idx] fidelity = np.abs(np.vdot(theoretical_state, state)) # if time == 60: # print("actual_state_is", state) # print("theoretical_state_is", theoretical_state) # fidelity_vals.append(fidelity) fidelity_vals[time] = fidelity collated_fidelity_vals[i] = fidelity_vals return collated_fidelity_vals
def generate_parity_operator_matform(num_qubits): dim = 2**num_qubits P_mat = np.zeros((dim, dim)) # test_mat = np.zeros(dim) for i in range(dim): ket_bitstring = np.binary_repr(i) ket_bitstring = (num_qubits - len(ket_bitstring)) * "0" + ket_bitstring ket = np.zeros(dim) ket[i] = 1 bra_bitstring = ket_bitstring[::-1] bra_index = int(bra_bitstring, 2) # print(ket_bitstring, bra_bitstring) bra = np.zeros(dim) bra[bra_index] = 1 P_mat += np.outer(ket, bra) spinflips = pcp.paulistring(num_qubits, [1] * num_qubits, 1).get_matrixform() return P_mat @ spinflips
def get_data_for_fidelity(num_qubits, ansatzlist, times,whatKs, qstype, hamiltonian, initial_state): finaldict = {} finaldict['times'] = list(times.real) initial_statevector = initial_state.get_statevector() if qstype == 'TQS': name = 'TQS' if qstype == 'QAS': name = 'QAS' if qstype == 'CQFF': name = 'CQFF' for i in range(len(ansatzlist)): if i in whatKs: #print('Plotting fidelity for K = ' + str(i)) ansatz = ansatzlist[i] result_pauli_string, result_alphas = ansatz.get_alphas() result_alphas = list(zip(*result_alphas)) #transpose it so that each entry is a time value fidelity_vals = [] for time_idx in range(len(times)): time = times[time_idx] alpha = result_alphas[time_idx] alpha = np.array(alpha) state = np.zeros(2**num_qubits) + 1j*np.zeros(2**num_qubits) for j in range(len(alpha)): # print("I'm here", result_pauli_string[j]) result_pauli_string_obj = pcp.paulistring(num_qubits, result_pauli_string[j], 1) # print(result_pauli_string_obj) result_pauli_string_matrix = result_pauli_string_obj.get_matrixform() # print("i am here", len(initial_statevector)) # print("i am here two", len(result_pauli_string_matrix)) # print("i am here three", alpha[j]) state += alpha[j] * result_pauli_string_matrix @initial_statevector hamiltonian_matrix = hamiltonian.to_matrixform() theoretical_state = expm(-1j * hamiltonian_matrix * time) @ initial_statevector # theoretical_state = final_results_from_classical_simulator[time_idx] fidelity = np.abs(np.vdot(theoretical_state, state)) # if time == 60: # print("actual_state_is", state) # print("theoretical_state_is", theoretical_state) fidelity_vals.append(fidelity) lab = name + " K=" + str(i) #plt.plot(times, fidelity_vals, label = lab) finaldict[str(i)] = list(fidelity_vals) return finaldict
def generate_arbitary_observable(N, couplings, pauli_strings): """ Here, N is the number of qubits Let the observable be sum_{i=1}^r beta_i P_i Then, couplings = [beta_1, beta_2, ..., beta_L] pauli_strings = [P_1, P_2,..,P_L] Here, P_i is any iterable, e.g a string "123", or a list [1,2,3]. Both these iterables represent the operator X_1 Y_2 Z_3 """ if len(couplings) != len(pauli_strings): raise (RuntimeError( "Length of couplings must match length of pauli_strings")) paulistring_objects = [] for j in range(len(pauli_strings)): beta_j = couplings[j] P_j = pauli_strings[j] P_j_formatted = [int(i) for i in P_j] pauliobject = pcp.paulistring(N, P_j_formatted, beta_j) paulistring_objects.append(pauliobject) return Observable(N, paulistring_objects)
def generate_arbitary_hamiltonian(N, couplings, pauli_strings): """ Here, N is the number of qubits Let the Hamiltonian be sum_{i=1}^r beta_i P_i Then, couplings = [beta_1, beta_2, ..., beta_L] pauli_strings = [P_1, P_2,..,P_L] Here, P_i is any iterable, e.g a string "123", or a list [1,2,3]. Both these iterables represent the operator X_1 Y_2 Z_3 EXAMPLE: If we have a 4 qubit system and I want to implement the hamiltonian H = 0.6*(XXII) + 0.4*(XZIY), the hamiltonian will be generated with this: generate_arbitrary_hamiltonian(4,[0.6,0.4],["1100","1302"]) """ if len(couplings) != len(pauli_strings): raise (RuntimeError( "Length of couplings must match length of pauli_strings")) paulistring_objects = [] for j in range(len(pauli_strings)): beta_j = couplings[j] P_j = pauli_strings[j] P_j_formatted = [int(i) for i in P_j] pauliobject = pcp.paulistring(N, P_j_formatted, beta_j) paulistring_objects.append(pauliobject) return Hamiltonian(N, paulistring_objects)
def gen_next_ansatz(anz, H, N, method="no_processing", pruning_condition=0.1, num_new_to_add=5): if method == 'no_processing': newmomentstrings = [] for mom in anz.moments: newmomentstrings.append(mom.paulistring.return_string()) for mom in anz.moments: for ham in H.return_paulistrings(): newpauli = pcp.pauli_combine(mom.paulistring, ham) if newpauli.return_string() not in newmomentstrings: newmomentstrings.append( newpauli.return_string() ) #This is the string that is [0,1,2,1,1,2,...] ect, NOT the paulistring class #print for debugging purposes print("there are " + str(len(newmomentstrings)) + " states in CSk") newmoment = [] for i in newmomentstrings: newmoment.append(moment(N, paulistring( N, i, 1))) #Appending the paulistring class objects if method == 'random_selection_new': oldmomentstrings = [] for mom in anz.moments: oldmomentstrings.append(mom.paulistring.return_string()) newmomentstrings = [] for mom in anz.moments: for ham in H.return_paulistrings(): newpauli = pcp.pauli_combine(mom.paulistring, ham) if newpauli.return_string( ) not in oldmomentstrings and newpauli.return_string( ) not in newmomentstrings: newmomentstrings.append( newpauli.return_string() ) #This is the string that is [0,1,2,1,1,2,...] ect, NOT the paulistring class newmoment = [] for i in oldmomentstrings: newmoment.append(moment(N, paulistring( N, i, 1))) #Appending the paulistring class objects if len(newmomentstrings) <= num_new_to_add: for i in newmomentstrings: newmoment.append(moment(N, paulistring( N, i, 1))) #Appending the paulistring class objects else: indicestoadd = np.random.choice(len(newmomentstrings), num_new_to_add, replace=False) for i in indicestoadd: newmoment.append( moment(N, paulistring( N, newmomentstrings[i], 1))) #Appending the paulistring class objects print("there are " + str(len(newmoment)) + " states in CSk") if method == 'pruning': newmomentstrings = [] for mom in anz.moments: maximum = max(mom.alphas) if maximum > pruning_condition: newmomentstrings.append(mom.paulistring.return_string()) for mom in anz.moments: maximum = max(mom.alphas) if maximum > pruning_condition: for ham in H.return_paulistrings(): newpauli = pcp.pauli_combine(mom.paulistring, ham) if newpauli.return_string() not in newmomentstrings: newmomentstrings.append( newpauli.return_string() ) #This is the string that is [0,1,2,1,1,2,...] ect, NOT the paulistring class #print for debugging purposes print("there are " + str(len(newmomentstrings)) + " states in CSk") newmoment = [] for i in newmomentstrings: newmoment.append(moment(N, paulistring( N, i, 1))) #Appending the paulistring class objects return Ansatz(N, anz.K + 1, newmoment)
def initial_ansatz(N): initialmoment = moment(N, paulistring(N, [0] * N, 1)) return Ansatz(N, 0, [initialmoment])