Path: blob/main/chemistry-simulations/aux_files/krylov/qchem/uccsd.py
583 views
import cudaq1from cudaq import spin234def uccsd_get_excitation_list(n_electrons: int, n_qubits: int, spin_mult=0):56if n_qubits % 2 != 0:7raise ValueError(8"Total number of spin molecular orbitals (number of qubits) should be even."9)10else:11n_spatial_orbitals = n_qubits // 21213singles_alpha = []14singles_beta = []15doubles_mixed = []16doubles_alpha = []17doubles_beta = []1819if spin_mult > 0:20n_occupied_beta = (n_electrons - spin_mult) // 221n_occupied_alpha = n_electrons - n_occupied_beta22n_virtual_alpha = n_spatial_orbitals - n_occupied_alpha23n_virtual_beta = n_spatial_orbitals - n_occupied_beta2425occupied_alpha_indices = [i * 2 for i in range(n_occupied_alpha)]26virtual_alpha_indices = [27i * 2 + n_electrons + 1 for i in range(n_virtual_alpha)28]2930occupied_beta_indices = [i * 2 + 1 for i in range(n_occupied_beta)]31virtual_beta_indices = [32i * 2 + 1 + n_electrons - 1 for i in range(n_virtual_beta)33]3435elif n_electrons % 2 == 0 and spin_mult == 0:36n_occupied = n_electrons // 237n_virtual = n_spatial_orbitals - n_occupied3839occupied_alpha_indices = [i * 2 for i in range(n_occupied)]40virtual_alpha_indices = [i * 2 + n_electrons for i in range(n_virtual)]4142occupied_beta_indices = [i * 2 + 1 for i in range(n_occupied)]43virtual_beta_indices = [44i * 2 + 1 + n_electrons for i in range(n_virtual)45]4647else:48raise ValueError("spin should be zero or larger than zero.")4950#occupied orbital is alpha, virtual orbital is alpha51for p in occupied_alpha_indices:52for q in virtual_alpha_indices:53singles_alpha.append((p, q))5455# occupied orbital is beta and virtual orbital is beta56for p in occupied_beta_indices:57for q in virtual_beta_indices:58singles_beta.append((p, q))5960#Mixed spin double excitation61for p in occupied_alpha_indices:62for q in occupied_beta_indices:63for r in virtual_beta_indices:64for s in virtual_alpha_indices:65doubles_mixed.append((p, q, r, s))6667# same spin double excitation68n_occ_alpha = len(occupied_alpha_indices)69n_occ_beta = len(occupied_beta_indices)70n_virt_alpha = len(virtual_alpha_indices)71n_virt_beta = len(virtual_beta_indices)7273for p in range(n_occ_alpha - 1):74for q in range(p + 1, n_occ_alpha):75for r in range(n_virt_alpha - 1):76for s in range(r + 1, n_virt_alpha):7778# Same spin: all alpha79doubles_alpha.append((occupied_alpha_indices[p],occupied_alpha_indices[q],\80virtual_alpha_indices[r],virtual_alpha_indices[s]))8182for p in range(n_occ_beta - 1):83for q in range(p + 1, n_occ_beta):84for r in range(n_virt_beta - 1):85for s in range(r + 1, n_virt_beta):8687# Same spin: all beta88doubles_beta.append((occupied_beta_indices[p],occupied_beta_indices[q],\89virtual_beta_indices[r],virtual_beta_indices[s]))9091return singles_alpha, singles_beta, doubles_mixed, doubles_alpha, doubles_beta929394#######################################959697def uccsd_parameter_size(n_electrons: int, n_qubits: int, spin_mult=0):98# Compute the size of theta parameters for all UCCSD excitation.99100singles_alpha, singles_beta, doubles_mixed, doubles_alpha, doubles_beta = \101uccsd_get_excitation_list(n_electrons, n_qubits, spin_mult)102103length_alpha_singles = len(singles_alpha)104length_beta_singles = len(singles_beta)105length_mixed_doubles = len(doubles_mixed)106length_alpha_doubles = len(doubles_alpha)107length_beta_doubles = len(doubles_beta)108109singles = length_alpha_singles + length_beta_singles110doubles = length_mixed_doubles + length_alpha_doubles + length_beta_doubles111total = singles + doubles112113return singles, doubles, total114115116###################################################117118119def add_single_excitation(op, p_occ, q_virt):120121parity = 1.0122for i in range(p_occ + 1, q_virt):123parity *= spin.z(i)124125c = 0.5126op.append(c * spin.y(p_occ) * parity * spin.x(q_virt) -127c * spin.x(p_occ) * parity * spin.y(q_virt))128129130##################################131132133def add_double_excitation(op, p_occ, q_occ, r_virt, s_virt):134135temp = []136if (p_occ < q_occ) and (r_virt < s_virt):137i_occ, j_occ = p_occ, q_occ138a_virt, b_virt = r_virt, s_virt139140elif (p_occ > q_occ) and (r_virt > s_virt):141i_occ, j_occ = q_occ, p_occ142a_virt, b_virt = s_virt, r_virt143144elif (p_occ < q_occ) and (r_virt > s_virt):145i_occ, j_occ = p_occ, q_occ146a_virt, b_virt = s_virt, r_virt147148elif (p_occ > q_occ) and (r_virt < s_virt):149i_occ, j_occ = q_occ, p_occ150a_virt, b_virt = r_virt, s_virt151152parity_a = 1.0153parity_b = 1.0154155for i in range(i_occ + 1, j_occ):156parity_a *= spin.z(i)157158for i in range(a_virt + 1, b_virt):159parity_b *= spin.z(i)160161c = 1.0 / 8.0162temp_op = c * spin.x(i_occ) * parity_a * spin.x(j_occ) * spin.x(163a_virt) * parity_b * spin.y(b_virt)164temp_op += c * spin.x(i_occ) * parity_a * spin.x(j_occ) * spin.y(165a_virt) * parity_b * spin.x(b_virt)166temp_op += c * spin.x(i_occ) * parity_a * spin.y(j_occ) * spin.y(167a_virt) * parity_b * spin.y(b_virt)168temp_op += c * spin.y(i_occ) * parity_a * spin.x(j_occ) * spin.y(169a_virt) * parity_b * spin.y(b_virt)170temp_op -= c * spin.x(i_occ) * parity_a * spin.y(j_occ) * spin.x(171a_virt) * parity_b * spin.x(b_virt)172temp_op -= c * spin.y(i_occ) * parity_a * spin.x(j_occ) * spin.x(173a_virt) * parity_b * spin.x(b_virt)174temp_op -= c * spin.y(i_occ) * parity_a * spin.y(j_occ) * spin.x(175a_virt) * parity_b * spin.y(b_virt)176temp_op -= c * spin.y(i_occ) * parity_a * spin.y(j_occ) * spin.y(177a_virt) * parity_b * spin.x(b_virt)178179op.append(temp_op)180181182########################################183184185def get_uccsd_op(nelectrons,186n_qubits,187spin_mult=0,188only_singles=False,189only_doubles=False):190191singles_alpha, singles_beta, doubles_mixed, doubles_alpha, doubles_beta = \192uccsd_get_excitation_list(nelectrons, n_qubits, spin_mult)193194n_alpha_singles = len(singles_alpha)195n_beta_singles = len(singles_beta)196n_mixed_doubles = len(doubles_mixed)197n_alpha_doubles = len(doubles_alpha)198n_beta_doubles = len(doubles_beta)199200pool_op_single = []201pool_op_double = []202203if not only_singles and not only_doubles:204205for i in range(n_alpha_singles):206p_alpha_occ, q_alpha_virt = singles_alpha[i]207add_single_excitation(pool_op_single, p_alpha_occ, q_alpha_virt)208209for i in range(n_beta_singles):210p_beta_occ, q_beta_virt = singles_beta[i]211add_single_excitation(pool_op_single, p_beta_occ, q_beta_virt)212213for i in range(n_mixed_doubles):214p_alpha_occ, q_beta_occ, r_beta_virt, s_alpha_virt = doubles_mixed[215i]216add_double_excitation(pool_op_double, p_alpha_occ, q_beta_occ,217r_beta_virt, s_alpha_virt)218219for i in range(n_alpha_doubles):220p_alpha_occ, q_alpha_occ, r_alpha_virt, s_alpha_virt = doubles_alpha[221i]222add_double_excitation(pool_op_double, p_alpha_occ, q_alpha_occ,223r_alpha_virt, s_alpha_virt)224225for i in range(n_beta_doubles):226p_beta_occ, q_beta_occ, r_beta_virt, s_beta_virt = doubles_beta[i]227228add_double_excitation(pool_op_double, p_beta_occ, q_beta_occ,229r_beta_virt, s_beta_virt)230231elif only_singles and not only_doubles:232pool_op = []233234for i in range(n_alpha_singles):235p_alpha_occ, q_alpha_virt = singles_alpha[i]236add_single_excitation(pool_op_single, p_alpha_occ, q_alpha_virt)237238for i in range(n_beta_singles):239p_beta_occ, q_beta_virt = singles_beta[i]240add_single_excitation(pool_op_single, p_beta_occ, q_beta_virt)241242elif not only_singles and only_doubles:243pool_op = []244245for i in range(n_mixed_doubles):246p_alpha_occ, q_beta_occ, r_beta_virt, s_alpha_virt = doubles_mixed[247i]248add_double_excitation(pool_op_double, p_alpha_occ, q_beta_occ,249r_beta_virt, s_alpha_virt)250251for i in range(n_alpha_doubles):252p_alpha_occ, q_alpha_occ, r_alpha_virt, s_alpha_virt = doubles_alpha[253i]254add_double_excitation(pool_op_double, p_alpha_occ, q_alpha_occ,255r_alpha_virt, s_alpha_virt)256257for i in range(n_beta_doubles):258p_beta_occ, q_beta_occ, r_beta_virt, s_beta_virt = doubles_beta[i]259260add_double_excitation(pool_op_double, p_beta_occ, q_beta_occ,261r_beta_virt, s_beta_virt)262263# Convert the list of operators to cudaq.`pauli_word`264word_single = []265word_double = []266coef_single = []267coef_double = []268269for i in range(len(pool_op_single)):270271op_i = pool_op_single[i]272for term in op_i:273coef_single.append(term.evaluate_coefficient().real)274word_single.append(term.get_pauli_word(n_qubits))275276for i in range(len(pool_op_double)):277278op_i = pool_op_double[i]279for term in op_i:280coef_double.append(term.evaluate_coefficient().real)281word_double.append(term.get_pauli_word(n_qubits))282283# Return the list of operators284if only_singles and not only_doubles:285return word_single, coef_single286287elif not only_singles and only_doubles:288return word_double, coef_double289290elif not only_singles and not only_doubles:291return word_single, word_double, coef_single, coef_double292293294###################################################295296297@cudaq.kernel298def uccsd_circuit_single(qubits: cudaq.qview, theta: list[float],299words_single: list[cudaq.pauli_word],300coef_single: list[float]):301"""302UCCSD circuit implementation for only single excitation.303"""304305n_qubits = qubits.size()306307count = 0308for i in range(0, len(words_single), 2):309exp_pauli(coef_single[i] * theta[count], qubits, words_single[i])310exp_pauli(coef_single[i + 1] * theta[count], qubits,311words_single[i + 1])312count += 1313314315@cudaq.kernel316def uccsd_circuit_double(qubits: cudaq.qview, theta: list[float],317words_double: list[cudaq.pauli_word],318coef_double: list[float]):319"""320UCCSD circuit implementation for only double excitation.321"""322323n_qubits = qubits.size()324325count = 0326for i in range(0, len(words_double), 8):327exp_pauli(coef_double[i] * theta[count], qubits, words_double[i])328exp_pauli(coef_double[i + 1] * theta[count], qubits,329words_double[i + 1])330exp_pauli(coef_double[i + 2] * theta[count], qubits,331words_double[i + 2])332exp_pauli(coef_double[i + 3] * theta[count], qubits,333words_double[i + 3])334exp_pauli(coef_double[i + 4] * theta[count], qubits,335words_double[i + 4])336exp_pauli(coef_double[i + 5] * theta[count], qubits,337words_double[i + 5])338exp_pauli(coef_double[i + 6] * theta[count], qubits,339words_double[i + 6])340exp_pauli(coef_double[i + 7] * theta[count], qubits,341words_double[i + 7])342count += 1343344345@cudaq.kernel346def uccsd_circuit(qubits: cudaq.qview, theta: list[float],347words_single: list[cudaq.pauli_word],348coef_single: list[float],349words_double: list[cudaq.pauli_word],350coef_double: list[float]):351"""352UCCSD circuit implementation for both single and double excitation.353"""354355n_qubits = qubits.size()356357count = 0358for i in range(0, len(words_single), 2):359exp_pauli(coef_single[i] * theta[count], qubits, words_single[i])360exp_pauli(coef_single[i + 1] * theta[count], qubits,361words_single[i + 1])362count += 1363364for i in range(0, len(words_double), 8):365exp_pauli(coef_double[i] * theta[count], qubits, words_double[i])366exp_pauli(coef_double[i + 1] * theta[count], qubits,367words_double[i + 1])368exp_pauli(coef_double[i + 2] * theta[count], qubits,369words_double[i + 2])370exp_pauli(coef_double[i + 3] * theta[count], qubits,371words_double[i + 3])372exp_pauli(coef_double[i + 4] * theta[count], qubits,373words_double[i + 4])374exp_pauli(coef_double[i + 5] * theta[count], qubits,375words_double[i + 5])376exp_pauli(coef_double[i + 6] * theta[count], qubits,377words_double[i + 6])378exp_pauli(coef_double[i + 7] * theta[count], qubits,379words_double[i + 7])380count += 1381382383