def hf_rdm(n_alpha: int, n_beta: int, n_orbitals: int) -> InteractionRDM: """Construct the RDM corresponding to a Hartree-Fock state. Args: n_alpha (int): number of spin-up electrons n_beta (int): number of spin-down electrons n_orbitals (int): number of spatial orbitals (not spin orbitals) Returns: openfermion.ops.InteractionRDM: the reduced density matrix """ # Determine occupancy of each spin orbital occ = np.zeros(2 * n_orbitals) occ[:(2 * n_alpha):2] = 1 occ[1:(2 * n_beta + 1):2] = 1 one_body_tensor = np.diag(occ) two_body_tensor = np.zeros([2 * n_orbitals for i in range(4)]) for i in range(2 * n_orbitals): for j in range(2 * n_orbitals): if i != j and occ[i] and occ[j]: two_body_tensor[i, j, j, i] = 1 two_body_tensor[i, j, i, j] = -1 return InteractionRDM(one_body_tensor, two_body_tensor)
def get_rdms_from_psi4(wfn, ndocc=None, nact=None): """Get 1- and 2-RDMs from a Psi4 calculation. Args: wfn (psi4.core.Wavefunction): Psi4 wavefunction object ndocc (int): number of doubly occupied molecular orbitals to exclude from the saved RDM. nact (int): number of active molecular orbitals to include in the saved RDM. Returns: rdm (openfermion.ops.InteractionRDM): an openfermion object storing 1- and 2-RDMs. """ if nact is None and ndocc is None: ndocc = 0 nact = wfn.Ca().to_array(dense=True).shape[1] print( f"Active space selection options were reset to: ndocc = {ndocc} and nact = {nact}" ) elif nact is not None and ndocc is None: assert nact <= wfn.Ca().to_array(dense=True).shape[1] ndocc = 0 print( f"Active space selection options were reset to: ndocc = {ndocc} and nact = {nact}" ) elif ndocc is not None and nact is None: assert ndocc <= wfn.Ca().to_array(dense=True).shape[1] nact = wfn.Ca().to_array(dense=True).shape[1] - ndocc print( f"Active space selection options were reset to: ndocc = {ndocc} and nact = {nact}" ) one_rdm_a = np.array(wfn.get_opdm(0, 0, "A", True)).reshape(wfn.nmo(), wfn.nmo()) one_rdm_b = np.array(wfn.get_opdm(0, 0, "B", True)).reshape(wfn.nmo(), wfn.nmo()) # Get 2-RDM from CI calculation. assert nact == wfn.nmo() - wfn.nfrzc() - wfn.frzvpi().sum() assert ndocc == wfn.nfrzc() two_rdm_aa = np.array(wfn.get_tpdm("AA", False)).reshape(nact, nact, nact, nact) two_rdm_ab = np.array(wfn.get_tpdm("AB", False)).reshape(nact, nact, nact, nact) two_rdm_bb = np.array(wfn.get_tpdm("BB", False)).reshape(nact, nact, nact, nact) # adjusting 1-RDM # Indices of active molecular orbitals active_indices = range(ndocc, ndocc + nact) one_rdm_a = one_rdm_a[np.ix_(active_indices, active_indices)] one_rdm_b = one_rdm_b[np.ix_(active_indices, active_indices)] one_rdm, two_rdm = unpack_spatial_rdm( one_rdm_a, one_rdm_b, two_rdm_aa, two_rdm_ab, two_rdm_bb ) rdms = InteractionRDM(one_rdm, two_rdm) return rdms
def convert_dict_to_interaction_rdm(dictionary): """Get an InteractionRDM from a dictionary. Args: dictionary (dict): the dictionary representation Returns: op (openfermion.ops.InteractionRDM): the operator """ one_body_tensor = convert_dict_to_array(dictionary["one_body_tensor"]) two_body_tensor = convert_dict_to_array(dictionary["two_body_tensor"]) return InteractionRDM(one_body_tensor, two_body_tensor)
def get_ground_state_rdm_from_qubit_op( qubit_operator: QubitOperator, n_particles: int ) -> InteractionRDM: """Diagonalize operator and compute the ground state 1- and 2-RDM Args: qubit_operator (openfermion.QubitOperator): The openfermion operator to diagonalize n_particles (int): number of particles in the target ground state Returns: rdm (openfermion.InteractionRDM): interaction RDM of the ground state with the particle number n_particles """ sparse_operator = get_sparse_operator(qubit_operator) e, ground_state_wf = jw_get_ground_state_at_particle_number( sparse_operator, n_particles ) # float/np.array pair n_qubits = count_qubits(qubit_operator) one_body_tensor = [] for i in range(n_qubits): for j in range(n_qubits): idag_j = get_sparse_operator( FermionOperator(f"{i}^ {j}"), n_qubits=n_qubits ) idag_j = idag_j.toarray() one_body_tensor.append( np.conjugate(ground_state_wf) @ idag_j @ ground_state_wf ) one_body_tensor = np.array(one_body_tensor) one_body_tensor = one_body_tensor.reshape(n_qubits, n_qubits) two_body_tensor = np.zeros((n_qubits,) * 4, dtype=complex) for p in range(n_qubits): for q in range(0, p + 1): for r in range(n_qubits): for s in range(0, r + 1): pdag_qdag_r_s = get_sparse_operator( FermionOperator(f"{p}^ {q}^ {r} {s}"), n_qubits=n_qubits ) pdag_qdag_r_s = pdag_qdag_r_s.toarray() rdm_element = ( np.conjugate(ground_state_wf) @ pdag_qdag_r_s @ ground_state_wf ) two_body_tensor[p, q, r, s] = rdm_element two_body_tensor[q, p, r, s] = -rdm_element two_body_tensor[q, p, s, r] = rdm_element two_body_tensor[p, q, s, r] = -rdm_element return InteractionRDM(one_body_tensor, two_body_tensor)
def setUp(self): n_modes = 2 np.random.seed(0) one_body_tensor = np.random.rand(*(n_modes, ) * 2) two_body_tensor = np.random.rand(*(n_modes, ) * 4) self.interaction_rdm = InteractionRDM(one_body_tensor, two_body_tensor)
[ [0.0, -0.10410015, 0.0, 0.0], [0.10410015, 0.0, -0.0, 0.0], [0.0, 0.0, 0.0, 0.01095689], [-0.0, 0.0, -0.01095689, 0.0], ], [ [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], ], ], ]) rdms = InteractionRDM(rdm1, rdm2) @pytest.mark.parametrize( "term1,term2,expected_result", [ (((0, "Y"), ), ((0, "X"), ), False), (((0, "Y"), ), ((1, "X"), ), True), (((0, "Y"), (1, "X")), (), True), ], ) def test_is_comeasureable(term1, term2, expected_result): assert is_comeasureable(term1, term2) == expected_result @pytest.mark.parametrize(