def expectation_one_body_db_operator_computational_basis_state( dual_basis_action, plane_wave_occ_orbitals, grid, spinless): """Compute expectation value of a 1-body dual-basis operator with a plane wave computational basis state. Args: dual_basis_action: Dual-basis action of FermionOperator to evaluate expectation value of. plane_wave_occ_orbitals (list): list of occupied plane-wave orbitals. grid (openfermion.utils.Grid): The grid used for discretization. spinless (bool): Whether the system is spinless. Returns: A real float giving the expectation value. """ expectation_value = 0.0 r_p = position_vector( grid_indices(dual_basis_action[0][0], grid, spinless), grid) r_q = position_vector( grid_indices(dual_basis_action[1][0], grid, spinless), grid) for orbital in plane_wave_occ_orbitals: # If there's spin, p and q have to have the same parity (spin), # and the new orbital has to have the same spin as these. k_orbital = momentum_vector(grid_indices(orbital, grid, spinless), grid) # The Fourier transform is spin-conserving. This means that p, q, # and the new orbital all have to have the same spin (parity). if spinless or (dual_basis_action[0][0] % 2 == dual_basis_action[1][0] % 2 == orbital % 2): expectation_value += numpy.exp(-1j * k_orbital.dot(r_p - r_q)) return expectation_value
def expectation_two_body_db_operator_computational_basis_state( dual_basis_action, plane_wave_occ_orbitals, grid, spinless): """Compute expectation value of a 2-body dual-basis operator with a plane wave computational basis state. Args: dual_basis_action: Dual-basis action of FermionOperator to evaluate expectation value of. plane_wave_occ_orbitals (list): list of occupied plane-wave orbitals. grid (openfermion.utils.Grid): The grid used for discretization. spinless (bool): Whether the system is spinless. Returns: A float giving the expectation value. """ expectation_value = 0.0 r = {} for i in range(4): r[i] = position_vector( grid_indices(dual_basis_action[i][0], grid, spinless), grid) rr = {} k_map = {} for i in range(2): rr[i] = {} k_map[i] = {} for j in range(2, 4): rr[i][j] = r[i] - r[j] k_map[i][j] = {} # Pre-computations. for o in plane_wave_occ_orbitals: k = momentum_vector(grid_indices(o, grid, spinless), grid) for i in range(2): for j in range(2, 4): k_map[i][j][o] = k.dot(rr[i][j]) for orbital1 in plane_wave_occ_orbitals: k1ac = k_map[0][2][orbital1] k1ad = k_map[0][3][orbital1] for orbital2 in plane_wave_occ_orbitals: if orbital1 != orbital2: k2bc = k_map[1][2][orbital2] k2bd = k_map[1][3][orbital2] # The Fourier transform is spin-conserving. This means that # the parity of the orbitals involved in the transition must # be the same. if spinless or ((dual_basis_action[0][0] % 2 == dual_basis_action[3][0] % 2 == orbital1 % 2) and (dual_basis_action[1][0] % 2 == dual_basis_action[2][0] % 2 == orbital2 % 2)): value = numpy.exp(-1j * (k1ad + k2bc)) # Add because it came from two anti-commutations. expectation_value += value # The Fourier transform is spin-conserving. This means that # the parity of the orbitals involved in the transition must # be the same. if spinless or ((dual_basis_action[0][0] % 2 == dual_basis_action[2][0] % 2 == orbital1 % 2) and (dual_basis_action[1][0] % 2 == dual_basis_action[3][0] % 2 == orbital2 % 2)): value = numpy.exp(-1j * (k1ac + k2bd)) # Subtract because it came from a single anti-commutation. expectation_value -= value return expectation_value
def expectation_three_body_db_operator_computational_basis_state( dual_basis_action, plane_wave_occ_orbitals, grid, spinless): """Compute expectation value of a 3-body dual-basis operator with a plane wave computational basis state. Args: dual_basis_action: Dual-basis action of FermionOperator to evaluate expectation value of. plane_wave_occ_orbitals (list): list of occupied plane-wave orbitals. grid (openfermion.utils.Grid): The grid used for discretization. spinless (bool): Whether the system is spinless. Returns: A float giving the expectation value. """ expectation_value = 0.0 r = {} for i in range(6): r[i] = position_vector( grid_indices(dual_basis_action[i][0], grid, spinless), grid) rr = {} k_map = {} for i in range(3): rr[i] = {} k_map[i] = {} for j in range(3, 6): rr[i][j] = r[i] - r[j] k_map[i][j] = {} # Pre-computations. for o in plane_wave_occ_orbitals: k = momentum_vector(grid_indices(o, grid, spinless), grid) for i in range(3): for j in range(3, 6): k_map[i][j][o] = k.dot(rr[i][j]) for orbital1 in plane_wave_occ_orbitals: k1ad = k_map[0][3][orbital1] k1ae = k_map[0][4][orbital1] k1af = k_map[0][5][orbital1] for orbital2 in plane_wave_occ_orbitals: if orbital1 != orbital2: k2bd = k_map[1][3][orbital2] k2be = k_map[1][4][orbital2] k2bf = k_map[1][5][orbital2] for orbital3 in plane_wave_occ_orbitals: if orbital1 != orbital3 and orbital2 != orbital3: k3cd = k_map[2][3][orbital3] k3ce = k_map[2][4][orbital3] k3cf = k_map[2][5][orbital3] # Handle \delta_{ad} \delta_{bf} \delta_{ce} after FT. # The Fourier transform is spin-conserving. if spinless or ( (dual_basis_action[0][0] % 2 == dual_basis_action[3][0] % 2 == orbital1 % 2) and (dual_basis_action[1][0] % 2 == dual_basis_action[5][0] % 2 == orbital2 % 2) and (dual_basis_action[2][0] % 2 == dual_basis_action[4][0] % 2 == orbital3 % 2)): expectation_value += numpy.exp( -1j * (k1ad + k2bf + k3ce)) # Handle -\delta_{ad} \delta_{be} \delta_{cf} after FT. # The Fourier transform is spin-conserving. if spinless or ( (dual_basis_action[0][0] % 2 == dual_basis_action[3][0] % 2 == orbital1 % 2) and (dual_basis_action[1][0] % 2 == dual_basis_action[4][0] % 2 == orbital2 % 2) and (dual_basis_action[2][0] % 2 == dual_basis_action[5][0] % 2 == orbital3 % 2)): expectation_value -= numpy.exp( -1j * (k1ad + k2be + k3cf)) # Handle -\delta_{ae} \delta_{bf} \delta_{cd} after FT. # The Fourier transform is spin-conserving. if spinless or ( (dual_basis_action[0][0] % 2 == dual_basis_action[4][0] % 2 == orbital1 % 2) and (dual_basis_action[1][0] % 2 == dual_basis_action[5][0] % 2 == orbital2 % 2) and (dual_basis_action[2][0] % 2 == dual_basis_action[3][0] % 2 == orbital3 % 2)): expectation_value -= numpy.exp( -1j * (k1ae + k2bf + k3cd)) # Handle \delta_{ae} \delta_{bd} \delta_{cf} after FT. # The Fourier transform is spin-conserving. if spinless or ( (dual_basis_action[0][0] % 2 == dual_basis_action[4][0] % 2 == orbital1 % 2) and (dual_basis_action[1][0] % 2 == dual_basis_action[3][0] % 2 == orbital2 % 2) and (dual_basis_action[2][0] % 2 == dual_basis_action[5][0] % 2 == orbital3 % 2)): expectation_value += numpy.exp( -1j * (k1ae + k2bd + k3cf)) # Handle \delta_{af} \delta_{be} \delta_{cd} after FT. # The Fourier transform is spin-conserving. if spinless or ( (dual_basis_action[0][0] % 2 == dual_basis_action[5][0] % 2 == orbital1 % 2) and (dual_basis_action[1][0] % 2 == dual_basis_action[4][0] % 2 == orbital2 % 2) and (dual_basis_action[2][0] % 2 == dual_basis_action[3][0] % 2 == orbital3 % 2)): expectation_value += numpy.exp( -1j * (k1af + k2be + k3cd)) # Handle -\delta_{af} \delta_{bd} \delta_{ce} after FT. # The Fourier transform is spin-conserving. if spinless or ( (dual_basis_action[0][0] % 2 == dual_basis_action[5][0] % 2 == orbital1 % 2) and (dual_basis_action[1][0] % 2 == dual_basis_action[3][0] % 2 == orbital2 % 2) and (dual_basis_action[2][0] % 2 == dual_basis_action[4][0] % 2 == orbital3 % 2)): expectation_value -= numpy.exp( -1j * (k1af + k2bd + k3ce)) return expectation_value