Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation of fermionic hilbert and operator #1090

Merged
merged 41 commits into from Feb 16, 2022

Conversation

jwnys
Copy link
Collaborator

@jwnys jwnys commented Jan 31, 2022

This is an implementation of discrete fermionic degrees of freedom by @imi-hub and myself.
It contains the hilbert space and an operator. The operator handles the minus signs coming from the exchange symmetry, while the hilbert space stores occupation numbers only. This follows e.g. the way qiskit and openfermion would implement things.
For the operator, we follow the implementation of openfermion and added an 'from_openfermion' function to create operators. This allows us to use all their hamiltonians, such as Fermi-Hubbard.
The hilbert space is not optimized for fixed number of fermions (since it inherits from HomogeneousHilbert), for that we might need to add another Hilbert implementation.

FYI: formatting will fail because flake8 and flakehell are giving me hell.

@gcarleo
Copy link
Member

gcarleo commented Jan 31, 2022

The hilbert space is not optimized for fixed number of fermions (since it inherits from HomogeneousHilbert), for that we might need to add another Hilbert implementation.

don't we already have some kind of support for that for fock spaces? (actually, I would tend to say we can use the already existing fock hilbert without creating a new one? maybe I am mistaken...!)

@gcarleo
Copy link
Member

gcarleo commented Jan 31, 2022

what I mean is: can't you derive Fermions2nd from Fock directly?

@jwnys
Copy link
Collaborator Author

jwnys commented Jan 31, 2022

Good point, I'll look into that

@PhilipVinc
Copy link
Member

Can we be careful about that and discuss it briefly in person?

While I know it's possible to inherit from a non abstract class, I'd be wary of it because it has been a source of bugs in the past.

I'd prefer if in general non abstract things where not inherited from.

@gcarleo
Copy link
Member

gcarleo commented Jan 31, 2022

I'd prefer if in general non abstract things where not inherited from.

sure, actually I just meant to construct a Fock space, not inherit from it

@jwnys
Copy link
Collaborator Author

jwnys commented Jan 31, 2022

What do you mean, creating a class Fermions2nd which has a self._fock as field?

@gcarleo
Copy link
Member

gcarleo commented Jan 31, 2022

no I just suspect you can construct the object just by returning Fock(something), do you need extra methods that are not in fock?

@codecov-commenter
Copy link

codecov-commenter commented Jan 31, 2022

Codecov Report

Merging #1090 (19f3c25) into master (53769ed) will increase coverage by 0.14%.
The diff coverage is 76.18%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1090      +/-   ##
==========================================
+ Coverage   81.77%   81.91%   +0.14%     
==========================================
  Files         199      208       +9     
  Lines       12015    12526     +511     
  Branches     1800     1897      +97     
==========================================
+ Hits         9825    10261     +436     
- Misses       1762     1817      +55     
- Partials      428      448      +20     
Impacted Files Coverage Δ
netket/experimental/operator/_fermions_2nd.py 73.22% <73.22%> (ø)
netket/experimental/operator/fermion.py 76.92% <76.92%> (ø)
...tket/experimental/hilbert/spin_orbital_fermions.py 85.33% <85.33%> (ø)
...perimental/hilbert/random/spin_orbital_fermions.py 90.90% <90.90%> (ø)
netket/experimental/__init__.py 100.00% <100.00%> (ø)
netket/experimental/hilbert/__init__.py 100.00% <100.00%> (ø)
netket/experimental/hilbert/random/__init__.py 100.00% <100.00%> (ø)
netket/experimental/operator/__init__.py 100.00% <100.00%> (ø)
netket/operator/_local_operator.py 64.15% <0.00%> (-4.28%) ⬇️
netket/operator/_graph_operator.py 83.05% <0.00%> (-1.70%) ⬇️
... and 7 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 53769ed...19f3c25. Read the comment docs.

@jwnys
Copy link
Collaborator Author

jwnys commented Jan 31, 2022

Well, the idea is mostly to (in the next step) optimize this for fixed number of fermions, since that's relevant for 99% of all cases. I guess that would be less obvious with Fock?

@gcarleo
Copy link
Member

gcarleo commented Jan 31, 2022

Well, the idea is mostly to (in the next step) optimize this for fixed number of fermions, since that's relevant for 99% of all cases. I guess that would be less obvious with Fock?

but Fock is already optimized for fixed number of particles, as far as I remember (not sure why N is referred to as the number of bosonic modes in the docs though, since it's more general)

        Args:
          n_max: Maximum occupation for a site (inclusive). If None, the local
            occupation number is unbounded.
          N: number of bosonic modes (default = 1)
          n_particles: Constraint for the number of particles. If None, no constraint
            is imposed.
          graph: (Deprecated, pleaese use `N`) A graph, from which the number of nodes
            is extracted.

@gcarleo
Copy link
Member

gcarleo commented Jan 31, 2022

I would say that Fock(n_max=1, N=n_sites,n_particles=n_fermions) is already the fock space for spinless fermions at fixed number of particles... then if you have two orbitals just take the tensor product of two fock states etc?

@PhilipVinc
Copy link
Member

PhilipVinc commented Jan 31, 2022

girls/guys people something happened and i see tons of commits around and stuff that i think is not related?
Can you please clean it up?

@jwnys
Copy link
Collaborator Author

jwnys commented Jan 31, 2022

Should be ok now.

@PhilipVinc
Copy link
Member

By the way, if we are going to merge this in NetKet, i'd like to have this live for at least a few months in import netket.experimental as nkx for a while, while the interface gets refined by... you guys.

@jwnys
Copy link
Collaborator Author

jwnys commented Jan 31, 2022

Well, the idea is mostly to (in the next step) optimize this for fixed number of fermions, since that's relevant for 99% of all cases. I guess that would be less obvious with Fock?

but Fock is already optimized for fixed number of particles, as far as I remember (not sure why N is referred to as the number of bosonic modes in the docs though, since it's more general)

        Args:
          n_max: Maximum occupation for a site (inclusive). If None, the local
            occupation number is unbounded.
          N: number of bosonic modes (default = 1)
          n_particles: Constraint for the number of particles. If None, no constraint
            is imposed.
          graph: (Deprecated, pleaese use `N`) A graph, from which the number of nodes
            is extracted.

Fock uses the constraint function to impose the number of particles, so it enumerates them all and then removes the incorrect ones, if I understand correctly. What do we gain from inheriting from Fock and not Homogeneous? I don't see much gain...
So, the idea (after talking to Filippo) is now to keep inheriting from HomogeneousHilbert and to just overwrite all the correct _numbers_to_states etc. stuff if we want to optimize for fixed number of fermions. I'm not the biggest fan of this API, but I agree it makes conceptually more sense.

@jwnys
Copy link
Collaborator Author

jwnys commented Jan 31, 2022

By the way, if we are going to merge this in NetKet, i'd like to have this live for at least a few months in import netket.experimental as nkx for a while, while the interface gets refined by... you guys.

I will do this once we agree on the hilbert and operator concept, have a all the minimal implementations, etc.

@PhilipVinc
Copy link
Member

The problem is that the api of _constraint_fn, which is quite ugly, has never been thought to be completely overriden.
We should revisit that part of the API a bit...

It goes back to netket 1

@jwnys
Copy link
Collaborator Author

jwnys commented Feb 4, 2022

One thing I realized is the following: in this representation, if you do a translation operator for example, you need to define the parity of such an operator. So e.g. if you order your original sites as (0, 1, 2, 3) in some way (e.g. zigzag), then the translation brings this (on a 2x2 lattice) to (1, 0, 3, 2) for example. You then need to compute the parity of the (1, 0, 3, 2) permutation to determine the representation of this transformation in the given basis. This might be a bit annoying, but maybe it's fine if we just add some functions that can quickly compute the parity of such transformations. Alternatively, we define an additional operator type that does this. What do you think?

@PhilipVinc
Copy link
Member

Can you say something more about why you'd need me he parity? Where?

@jwnys
Copy link
Collaborator Author

jwnys commented Feb 4, 2022

This would be when you want to look at excitations, for example. Maybe it's not necessary to define it, but it might also be tricky because it's not a priori clear in this representation that you need such parity factors.

@gcarleo
Copy link
Member

gcarleo commented Feb 4, 2022

@jwnys yes I understand the issue, but I am not sure why you need this to be defined in the operator itself? (as far as I know we do not support transforming operators with symmetries, even for spins?)

@gcarleo
Copy link
Member

gcarleo commented Feb 4, 2022

what I am trying to say here is that we should think about more broadly about supporting symmetry transformations for operators/ quickly identifying the correct phase, but I think it's best to separate the discussion and do that in another PR?

@jwnys
Copy link
Collaborator Author

jwnys commented Feb 4, 2022

what I am trying to say here is that we should think about more broadly about supporting symmetry transformations for operators/ quickly identifying the correct phase, but I think it's best to separate the discussion and do that in another PR?

Ok, that makes sense, yeah. Thanks for the feedback.

@gcarleo
Copy link
Member

gcarleo commented Feb 4, 2022

Still, I am a bit unconvinced by the fact that we cannot derive/ construct this directly from Fock, since both the constraints and the local occupation numbers you need are exactly the same you already have there. Aren't we just going to duplicate the code to fix the total number of particles, for example?

@jwnys
Copy link
Collaborator Author

jwnys commented Feb 4, 2022

Still, I am a bit unconvinced by the fact that we cannot derive/ construct this directly from Fock, since both the constraints and the local occupation numbers you need are exactly the same you already have there. Aren't we just going to duplicate the code to fix the total number of particles, for example?

I don't really have a very strong opinion on this. It might be ok to do it like that. What I had in mind for fixed particles was to construct the hilbert states in blocks of fixed number of fermions. In that case the ordering would be rather different from e.g. Fock where you list all possibilities and just delete the ones that violate the constraint. The advantage would be that you can do ED for bigger systems. However, the disadvantage would be that our matrix then looks quite different from other libraries, since the convention of ordering the states would be different.
In any case, maybe we could just leave this for later and use Fock for now.

Copy link
Member

@gcarleo gcarleo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a few points in the API I guess need to be clarified, but otherwise it's good! can we also maybe add a small example (say, Hubbard model or spinless fermions) or even (ideally, if you or Imelda have time) a tutorial with ED?

netket/hilbert/fermions_2nd.py Outdated Show resolved Hide resolved
netket/hilbert/fermions_2nd.py Outdated Show resolved Hide resolved
netket/hilbert/fermions_2nd.py Outdated Show resolved Hide resolved
@jwnys
Copy link
Collaborator Author

jwnys commented Feb 13, 2022

To summarize, the new version: it's a lot faster for symbolic operations and implements many more things like iadd, etc (following the new implementation of LocalOperator by @PhilipVinc ).
I've changed the spin=None default argument and made some more small changes. I think this version is close to final for now.

netket/experimental/operator/_fermions_2nd.py Outdated Show resolved Hide resolved
netket/experimental/operator/_fermions_2nd.py Outdated Show resolved Hide resolved
netket/experimental/operator/_fermions_2nd.py Outdated Show resolved Hide resolved
netket/experimental/operator/_fermions_2nd.py Outdated Show resolved Hide resolved
netket/experimental/operator/_fermions_2nd.py Outdated Show resolved Hide resolved
netket/experimental/operator/_fermions_2nd.py Show resolved Hide resolved
netket/experimental/operator/_fermions_2nd.py Outdated Show resolved Hide resolved
netket/experimental/operator/_fermions_2nd.py Outdated Show resolved Hide resolved
Copy link
Member

@PhilipVinc PhilipVinc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some more stuff

netket/experimental/operator/_fermions_2nd.py Outdated Show resolved Hide resolved
netket/experimental/operator/_fermions_2nd.py Outdated Show resolved Hide resolved
netket/experimental/operator/_fermions_2nd.py Outdated Show resolved Hide resolved
netket/experimental/operator/_fermions_2nd.py Show resolved Hide resolved
netket/experimental/operator/_fermions_2nd.py Outdated Show resolved Hide resolved
netket/experimental/operator/_fermions_2nd.py Show resolved Hide resolved
netket/experimental/operator/_fermions_2nd.py Show resolved Hide resolved
netket/experimental/operator/_fermions_2nd.py Outdated Show resolved Hide resolved
netket/experimental/operator/_fermions_2nd.py Show resolved Hide resolved
netket/experimental/operator/_fermions_2nd.py Outdated Show resolved Hide resolved
Copy link
Member

@PhilipVinc PhilipVinc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, there's only a few missing tests and we're ready to merge.

netket/experimental/operator/fermion.py Show resolved Hide resolved
netket/experimental/operator/fermion.py Show resolved Hide resolved
netket/experimental/operator/fermion.py Show resolved Hide resolved
netket/experimental/operator/_fermions_2nd.py Show resolved Hide resolved
Copy link
Member

@PhilipVinc PhilipVinc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems good to me now.

@PhilipVinc
Copy link
Member

Assuming tests pass*

@PhilipVinc
Copy link
Member

PhilipVinc commented Feb 15, 2022

Tests pass, so this can be merged now.
@jwnys Could you just add the new hilbert space and operator to the documentation, under the experimental section? the file is 'docs/docs/api-experimental.md` i think

@gcarleo
Copy link
Member

gcarleo commented Feb 16, 2022

good to squash and merge for me

@PhilipVinc PhilipVinc merged commit 75a602a into netket:master Feb 16, 2022
nikosavola pushed a commit to nikosavola/netket that referenced this pull request Jun 4, 2022
This is an implementation of discrete fermionic degrees of freedom by @imi-hub and myself.

It contains the hilbert space and an operator. The operator handles the minus signs coming from the exchange symmetry, while the hilbert space stores occupation numbers only. This follows e.g. the way qiskit and openfermion would implement things.

For the operator, we follow the implementation of openfermion and added an 'from_openfermion' function to create operators. This allows us to use all their hamiltonians, such as Fermi-Hubbard.

Co-authored-by: Imelda Romero <imelda.romero@epfl.ch>
Co-authored-by: Filippo Vicentini <filippovicentini@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants