Skip to content

Commit 361a5f7

Browse files
committed
Add implementation explanation in computer_gcd
1 parent 20db2c0 commit 361a5f7

1 file changed

Lines changed: 10 additions & 16 deletions

File tree

src/torchjd/sparse/_linalg.py

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,16 @@ def compute_gcd(S1: Tensor, S2: Tensor) -> tuple[Tensor, Tensor, Tensor]:
135135
S2 = G @ K2
136136
with G having minimal rank.
137137
138+
Implementation logic:
139+
The concatenated matrix [S1 | S2] spans exactly the sum of the lattices generated by S1 and S2.
140+
This is because S1 @ u1 + S2 @ u2 = [S1 | S2] @ [u1.T | u2.T].T
141+
The reduced HNF decomposition of [S1 | S2] yields G, U, V where the G.shape[1] is the rank of
142+
[S1 | S2] and [S1 | S2] = G @ V. This means that
143+
S1 = G @ V[:, :m1]
144+
S2 = G @ V[:, m1:]
145+
This is the target common factorization. It is the greatest as the lattice spanned by G is the
146+
same as that spanned by [S1 | S2].
147+
138148
Args:
139149
S1, S2: torch.Tensors (m x n1), (m x n2)
140150
@@ -149,22 +159,6 @@ def compute_gcd(S1: Tensor, S2: Tensor) -> tuple[Tensor, Tensor, Tensor]:
149159
A = torch.cat([S1, S2], dim=1)
150160
G, U, V = hnf_decomposition(A)
151161

152-
# H = [S1 | S2] @ U
153-
# [S1 | S2] = H @ V
154-
#
155-
# S1 = H @ V[:, :m1]
156-
# S2 = H @ V[:, m1:]
157-
#
158-
# K1 = V[:, :m1]
159-
# K2 = V[:, m1:]
160-
# G = H
161-
#
162-
# S1 = G @ K1
163-
# S2 = G @ K2
164-
#
165-
# SLT(p1, S1) = SLT(SLT(p1, K1), G)
166-
# SLT(p2, S2) = SLT(SLT(p2, K2), G)
167-
168162
K1 = V[:, :n1]
169163
K2 = V[:, n1:]
170164

0 commit comments

Comments
 (0)