Skip to content

Commit c8aec3f

Browse files
Add symmetric QR factorization method
- Implement SymmetricQRFactorizationProblem for symmetric matrices - Create kernel method for symmetric QR decomposition - Add test case for symmetric QR factorization - Remove unnecessary Printf and Unicode dependencies
1 parent 82a4438 commit c8aec3f

File tree

3 files changed

+69
-10
lines changed

3 files changed

+69
-10
lines changed

examples/Manifest.toml

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,21 +27,12 @@ deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"]
2727
uuid = "4536629a-c528-5b80-bd46-f80d51c5b363"
2828
version = "0.3.27+1"
2929

30-
[[deps.Printf]]
31-
deps = ["Unicode"]
32-
uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7"
33-
version = "1.11.0"
34-
3530
[[deps.SimpleLinearAlgebra]]
36-
deps = ["LinearAlgebra", "Printf"]
31+
deps = ["LinearAlgebra"]
3732
path = "/Users/yangjunjie/.julia/dev/SimpleLinearAlgebra"
3833
uuid = "555e9691-8231-4cde-a0d7-6dc20204a59a"
3934
version = "1.0.0-DEV"
4035

41-
[[deps.Unicode]]
42-
uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"
43-
version = "1.11.0"
44-
4536
[[deps.libblastrampoline_jll]]
4637
deps = ["Artifacts", "Libdl"]
4738
uuid = "8e850b90-86db-534c-a0d3-1478176c7d93"

src/qr.jl

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,3 +167,53 @@ end
167167

168168
kernel(prob::QRFactorizationProblem) = QR.kernel(prob)
169169
export QR
170+
171+
struct SymmetricQRFactorizationProblem <: ProblemMixin
172+
a::AbstractMatrix
173+
tol::Real
174+
function SymmetricQRFactorizationProblem(a, tol=1e-10)
175+
prob = new(a, tol)
176+
return prob
177+
end
178+
end
179+
180+
struct SymmetricQRFactorizationSolution <: SolutionMixin
181+
q::AbstractMatrix
182+
r::AbstractMatrix
183+
function SymmetricQRFactorizationSolution(q, r)
184+
r = triu(r, -2)
185+
r = tril(r, 2)
186+
@assert isapprox(q' * q, I) "matrix must be orthogonal"
187+
soln = new(q, r)
188+
return soln
189+
end
190+
end
191+
192+
function kernel(prob::SymmetricQRFactorizationProblem)
193+
tol = prob.tol
194+
n = size(prob.a, 1)
195+
q = Matrix{Float64}(I, n, n)
196+
r = copy(prob.a)
197+
198+
for i in 1:n-1
199+
# Get the column vector below and including the diagonal
200+
vi = copy(r[(i+1):n, i])
201+
vi[1] += sign(vi[1]) * norm(vi)
202+
beta = 2.0 / dot(vi, vi)
203+
hi = I - beta * vi * vi' # shape (n-i-1, n-i-1)
204+
205+
r[(i+1):n, i:n] = hi * r[(i+1):n, i:n]
206+
r[i:n, (i+1):n] = r[i:n, (i+1):n] * hi'
207+
q[:, (i+1):n] = q[:, (i+1):n] * hi'
208+
end
209+
210+
@assert isapprox(q' * q, I, atol=tol) "q is not orthogonal"
211+
@assert isapprox(q * r * q', prob.a, atol=tol) "q * r * q' is not equal to a"
212+
213+
soln = SymmetricQRFactorizationSolution(q, r)
214+
return soln
215+
end
216+
217+
SymmetricQRFactorization = SymmetricQRFactorizationProblem
218+
SymmetricQRDecomposition = SymmetricQRFactorizationProblem
219+
export SymmetricQRFactorization, SymmetricQRDecomposition

test/qr.jl

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,21 @@ end
6464
@test isapprox(q' * q, I, atol=tol)
6565
@test isapprox(a, q * r, atol=tol)
6666
end
67+
68+
@testset "Symmetric QR factorization" begin
69+
n = 4
70+
a = rand(n, n)
71+
a = a * a'
72+
73+
prob = SymmetricQRFactorization(a, 1e-6)
74+
tol = prob.tol
75+
76+
soln = kernel(prob)
77+
q = soln.q
78+
r = soln.r
79+
80+
@test isapprox(r, triu(r, -2), atol=tol)
81+
@test isapprox(r, tril(r, 2), atol=tol)
82+
@test isapprox(q' * q, I, atol=tol)
83+
@test isapprox(a, q * r * q', atol=tol)
84+
end

0 commit comments

Comments
 (0)