OpenFermion icon indicating copy to clipboard operation
OpenFermion copied to clipboard

Allowing more general indices for SymbolicOperator

Open obriente opened this issue 5 years ago • 3 comments

Currently, we only allow the index of a SymbolicOperator to be a single number. In some cases (e.g. conversion to a sparse matrix or to a PolynomialTensor) this is required, but in many cases it makes sense to label spin or fermionic creation/annihilation operators with more than just one index. E.g. to represent spin, or to put on a lattice. Currently the user then has to keep track of the mapping from multi-index -> single integer themselves, which can be difficult.

I propose we allow a more general set of indices for SymbolicOperator. I think we can deal with the above conversion issues by insisting that we always have a total order on the class. Two options spring to mind: a) allowing tuples with the convention that in checking a > b we first check a[0] > b[0], then a[1] > b[1], etc, and b) writing a general 'index' class that lets the user generalize this further.

Thoughts? @ncrubin

obriente avatar Nov 26 '20 10:11 obriente

I'll have to certainly think about this more. For inspiration you can checkout what I do in the representability library in third_party.

https://github.com/quantumlib/OpenFermion/blob/master/src/openfermion/third_party/representability/_bijections.py

I define a bijection which maps you from one set of labels to another. I did this pretty much because of the scenario you are describing. Sometimes it is easier to index things in a notation that might be closer to physics.

My concern for building in an index bijection at the base level is that it adds a lot of maintenance overhead. I also think it would be fairly complicated to implement. Why not have something above SymbolicOperator that absorbs the logic of indexing. You can have various grids for different spatial or brillouin zone geometries. All the logic for indexing could be above SymbolicOperator.

ncrubin avatar Nov 27 '20 23:11 ncrubin

Thanks for the quick reply, and that's a useful link.

I agree with the worries about implementation + maintenance, which is why I figured raising the issue for discussion might be a good idea (maybe this is more appropriate to bring up in the Google Group?). I think I'd like to push for something minimal that doesn't change much:

As far as I am aware, as long as the user provides indices that are hashable, then the current data structure doesn't actually need to be changed --- we just need to be able to use ((index, action),... ) tuples as dictionary keys. So a simple change would be just removing the restriction on indices being integers and just let them be hashable.

The issue however is that this will break many functions e.g. jordan_wigner() or get_sparse_operator() if the user passes in an operator that doesn't have integers as indices. Obviously there's a pretty simple workaround here - use the bijection object you described to make a new SymbolicOperator with the right indices, do the transform, and then invert the bijection on the new object. I'm inclined towards just making 'order_operator_indices' and 'revert_operator_indices' functions which do this, exposing these to the user, and then adding some documentation and explicit errors to the functions where people might hit an error. This way we're being as explicit as possible, and if someone wants to write their own ordering function to make use of some structure in the problem they're free to do so.

Does this sound reasonable, or do you think I've missed something?

obriente avatar Nov 28 '20 14:11 obriente

Probably bringing up on Google Group is good too since the group will be pinged about this discussion.

I am still biased towards building something on top of the existing infrastructure instead of building 'order_operator_indices' into SymbolicOperator. I am imagining a new object "LatticeIndexing" or whatever you want to call it that inherits from SymbolicOperator but then just redefines the index map the way you are suggesting. That way you get the functionality you want, we provide a template on how to extend functionality for the various scenarios I mentioned before, and we don't touch any of the existing infrastructure.

Building in bijections would be a fairly large project and to do it well I think we should build a couple of prototypes. An easy way to start is to build something on top of SymbolicOperator before we start changing the internal infrastructure of the object. That way we can see tradeoffs to be made.

ncrubin avatar Nov 28 '20 19:11 ncrubin