Skip to content
This repository was archived by the owner on Jan 16, 2026. It is now read-only.

[unitaryHACK] Strawberry Fields: Gaussian Merge#591

Merged
nquesada merged 40 commits intoXanaduAI:masterfrom
federico0112:gaussian_merge
Jun 11, 2021
Merged

[unitaryHACK] Strawberry Fields: Gaussian Merge#591
nquesada merged 40 commits intoXanaduAI:masterfrom
federico0112:gaussian_merge

Conversation

@federico0112
Copy link
Copy Markdown
Contributor

@federico0112 federico0112 commented May 30, 2021

Adds hybrid Gaussian Merge compiler that merges gaussian operations into Gaussian Tranform operations in a program with non-Gaussian and Gaussian operations.

Before submitting

Please complete the following checklist when submitting a PR:

  • All new features must include a unit test.
    If you've fixed a bug or added code that should be tested, add a test to the
    test directory!

  • All new functions and code must be clearly commented and documented.
    If you do make documentation changes, make sure that the docs build and
    render correctly by running make docs.

  • Ensure that the test suite passes, by running make test.

  • Ensure that code is properly formatted, by running make format or black -l 100 strawberryfields. You will need to have the Black code format installed: pip install black.

  • Add a new entry to the .github/CHANGELOG.md file, summarizing the
    change, and including a link back to the PR.

  • The Strawberry Fields source code conforms to
    PEP8 standards.
    We check all of our code against Pylint.
    To lint modified files, simply pip install pylint, and then
    run pylint strawberryfields/path/to/file.py.

When all the above are checked, delete everything above the dashed
line and fill in the pull request template.


Context: #574

Description of the Change: Adds hybrid Gaussian Merge compiler that merges gaussian operations into Gaussian Tranform operations in a program with non-Gaussian and Gaussian operations.

Benefits: Can potantially reduce calculation overhead by reducing the number of gaussian operations in a circuit

Possible Drawbacks: Circuits with displacement and squeezing gates require precise cutoff values, determining the correct cutoff and displacement/squeezing parameters has to be done manually.

Related GitHub Issues: #574

@nquesada
Copy link
Copy Markdown
Collaborator

Hi @federico0112 : as a first suggestion, I'd like to ask you to start looking into the CodeFactor issues reported by the first bot.

@nquesada
Copy link
Copy Markdown
Collaborator

@federico0112 : it looks like you are almost there in terms of linting. You only need two three more docstrings and a whitespace issue.

@codecov
Copy link
Copy Markdown

codecov bot commented May 30, 2021

Codecov Report

Merging #591 (6c2f3a6) into master (07c6f95) will increase coverage by 0.02%.
The diff coverage is 100.00%.

@@            Coverage Diff             @@
##           master     #591      +/-   ##
==========================================
+ Coverage   98.42%   98.44%   +0.02%     
==========================================
  Files          75       76       +1     
  Lines        8608     8752     +144     
==========================================
+ Hits         8472     8616     +144     
  Misses        136      136              
Impacted Files Coverage Δ
strawberryfields/compilers/__init__.py 100.00% <100.00%> (ø)
strawberryfields/compilers/gaussian_merge.py 100.00% <100.00%> (ø)

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 07c6f95...6c2f3a6. Read the comment docs.

@nquesada
Copy link
Copy Markdown
Collaborator

@federico0112 : can you pass black -l 100 in these two files:

strawberryfields/compilers/__init__.py
strawberryfields/compilers/gaussian_merge.py

@nquesada
Copy link
Copy Markdown
Collaborator

@federico0112 : for what I can see you have not added new tests. A trivial tests this compiler should have is that it should pass all the tests the Gaussian compiler passes. Then you should create a new test file in tests/frontend/compilers that tests the new functionality.

@federico0112
Copy link
Copy Markdown
Contributor Author

Can this test be the one you gave me? Would that be enough or do I need more test cases

@nquesada
Copy link
Copy Markdown
Collaborator

nquesada commented May 30, 2021

That is a potential test, but more are needed. For those I suggest you for example try to compile the program showed in the issue [#574]. Keep in mind that you will want to use small parameters for all the gates that generate photons so that you don't need gigantic photon number cutoff. Moreover, you will want to modify tests for gaussian_unitary so that your now compiler also passes. For example this test you should be able to repurpose for your compiler by something like

@pytest.mark.parametrize("depth", [1, 3, 6])
@pytest.mark.parametrize("width", [5, 10, 15])
@pytest.mark.parametrize("compiler", ["gaussian_unitary", "gaussian_merge"])
def test_gaussian_program(depth, width, compiler):
    """Tests that a circuit and its compiled version produce the same Gaussian state"""
    eng = sf.LocalEngine(backend="gaussian")
    eng1 = sf.LocalEngine(backend="gaussian")
    circuit = sf.Program(width)
    with circuit.context as q:
        for _ in range(depth):
            U, s, V, alphas = random_params(width, 2.0 / depth, 1.0)
            ops.Interferometer(U) | q
            for i in range(width):
                ops.Sgate(s[i]) | q[i]
            ops.Interferometer(V) | q
            for i in range(width):
                ops.Dgate(np.abs(alphas[i]), np.angle(alphas[i])) | q[i]
    compiled_circuit = circuit.compile(compiler=compiler)
    cv = eng.run(circuit).state.cov()
    mean = eng.run(circuit).state.means()

    cv1 = eng1.run(compiled_circuit).state.cov()
    mean1 = eng1.run(compiled_circuit).state.means()
    assert np.allclose(cv, cv1)
    assert np.allclose(mean, mean1)

@federico0112
Copy link
Copy Markdown
Contributor Author

Ah I see, thats interesting I've never done test coverage in Python. Ill work on getting the test coverage up. Is this required for the bounty? I am going to be busy all tonight and I don't know if I'll be able to finish it by midnight tonight. It's okay if it is required, just curious.

@federico0112 federico0112 changed the title Strawberry Fields Unitary Hack: Gaussian Merge [Unitart Hack] Strawberry Fields: Gaussian Merge May 30, 2021
@federico0112 federico0112 changed the title [Unitart Hack] Strawberry Fields: Gaussian Merge [Unitary Hack] Strawberry Fields: Gaussian Merge May 30, 2021
@federico0112 federico0112 changed the title [Unitary Hack] Strawberry Fields: Gaussian Merge [unitaryHACK] Strawberry Fields: Gaussian Merge May 30, 2021
Copy link
Copy Markdown
Member

@josh146 josh146 left a comment

Choose a reason for hiding this comment

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

Thanks @federico0112 for this great contribution 💯

I've left a couple of preliminary comments, in particular, don't forget to run black on the new and modified files as @nquesada mentions!

black -l 100 strawberryfields/compilers/__init__.py
black -l 100 strawberryfields/compilers/gaussian_merge.py

Is this required for the bounty? I am going to be busy all tonight and I don't know if I'll be able to finish it by midnight tonight. It's okay if it is required, just curious.

The requirement for the bounty is that the PR passes code review and is merged in --- this requires passing our coverage checks as well :)

Comment thread strawberryfields/compilers/gaussian_merge.py Outdated
Comment thread strawberryfields/compilers/gaussian_merge.py Outdated
Comment thread strawberryfields/compilers/gaussian_merge.py Outdated
"BSgate",
"CKgate",
"S2gate",
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm curious if it makes sense to include GaussianTransformation as a primitive? That way, it will avoid the GaussianTransformation from being needlessly decomposed and 're-merged'.

It might also make sense to include all decompositions here, with the exception of the Graph ones.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Agreed not sure why I haven't added it

Comment thread strawberryfields/compilers/gaussian_merge.py Outdated
gaussian_transform, successors, displacement_mapping
)

# Add edges for all successor/predecessor operations of the merged operations
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Great commenting throughout this method @federico0112!

return True
return False

def recursive_d_gate_successors(self, gate):
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Out of curiosity, how come the Dgate is merged separately compared to the GaussianTransform?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The displacement gates never get actually merged into the gaussian transform, cause thats what Gaussian Unitary does. So I had to add logic to handle them. I put the after the gaussian transform and add edges to the successive operations that were not merged. Most of what made the code more complicated was trying to deal with displacement gates.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Got it, thanks @federico0112

Comment thread strawberryfields/compilers/gaussian_merge.py Outdated
@nquesada
Copy link
Copy Markdown
Collaborator

HI @federico0112 : Great progress so far. There are still a few lines of gaussian_merge that are not being covered by the tests: https://app.codecov.io/gh/XanaduAI/strawberryfields/compare/591/diff#diff-c3RyYXdiZXJyeWZpZWxkcy9jb21waWxlcnMvZ2F1c3NpYW5fbWVyZ2UucHk=

It seems like most of them are related to displacements.

@federico0112
Copy link
Copy Markdown
Contributor Author

I made a change to the unit test. It should increase the code coverage

@nquesada
Copy link
Copy Markdown
Collaborator

