def from_cirq(state: numpy.ndarray, thresh: float) -> 'wavefunction.Wavefunction': """Interoperability between cirq and the openfermion-fqe. This takes a cirq wavefunction and creates an FQE wavefunction object initialized with the correct data. Args: state (numpy.array(dtype=numpy.complex128)) - a cirq wavefunction thresh (double) - set the limit at which a cirq element should be \ considered zero and not make a contribution to the FQE wavefunction Returns: openfermion-fqe.Wavefunction """ param = [] nqubits = int(numpy.log2(state.size)) norb = nqubits // 2 for pnum in range(nqubits + 1): occ = qubit_particle_number_index_spin(nqubits, pnum) for orb in occ: if numpy.absolute(state[orb[0]]) > thresh: param.append([pnum, orb[1], norb]) param_set = set([tuple(p) for p in param]) param_list = [list(x) for x in param_set] wfn = wavefunction.Wavefunction(param_list) transform.from_cirq(wfn, state) return wfn
def test_fqe_to_fermion_operator(self): """Convert the fqe representation to openfermion operators. Note: Due to the unique OpenFermion data structure and the conversion of the data internally, test requires an iterative stucture rather than assertDictEqual """ def _calc_coeff(val): return round(val / numpy.sqrt(30.0), 7) + .0j coeff = [ _calc_coeff(1.0), _calc_coeff(2.0), _calc_coeff(3.0), _calc_coeff(4.0) ] data = numpy.array([[coeff[0]], [coeff[1]], [coeff[2]], [coeff[3]]], dtype=numpy.complex128) test = FermionOperator('0^ 1^', coeff[0]) test += FermionOperator('0^ 3^', coeff[1]) test += FermionOperator('2^ 1^', coeff[2]) test += FermionOperator('2^ 3^', coeff[3]) wfn = wavefunction.Wavefunction([[2, 0, 2]]) data = numpy.reshape(data, (2, 2)) passed_data = {(2, 0): data} wfn.set_wfn(strategy='from_data', raw_data=passed_data) ops = openfermion_utils.fqe_to_fermion_operator(wfn) self.assertListEqual(list(ops.terms.keys()), list(test.terms.keys())) for term in ops.terms: self.assertAlmostEqual(ops.terms[term], test.terms[term])
def test_operator(self): """Testing base FqeOperator using a dummy class""" # The Test class is just to make sure the Hamiltonian class is tested. # pylint: disable=useless-super-delegation class Test(fqe_operator.FqeOperator): """A testing dummy class.""" def contract( self, brastate: "wavefunction.Wavefunction", ketstate: "wavefunction.Wavefunction", ) -> complex: return super().contract(brastate, ketstate) def representation(self) -> str: return super().representation() def rank(self) -> int: return super().rank() test = Test() wfn = wavefunction.Wavefunction([[1, 0, 1]]) self.assertAlmostEqual(0.0 + 0.0j, test.contract(wfn, wfn)) self.assertEqual("fqe-operator", test.representation()) self.assertEqual(0, test.rank())
def test_ops_general(self): """Check general properties of the fqe_ops.""" s_2 = S2Operator() self.assertEqual(s_2.representation(), "s_2") self.assertEqual(s_2.rank(), 2) s_z = SzOperator() self.assertEqual(s_z.representation(), "s_z") self.assertEqual(s_z.rank(), 2) t_r = TimeReversalOp() self.assertEqual(t_r.representation(), "T") self.assertEqual(t_r.rank(), 2) num = NumberOperator() self.assertEqual(num.representation(), "N") self.assertEqual(num.rank(), 2) wfn = wavefunction.Wavefunction([[4, 2, 4], [4, 0, 4]]) self.assertRaises(ValueError, t_r.contract, wfn, wfn) wfn = wavefunction.Wavefunction([[4, -2, 4], [4, 0, 4]]) self.assertRaises(ValueError, t_r.contract, wfn, wfn)
def Wavefunction(param: List[List[int]], broken: Optional[Union[List[str], str]] = None): """Initialize a wavefunction through the fqe namespace Args: param (List[List[int]]) - parameters for the sectors broken (Union[List[str], str]) - symmetry to be broken Returns: (wavefunction.Wavefunction) - a wavefunction object meeting the \ criteria laid out in the calling argument """ return wavefunction.Wavefunction(param, broken=broken)
def get_wavefunction(nele: int, m_s: int, norb: int) -> 'wavefunction.Wavefunction': """Build a wavefunction with definite particle number and spin. Args: nele (int) - the number of electrons in the system m_s (int) - the s_z spin projection of the system norb (int) - the number of spatial orbtials to used Returns: (wavefunction.Wavefunction) - a wavefunction object meeting the \ criteria laid out in the calling argument """ arg = [[nele, m_s, norb]] return wavefunction.Wavefunction(param=arg)
def get_wavefunction_multiple(param: List[List[int]] ) -> List['wavefunction.Wavefunction']: """Generate many different wavefunctions. Args: param (list[list[nele, m_s, norb]]) - a list of parameters used to \ initialize wavefunctions. The arguments in the parameters are nele (int) - the number of electrons in the system; m_s (int) - the s_z spin projection of the system; norb (int) - the number of spatial orbtials to used Returns: list[(wavefunction.Wavefunction)] - a list of wavefunction objects """ state = [] for val in param: state.append(wavefunction.Wavefunction(param=[val])) return state
def get_number_conserving_wavefunction(nele: int, norb: int ) -> 'wavefunction.Wavefunction': """Build a wavefunction Args: nele (int) - the number of electrons in the system norb (int) - the number of orbitals Returns: (wavefunction.Wavefunction) - a wavefunction object meeting the \ criteria laid out in the calling argument """ param = [] maxb = min(norb, nele) minb = nele - maxb for nbeta in range(minb, maxb + 1): m_s = nele - nbeta * 2 param.append([nele, m_s, norb]) return wavefunction.Wavefunction(param, broken=['spin'])
def get_spin_conserving_wavefunction(s_z: int, norb: int) -> 'wavefunction.Wavefunction': """Return a wavefunction which has s_z conserved Args: s_z (int) - the value of :math:`S_z` norb (int) - the number of orbitals in the system Returns: (Wavefunction) - wave function initialized to zero """ param = [] if s_z >= 0: max_ele = norb + 1 min_ele = s_z if s_z < 0: max_ele = norb + s_z + 1 min_ele = 0 for nalpha in range(min_ele, max_ele): param.append([2 * nalpha - s_z, s_z, norb]) return wavefunction.Wavefunction(param, broken=['number'])