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

4/4! - transform functions. #232

Merged
merged 94 commits into from
Mar 5, 2018
Merged

4/4! - transform functions. #232

merged 94 commits into from
Mar 5, 2018

Conversation

conta877
Copy link
Contributor

@conta877 conta877 commented Mar 2, 2018

final pull request for #154
transforms demo,
predefined transforms & their tests

I really wanted to name the file code_transformers... 🤖

conta877 and others added 30 commits January 18, 2018 09:36
…ing mathematica code. it was giving wrong operators before, now the operators are fine but signs are wonky
…to count qubit/fermion labels from 1 instead of 0
…ht) as a tool to append the same code intance several times
…sts for symbolicBinary. minor mods for python3 comp.
…ode, added an error if qubit index in a code is out of bounds


def _encoder_checksum(modes):
""" Outputs the encoder matrix for checksum codes.
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you add a couple lines describing the checksum code?

Copy link
Contributor

@babbush babbush left a comment

Choose a reason for hiding this comment

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

Just add a little more explanation about some of these codes and we're good to go. Thanks for a great contribution overall!


def weight_one_binary_addressing_code(exponent):
""" Weight-1 binary addressing code.

Copy link
Contributor

Choose a reason for hiding this comment

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

Again, it would be good to have some more explanation of what these codes are and why people might be interested in them.

def test_jordan_wigner(self):
hamiltonian, gs_energy = lih_hamiltonian()
code = jordan_wigner_code(4)
qubit_hamiltonian = binary_code_transform(hamiltonian, code)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this supposed to do the same thing as the already-implemented jordan_wigner? If so, can we add a test that it does? Same for Bravyi-Kitaev.

Copy link
Collaborator

Choose a reason for hiding this comment

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

@conta877 @kevinsung @babbush I wonder if it would make sense to have jordan_wigner alias to this (eliminating duplicate code) - does being more general mean that this code is slower / is there any other reason not to?

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree with @kevinsung 's suggestion but am very opposed to @idk3 's suggestion. The implementation of Jordan-Wigner using the CodeOperator is significantly more complex. The Jordan-Wigner code might be useful to forks of OpenFermion that don't involve CodeOperator. The performance is also likely better in the more simple implementation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I agree that we should keep both. I also think its a good example of code transforms for people. I didn't check jordan-wigner implementation but the Bravyi-Kitaevs produce different qubitOperators.

Choose a reason for hiding this comment

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

Really ? Let me have a look at that - I tend to accidentally switch the two matrices. In any case it seems to be a valid transform, since it passed the test.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Because the mode with the highest index is always the root of the Fenwick tree (see arXiv:1701.07072).

Choose a reason for hiding this comment

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

Implementing our version, I followed the instructions in 1208.5986 and S. Tranter's paper. There they segment the matrix if its in between two dimension that are consecutive integer powers of two. It seems like the Fenwick-tree mapping is different.

Copy link
Collaborator

Choose a reason for hiding this comment

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

@msteudtner I think you're right. Perhaps this PR should use our implementation of Fenwick trees (contained in transforms) to define the Bravyi-Kitaev code? @babbush do you have an opinion? It seems that the code definitions are fundamentally different between 1208.5986 and 1701.07072.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Ok I just saw your comment below.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Based on the discussion below, I'm content with just checking that the JW (not BK) gives the same QubitOperators as the existing implementation, and that the new BK gives isospectral operators (does not need to give identical QubitOperators).

@conta877
Copy link
Contributor Author

conta877 commented Mar 3, 2018 via email

@kevinsung
Copy link
Collaborator

Is it true that arXiv:1208.5986 implicitly assumes that the number of qubits is a power of 2? Our implementation does not.

@babbush
Copy link
Contributor

babbush commented Mar 3, 2018

@kevinsung no, that is not assumed in any way by arXiv:1208.5986.

@babbush
Copy link
Contributor

babbush commented Mar 3, 2018

I had been under the impression that the Fenwick tree transform was just a different way of implementing essentially the same mapping. But you seem to be correct that there are real difference. This is interesting and suggests that perhaps we should have both types of BK implemented. I am curious to understand more about these differences. If I recall correctly, @VojtaHavlicek implemented the Fenwick tree BK. But @kanavsetia or @jarrodmcc may also have some insights about this difference...

In any event, this is really an issue that is unrelated to the quality of the pull request under review here. I think if you show your BK is isospectral and your JW gives the same JW transform as elsewhere in OpenFermion, that should be enough.

@kevinsung
Copy link
Collaborator

kevinsung commented Mar 3, 2018

I have not scrutinized 1208.5986, but my understanding is that it defines the BK transform for powers of 2 and then reduces the case of a general integer to the power-of-2 case by using its binary expansion and applying multiple power-of-2 BK transforms.

@kanavsetia
Copy link

I think @kevinsung got it right. BK transform of 1208.5986 explicitly defines the transform for powers of 2 (as is evident from figure2 in the paper) but that is not the case for 1701.07072, which is more general.
And I think this is what is causing the discrepancy. For 1208.5986 no matter how many qubits you use, even qubits will always hold just their occupancy, and odd qubits contain their occupancy as well as occupancy of other adjacent qubits. So, if you are looking for the occupancy of 6th qubit, no matter the total number of qubits (which in this case will always be powers of 2), you will always just operate of 6th qubit.
But this is little different for 1701.07072, where, which qubit stores what is also dependent on the number of qubits. If you have total number of qubits as some power of 2, I think you will get the same answer as in 1208.5986. But for general case this will be different.

@babbush
Copy link
Contributor

babbush commented Mar 3, 2018

I understand what you are talking about now. I thought Kevin was saying it would only work for a binary power number of qubits.

@kevinsung
Copy link
Collaborator

Yes, the Fenwick tree approach is more general, and I think it should be relatively straightforward to use the existing Fenwick tree code to define the BinaryCode used in bravyi_kitaev_code (I admit I don't know the details though).

@babbush
Copy link
Contributor

babbush commented Mar 3, 2018

This would be a nice but I won't require it. So long as their Jordan-Wigner encoder matches our Jordan-Wigner and their Bravyi-Kitaev encoder gives the transformation from 1208.5986 while also being isospectral, to our JW/BK, I think that is good enough for now.

@kevinsung
Copy link
Collaborator

Sure, I agree that this should not be a requirement for this PR. However, if we plan to keep two different implementations of BK in OpenFermion then we should remember to make it clear in the documentation.

@conta877
Copy link
Contributor Author

conta877 commented Mar 3, 2018

Ok - I will add the tests and in the description for BK I'll mention which paper the transformation is based on.

@kevinsung kevinsung mentioned this pull request Mar 3, 2018
@conta877
Copy link
Contributor Author

conta877 commented Mar 5, 2018

ready for review!

Copy link
Contributor

@babbush babbush left a comment

Choose a reason for hiding this comment

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

Just a few minor things. Thanks!

@@ -16,6 +16,7 @@
from ._bravyi_kitaev import bravyi_kitaev
from ._binary_code_transform import (binary_code_transform,
dissolve)
from ._code_transform_functions import *
Copy link
Contributor

Choose a reason for hiding this comment

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

please write explicitly what you are importing here so that it is clear to everyone what exists in the namespace of the transforms module.

return mtx[0:dimension, 0:dimension]


def _decoder_bk(modes):
Copy link
Contributor

Choose a reason for hiding this comment

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

I would recommend calling this n_modes to be consistent with the sort of notation we use elsewhere.

from openfermion.ops import BinaryCode, SymbolicBinary, linearize_decoder


def _encoder_bk(dimension):
Copy link
Contributor

Choose a reason for hiding this comment

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

There is probably some obvious reason why you use "dimension" here and "modes" below?

return BinaryCode(encoder, decoder)


def weight_one_segment_code():
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm a little confused why this function that only works for 2-qubits is necessary.

['w0 w1 + w0', 'w0 w1 + w1', ' w0 w1'])


def weight_two_segment_code():
Copy link
Contributor

Choose a reason for hiding this comment

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

Same question as above.

@conta877
Copy link
Contributor Author

conta877 commented Mar 5, 2018

ready!

@babbush babbush merged commit 8856404 into quantumlib:master Mar 5, 2018
philipp-q pushed a commit to philipp-q/OpenFermion that referenced this pull request Sep 2, 2020
* fixed bohr/angstrom confusion in function description

* translations from mathematica to python arxiv1712.07067

* work on those notimplementeds

* WIP: decoder class adittion

* modified decoder class. extractor implemented

* no need for pauliaction function

* introduction of symbolic binary class - no more decoder class

* minor bugs fixed, applies binary rules to input now

* started programming the BinaryCode class, work in progress

* added count qubit function in binary operator, modified code.py

* fixed morning brain bugs

* implemented concatination and appending, not yet documented and debugged

* added _shift function to symbolicBinary and integer addition. modified the decoder shifter accordinly

* radd imul, NOT TESTED! - just copy paste should work?

* fixed small bugs, added default codes, created transform

* fixed the multiplication error and modified the transform code following mathematica code. it was giving wrong operators before, now the operators are fine but signs are wonky

* fixed the transform and all the places where we accidentally started to count qubit/fermion labels from 1 instead of 0

* bug fixes: ordering matters to detect which terms should cancel

* fixed code appending, introduced the integer multiplication (left+right) as a tool to append the same code intance several times

* modified the multiply by 0 and 1 behavior in SymbolicBinary. added tests for symbolicBinary. minor mods for python3 comp.

* fixed the condition for code concatenation, fixed a bug in checksum_code, added an error if qubit index in a code is out of bounds

* added comments to binary_operator, more test, evaluate function

* started writing documentations and clipping lines, writing out numpy

* merging with the merger

* updating binary operator based on comments

* updating the binary_ops

* updates based on comments

* init update

* moved binaryop to first import

* added names into notice and readme

* started documentation in  _code_operator.py, added parity code / (K=1) and (K=2) segment code / K=1 binary addressing code

* encoders are sparse matrices now

* added tests for code_operator

* doc strings for the transform, fixed bug in the initialization of SymbolicBinary, made changes suggested by review, carried some of them over to files to be pulled later

* updates based on pull request comments

* merging changes with merger

* fixing possible integer checking errors

* cleaned version of transform function, needs testing and timing - seems to work so far

* fixed BK transforms. indexing errors

* added tests, pep8 and Ryan compliance mods

* added some style to the functions file

* renaming, re-structuring

* renaming again

* minor changes

* pep8

* changed the symbolicBInary class

* docstring cleanup

* bug docstring fixes

* bug fix in the evaluate method, pep8 the _binary_operator file

* merge with upstream and additional tests to SymbolicBinary class

* added weight-two segment code test, fixed bug with in the code appending by integer multiplication

* added half-up code

* bugs fixed in half-up code

* corrected weight_one_segment_code and the interleaved_code, former half-up. Added tests for the codes.

* get rid of heads

* reordering function for the fermionOperator class. takes 0,1,2,3,4,.. -> 0,2,4,..,1,3,...

* spin indexing within moleculardata

* started writing demo (work in progress), corrected typo in functions test , fixed possible bug for string parsing in symbolic binary file

* changed function file test such that data is obtained half-up, added last part for ipython demo

* corrected typos in the demo notebook

* fixed bugs in test, it now runs without error

* code transforms

* pep8

* transform demo

* fixes

* typos fixing in demo

* reverting back to original demo

* demo testing & indent

* docstring update

* not ready for review! started on docs

* descriptions for code functions

* final pass at docs, fixing spaces

* modes to n modes, and imports

* fixed a bug in demo, added description to weight-n codes
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

7 participants