Hi @federico0112 : there still some part of the compiler not covered by the tests (https://app.codecov.io/gh/XanaduAI/strawberryfields/compare/591/diff#diff-c3RyYXdiZXJyeWZpZWxkcy9jb21waWxlcnMvZ2F1c3NpYW5fbWVyZ2UucHk=). You might need to design some specific tests to cover those edge cases.

@federico0112
Copy link
Copy Markdown
Contributor Author

I just realized that I left out a function that was not being used anymore (figured out a better way to achieve the same thing). Thats why it wasn't covered by the unit tests.

federico0112 and others added 7 commits June 10, 2021 11:26
Co-authored-by: Josh Izaac <josh146@gmail.com>
Co-authored-by: Josh Izaac <josh146@gmail.com>
Co-authored-by: Josh Izaac <josh146@gmail.com>
Co-authored-by: Josh Izaac <josh146@gmail.com>
Co-authored-by: Josh Izaac <josh146@gmail.com>
Co-authored-by: Josh Izaac <josh146@gmail.com>
Comment thread strawberryfields/compilers/gaussian_merge.py
Comment thread strawberryfields/compilers/gaussian_merge.py Outdated
Co-authored-by: antalszava <antalszava@gmail.com>
Comment thread strawberryfields/compilers/gaussian_merge.py Outdated
Comment on lines +155 to +166
- For each operation (op) check and obtain Gaussian operations that can be merged
(get_valid_gaussian_merge_ops).
- If the operation has successor gaussian operations that can be merged,
then merge them using gaussian_unitary.py.
- Determine displacement gates, from gaussian unitary merge, and map them to the qumodes acted upon
(add_displacement_gates).
- Attach predecessor operations of the main operation (op) to new Gaussian transform operations.
- Attach successor non Gaussian operations of op to a displacement gate, if present,
or a gaussian transform operation from the merged operations (add_non_gaussian_successor_gates).
- Attach all non-merged predecessor and successor of the merged operations to the new gaussian
transform and displacement gates (add_gaussian_pre_and_succ_gates).
- Remove nodes of operations that were merged in and convert DAG to sequence.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
- For each operation (op) check and obtain Gaussian operations that can be merged
(get_valid_gaussian_merge_ops).
- If the operation has successor gaussian operations that can be merged,
then merge them using gaussian_unitary.py.
- Determine displacement gates, from gaussian unitary merge, and map them to the qumodes acted upon
(add_displacement_gates).
- Attach predecessor operations of the main operation (op) to new Gaussian transform operations.
- Attach successor non Gaussian operations of op to a displacement gate, if present,
or a gaussian transform operation from the merged operations (add_non_gaussian_successor_gates).
- Attach all non-merged predecessor and successor of the merged operations to the new gaussian
transform and displacement gates (add_gaussian_pre_and_succ_gates).
- Remove nodes of operations that were merged in and convert DAG to sequence.
- For each operation (op) check and obtain Gaussian operations that can be merged (get_valid_gaussian_merge_ops).
- If the operation has successor gaussian operations that can be merged, then merge them using gaussian_unitary.py.
- Determine displacement gates, from gaussian unitary merge, and map them to the qumodes acted upon (add_displacement_gates).
- Attach predecessor operations of the main operation (op) to new Gaussian transform operations.
- Attach successor non Gaussian operations of op to a displacement gate, if present, or a gaussian transform operation from the merged operations (add_non_gaussian_successor_gates).
- Attach all non-merged predecessor and successor of the merged operations to the new gaussian
transform and displacement gates (add_gaussian_pre_and_succ_gates).
- Remove nodes of operations that were merged in and convert DAG to sequence.

Comment thread strawberryfields/compilers/gaussian_merge.py Outdated
Comment on lines +84 to +86
# measurements
"MeasureFock",
"MeasureHomodyne",
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think it is a bad idea to leave measurement here for the time being.

Comment thread strawberryfields/compilers/gaussian_merge.py Outdated
Comment thread strawberryfields/compilers/gaussian_merge.py Outdated
Comment thread .github/CHANGELOG.md
@nquesada
Copy link
Copy Markdown
Collaborator

This is a fantastic addition to Strawberry Fields, thanks for all the hard work @federico0112 .

@nquesada nquesada merged commit 6b7b5c5 into XanaduAI:master Jun 11, 2021
@nquesada
Copy link
Copy Markdown
Collaborator

Dear @crazy4pi314 --- The fantastic addition by @federico0112 is now merged into SF. It was a lot of fun being part of the unitaryhack this year. Looking forward to the next one!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants