quantumlib / OpenFermion-FQE

The Fermionic Quantum Emulator (FQE) is a fermionic simulation research tool specializing in quantum circuits emulating fermion dynamics.
Apache License 2.0
61 stars 26 forks source link

Spinless fermionic tight binding: Time evolution yields AssertionError #133

Open hariseldon99 opened 9 months ago

hariseldon99 commented 9 months ago

Hi,

Noob here. Tried to time-evolve a TB Hamiltonian for spinless fermions, strting from a half-filled state

  import fqe 
  from openfermion import FermionOperator,hermitian_conjugated
  N=2
  M=4
  half_full = fqe.get_wavefunction(N, N, M)
  half_full.set_wfn(strategy='hartree-fock')
  half_full.print_wfn()

  #Periodic boundary conditions
  forward_hop = FermionOperator(((M-1,1),(0,0))) 
  for i in range(M-1):
      forward_hop += FermionOperator(((i,1),(i+1,0))) 

  tb_hamilt = forward_hop + hermitian_conjugated(forward_hop)
  fqe_ham = tb_hamilt

  fqe_ham = tb_hamilt
  #Evolve ballistically in time for t=10.2
  display(fqe_ham)
  psi_t = half_full.time_evolve(10.2, fqe_ham)
  psi_t.print_wfn()

Gave the following traceback:

  Sector N = 2 : S_z = 2
  a'0011'b'0000' (1+0j)
  1.0 [0^ 1] +
  1.0 [0^ 3] +
  1.0 [1^ 0] +
  1.0 [1^ 2] +
  1.0 [2^ 1] +
  1.0 [2^ 3] +
  1.0 [3^ 0] +
  1.0 [3^ 2]
  ---------------------------------------------------------------------------
  AssertionError                            Traceback (most recent call last)
  Cell In[6], line 22
       20 #Evolve ballistically in time for t=10.2
       21 display(fqe_ham)
  ---> 22 psi_t = half_full.time_evolve(10.2, fqe_ham)
       23 psi_t.print_wfn()

  File /usr/local/miniforge3/envs/openfermion/lib/python3.10/site-packages/fqe/fqe_decorators.py:393, in wrap_time_evolve.<locals>.convert(self, time, ops, inplace)
      383 """ Converts an FermionOperator to hamiltonian.Hamiltonian
      384 
      385 Args:
     (...)
      388     ops (FermionOperator or Hamiltonian): input operator
      389 """
      390 hamil = build_hamiltonian(ops,
      391                           norb=self.norb(),
      392                           conserve_number=self.conserve_number())
  --> 393 return time_evolve(self, time, hamil, inplace)

  File /usr/local/miniforge3/envs/openfermion/lib/python3.10/site-packages/fqe/wavefunction.py:1016, in Wavefunction.time_evolve(self, time, hamil, inplace)
     1013 else:
     1014     transformation = hamil.calc_diag_transform()
  -> 1016     permu, low, upp, work_wfn = work_wfn.transform(
     1017         transformation)
     1019     ci_trans = transformation @ permu
     1021     h1e = hamil.transform(ci_trans)

  File /usr/local/miniforge3/envs/openfermion/lib/python3.10/site-packages/fqe/wavefunction.py:926, in Wavefunction.transform(self, rotation, low, upp)
      924         civec.apply_columns_recursive_inplace(output, output)
      925 elif rotation.shape[0] == norb * 2:
  --> 926     assert numpy.std(rotation[:norb, norb:]) \
      927            + numpy.std(rotation[norb:, :norb]) < 1.0e-8
      928     if not external:
      929         perm1, low1, upp1 = ludecomp(rotation[:norb, :norb])

  AssertionError: 

Update: Ballistic evolution works fine:

  from openfermion import FermionOperator
  import fqe 
  N=3
  M=6

  N_op = FermionOperator('0^ 0')
  for i in range(1, M):
      N_op += FermionOperator(((i,1),(i,0)))

  wfn_fqe = fqe.get_wavefunction(N, N, M)
  wfn_fqe.set_wfn(strategy='hartree-fock')

  #N_op+= FermionOperator('0^ 1') + FermionOperator('1^ 0')

  psi_t = wfn_fqe.time_evolve(10.2, N_op)
  psi_t.print_wfn()

Yields

  Sector N = 3 : S_z = 3
  a'000111'b'000000' (0.6851938352639844+0.7283607678315959j)

Uncomment the hopping term, and the AssertionError is raised again.

awhite862 commented 8 months ago

I believe the problem is that FQE assumes that each FermionOperator is in the spin-orbital basis. So indices 0, 1, 2, ... refer to (spatial orbital 0, alpha), (spatial orbital 0, beta), (spatial orbital 1, alpha), .... With this convention, the hopping term you wrote does not conserve spin and this causes an (unclear) error because the wfn_fqe is supposed to have fixed spin. If you instead make the hopping term spin conserving like:

N_op += FermionOperator('0^ 2') + FermionOperator('2^ 0')  # alpha part
N_op += FermionOperator('1^ 3') + FermionOperator('3^ 1')  # beta part

I think it should work (the beta part may be unnecessary in this case)

hariseldon99 commented 8 months ago

If I wanna deal with spinless fermions, do I just ignore the beta part?

awhite862 commented 8 months ago

Yes, if you create a wavefunction with only alpha fermions (I think you do this in the original post) then it can be used as a representation of spinless fermions