1+ function check_lq_cotangents (
2+ L, Q, ΔL, ΔQ, minmn:: Int , p:: Int ;
3+ gauge_atol:: Real = default_pullback_gauge_atol (ΔQ)
4+ )
5+ if minmn > p # case where A is rank-deficient
6+ Δgauge = abs (zero (eltype (Q)))
7+ if ! iszerotangent (ΔQ)
8+ # in this case the number Householder reflections will
9+ # change upon small variations, and all of the remaining
10+ # columns of ΔQ should be zero for a gauge-invariant
11+ # cost function
12+ ΔQ2 = view (ΔQ, (p + 1 ): size (Q, 1 ), :)
13+ Δgauge = max (Δgauge, norm (ΔQ2))
14+ end
15+ if ! iszerotangent (ΔL)
16+ ΔL22 = view (ΔL, (p + 1 ): size (L, 1 ), (p + 1 ): minmn)
17+ Δgauge = max (Δgauge, norm (ΔL22))
18+ end
19+ Δgauge ≤ gauge_atol ||
20+ @warn " `lq` cotangents sensitive to gauge choice: (|Δgauge| = $Δgauge )"
21+ end
22+ return
23+ end
24+
25+ function check_lq_full_cotangents (Q1, ΔQ2, ΔQ2Q1ᴴ; gauge_atol:: Real = default_pullback_gauge_atol (Q1))
26+ # in the case where A is full rank, but there are more columns in Q than in A
27+ # (the case of `lq_full`), there is gauge-invariant information in the
28+ # projection of ΔQ2 onto the column space of Q1, by virtue of Q being a unitary
29+ # matrix. As the number of Householder reflections is in fixed in the full rank
30+ # case, Q is expected to rotate smoothly (we might even be able to predict) also
31+ # how the full Q2 will change, but this we omit for now, and we consider
32+ # Q2' * ΔQ2 as a gauge dependent quantity.
33+ Δgauge = norm (mul! (copy (ΔQ2), ΔQ2Q1ᴴ, Q1, - 1 , 1 ), Inf )
34+ Δgauge ≤ gauge_atol ||
35+ @warn " `lq` cotangents sensitive to gauge choice: (|Δgauge| = $Δgauge )"
36+ return
37+ end
38+
139"""
240 lq_pullback!(
341 ΔA, A, LQ, ΔLQ;
@@ -36,23 +74,7 @@ function lq_pullback!(
3674 ΔA1 = view (ΔA, 1 : p, :)
3775 ΔA2 = view (ΔA, (p + 1 ): m, :)
3876
39- if minmn > p # case where A is rank-deficient
40- Δgauge = abs (zero (eltype (Q)))
41- if ! iszerotangent (ΔQ)
42- # in this case the number Householder reflections will
43- # change upon small variations, and all of the remaining
44- # columns of ΔQ should be zero for a gauge-invariant
45- # cost function
46- ΔQ2 = view (ΔQ, (p + 1 ): size (Q, 1 ), :)
47- Δgauge = max (Δgauge, norm (ΔQ2, Inf ))
48- end
49- if ! iszerotangent (ΔL)
50- ΔL22 = view (ΔL, (p + 1 ): m, (p + 1 ): minmn)
51- Δgauge = max (Δgauge, norm (ΔL22, Inf ))
52- end
53- Δgauge ≤ gauge_atol ||
54- @warn " `lq` cotangents sensitive to gauge choice: (|Δgauge| = $Δgauge )"
55- end
77+ check_lq_cotangents (L, Q, ΔL, ΔQ, minmn, p; gauge_atol)
5678
5779 ΔQ̃ = zero! (similar (Q, (p, n)))
5880 if ! iszerotangent (ΔQ)
@@ -61,17 +83,8 @@ function lq_pullback!(
6183 if p < size (Q, 1 )
6284 Q2 = view (Q, (p + 1 ): size (Q, 1 ), :)
6385 ΔQ2 = view (ΔQ, (p + 1 ): size (Q, 1 ), :)
64- # in the case where A is full rank, but there are more columns in Q than in A
65- # (the case of `qr_full`), there is gauge-invariant information in the
66- # projection of ΔQ2 onto the column space of Q1, by virtue of Q being a unitary
67- # matrix. As the number of Householder reflections is in fixed in the full rank
68- # case, Q is expected to rotate smoothly (we might even be able to predict) also
69- # how the full Q2 will change, but this we omit for now, and we consider
70- # Q2' * ΔQ2 as a gauge dependent quantity.
7186 ΔQ2Q1ᴴ = ΔQ2 * Q1'
72- Δgauge = norm (mul! (copy (ΔQ2), ΔQ2Q1ᴴ, Q1, - 1 , 1 ), Inf )
73- Δgauge ≤ gauge_atol ||
74- @warn " `lq` cotangents sensitive to gauge choice: (|Δgauge| = $Δgauge )"
87+ check_lq_full_cotangents (Q1, ΔQ2, ΔQ2Q1ᴴ; gauge_atol)
7588 ΔQ̃ = mul! (ΔQ̃, ΔQ2Q1ᴴ' , Q2, - 1 , 1 )
7689 end
7790 end
@@ -102,6 +115,14 @@ function lq_pullback!(
102115 return ΔA
103116end
104117
118+ function check_lq_null_cotangents (Nᴴ, ΔNᴴ; gauge_atol:: Real = default_pullback_gauge_atol (ΔNᴴ))
119+ aNᴴΔN = project_antihermitian! (Nᴴ * ΔNᴴ' )
120+ Δgauge = norm (aNᴴΔN)
121+ Δgauge ≤ gauge_atol ||
122+ @warn " `lq_null` cotangent sensitive to gauge choice: (|Δgauge| = $Δgauge )"
123+ return
124+ end
125+
105126"""
106127 lq_null_pullback!(
107128 ΔA::AbstractMatrix, A, Nᴴ, ΔNᴴ;
@@ -118,10 +139,7 @@ function lq_null_pullback!(
118139 gauge_atol:: Real = default_pullback_gauge_atol (ΔNᴴ)
119140 )
120141 if ! iszerotangent (ΔNᴴ) && size (Nᴴ, 1 ) > 0
121- aNᴴΔN = project_antihermitian! (Nᴴ * ΔNᴴ' )
122- Δgauge = norm (aNᴴΔN)
123- Δgauge ≤ gauge_atol ||
124- @warn " `lq_null` cotangent sensitive to gauge choice: (|Δgauge| = $Δgauge )"
142+ check_lq_null_cotangents (Nᴴ, ΔNᴴ; gauge_atol)
125143 L, Q = lq_compact (A; positive = true ) # should we be able to provide algorithm here?
126144 X = ldiv! (LowerTriangular (L)' , Q * ΔNᴴ' )
127145 ΔA = mul! (ΔA, X, Nᴴ, - 1 , 1 )
0 commit comments