Skip to content

Givens orthogonal layer#57

Open
VolodyaCO wants to merge 1 commit into
dwavesystems:mainfrom
VolodyaCO:givens-rotation
Open

Givens orthogonal layer#57
VolodyaCO wants to merge 1 commit into
dwavesystems:mainfrom
VolodyaCO:givens-rotation

Conversation

@VolodyaCO

Copy link
Copy Markdown
Collaborator

This PR adds an orthogonal layer given by Givens rotations, using the parallel algorithm described by Firas in https://arxiv.org/abs/2106.00003, which gives a forward complexity of O(n) and backward complexity of O(n log(n)), even though there are O(n^2) rotations.

This PR still is in draft. I wrote it for even n. Probably some more unit tests are to be done, but I am quite lazy (will do it after all math is checked for odd n).

@VolodyaCO VolodyaCO requested a review from kevinchern December 19, 2025 00:01
@VolodyaCO VolodyaCO self-assigned this Dec 19, 2025
@VolodyaCO VolodyaCO added the enhancement New feature or request label Dec 19, 2025
@VolodyaCO

Copy link
Copy Markdown
Collaborator Author

I somehow broke @kevinchern's tests, what the hell...

Comment thread tests/helper_models.py Outdated
Comment thread tests/test_nn.py
@kevinchern

kevinchern commented Dec 19, 2025

Copy link
Copy Markdown
Collaborator

I somehow broke @kevinchern's tests, what the hell...

@VolodyaCO which tests? I'm seeing test_forward_agreement and test_backward_agreement failures on this CI test

@VolodyaCO

Copy link
Copy Markdown
Collaborator Author

I somehow broke @kevinchern's tests, what the hell...

@VolodyaCO which tests? I'm seeing test_forward_agreement and test_backward_agreement failures on this CI test

I forgot to update my tests to float64 precision. Now that I've done it, it's weird that all of the current failing tests are failing on

  File "/Users/distiller/project/tests/test_nn.py", line 144, in test_LinearBlock
    self.assertTrue(model_probably_good(model, (din,), (dout,)))

@kevinchern

Copy link
Copy Markdown
Collaborator

I somehow broke @kevinchern's tests, what the hell...

@VolodyaCO which tests? I'm seeing test_forward_agreement and test_backward_agreement failures on this CI test

I forgot to update my tests to float64 precision. Now that I've done it, it's weird that all of the current failing tests are failing on

  File "/Users/distiller/project/tests/test_nn.py", line 144, in test_LinearBlock
    self.assertTrue(model_probably_good(model, (din,), (dout,)))

Ahhhhhh. OK Theo also flagged this at #50 . It's a poorly-written test.. you can ignore it.

@VolodyaCO VolodyaCO marked this pull request as ready for review December 26, 2025 17:28
Comment thread dwave/plugins/torch/nn/modules/orthogonal.py Outdated
Comment thread dwave/plugins/torch/nn/modules/orthogonal.py Outdated
Comment thread dwave/plugins/torch/nn/modules/orthogonal.py
Comment on lines +122 to +127
angles, blocks, Ufwd_saved = ctx.saved_tensors
Ufwd = Ufwd_saved.clone()
M = grad_output.t() # dL/dU, i.e., grad_output is of shape (n, n)
n = M.size(1)
block_size = n // 2
A = torch.zeros((block_size, n), device=angles.device, dtype=angles.dtype)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Same here re lowercase for Ufwd, M, and A. Avoids incorrect colour highlighting in themes.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Hmmm, I didn't read this about the incorrect colour highlighting before I made my previous comment. I still think that it is easier to read the algorithm alongside the code if the use of lower/upper case match. For example, lower case m is usually used for an integer variable, not a tensor.

Comment thread dwave/plugins/torch/nn/modules/orthogonal.py Outdated
Comment thread dwave/plugins/torch/nn/modules/orthogonal.py Outdated
Comment thread tests/helper_models.py Outdated
Comment thread tests/test_nn.py Outdated
@VolodyaCO

Copy link
Copy Markdown
Collaborator Author

After a bit of git wrangling, I was able to clean my whole mess of merge commits 😆.

@anahitamansouri anahitamansouri left a comment

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.

This is a nice PR Vlad. It took me a while to go over the paper and this PR :) The only thing is the tests that are failing. Thanks for the great work.

Comment thread dwave/plugins/torch/nn/modules/orthogonal.py Outdated

@kevinchern kevinchern left a comment

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.

Did a quick pass to provide some feedback before taking some time to take a deep dive into the paper.

Comment thread dwave/plugins/torch/nn/modules/orthogonal.py Outdated
Comment thread dwave/plugins/torch/nn/modules/orthogonal.py Outdated
Comment thread dwave/plugins/torch/nn/modules/orthogonal.py Outdated
Comment thread dwave/plugins/torch/nn/modules/orthogonal.py Outdated
for _ in range(n - 1):
pairs = circle_method(sequence)
if is_odd:
# Remove pairs involving the dummy dimension:

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
# Remove pairs involving the dummy dimension:
# Remove pairs involving the dummy dimension

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I was gonna ask why remove the colon?

Comment thread dwave/plugins/torch/nn/modules/orthogonal.py Outdated
Comment thread dwave/plugins/torch/nn/modules/orthogonal.py Outdated
Comment thread dwave/plugins/torch/nn/modules/orthogonal.py Outdated
Comment thread dwave/plugins/torch/nn/modules/orthogonal.py Outdated
Comment thread dwave/plugins/torch/nn/modules/orthogonal.py Outdated
@VolodyaCO VolodyaCO force-pushed the givens-rotation branch 3 times, most recently from 1146ebb to df400fb Compare January 14, 2026 14:41
@kevinchern

Copy link
Copy Markdown
Collaborator

@VolodyaCO can you rebase on main?

Comment thread dwave/plugins/torch/nn/modules/orthogonal.py
Comment thread tests/helper_models.py Outdated
Comment thread tests/test_nn.py
@VolodyaCO VolodyaCO force-pushed the givens-rotation branch 3 times, most recently from 6587b89 to 97c2b8e Compare April 27, 2026 21:33
@kevinchern kevinchern closed this Apr 27, 2026
@kevinchern kevinchern reopened this Apr 27, 2026

@VolodyaCO VolodyaCO left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

@kevinchern I have addressed all comments. Should be ready to merge now.

Comment thread tests/test_nn.py
Comment thread dwave/plugins/torch/nn/modules/orthogonal.py
Comment thread dwave/plugins/torch/nn/modules/orthogonal.py Outdated
__all__ = ["GivensRotation"]


class _RoundRobinGivens(torch.autograd.Function):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The documentation is quite thorough for a hidden class. Would this perhaps make sense moving to a nn.functions namespace and removing the underscore? @kevinchern

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

@kevinchern bumping this

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 don't think it will be used beyond this class, so it's probably safe to keep her. If there's demand for it as a public function, we can move it out.

Comment thread dwave/plugins/torch/nn/modules/orthogonal.py Outdated
Comment on lines +98 to +101
# Initialize U^fwd from forward pass output U. Mathematically, U^fwd represents U^{1:k-1}
# at block k, defined in equation (11). It is post-multiplied by G_bk^T at each block
# iteration to "remove the effect of the block's rotations" (Section 4.1, paragraph before
# equation (12)). This corresponds to the update from U^{1:k} back to U^{1:k-1}.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I haven't looked at the reference link, but these comments seem a bit messy (for lack of a better term). If the algorithm in the link describes the process in a clear way, I'd perhaps shorten these comments a bit, although references to equations are always good.

Also, separation by empty lines always makes things look a bit tidier.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I have added separation by empty lines to make things look tidier. I added these inline comments at @kevinchern 's request. I do agree that it is enough for the interested reader to read the paper. I also think it's helpful to have the inline comments too.

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.

shorten these comments a bit

I second this opinion

kevin's request

To clarify my suggestion: it will be very helpful for future maintenance to include references to "where" these equations appear. The idea is for the developer to be able to easily reference the material and not necessarily understand the method from comments.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I see your point. Comments have now been shortened.

@kevinchern kevinchern left a comment

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.

Unit tests hinge on NaiveGivensRotationLayer being correct but there aren't correctness tests for it. It checks for serial versus parallel implementations.
We need a unit test to check the forward and backward methods are correct, e.g., work out the expected forward/backward values a small input (n=3?)

Comment thread tests/test_nn.py Outdated
Comment thread tests/test_nn.py
Comment thread tests/test_nn.py
Comment thread tests/test_nn.py Outdated
Comment thread tests/test_nn.py Outdated
Comment thread tests/test_nn.py Outdated
Comment thread dwave/plugins/torch/nn/modules/orthogonal.py
Comment on lines +98 to +101
# Initialize U^fwd from forward pass output U. Mathematically, U^fwd represents U^{1:k-1}
# at block k, defined in equation (11). It is post-multiplied by G_bk^T at each block
# iteration to "remove the effect of the block's rotations" (Section 4.1, paragraph before
# equation (12)). This corresponds to the update from U^{1:k} back to U^{1:k-1}.

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.

shorten these comments a bit

I second this opinion

kevin's request

To clarify my suggestion: it will be very helpful for future maintenance to include references to "where" these equations appear. The idea is for the developer to be able to easily reference the material and not necessarily understand the method from comments.

Comment thread dwave/plugins/torch/nn/modules/orthogonal.py Outdated
Comment thread dwave/plugins/torch/nn/modules/orthogonal.py Outdated
Address orthogonal module PR feedback.

@kevinchern kevinchern left a comment

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.

LGTM; comments have been addressed.

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

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants