You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/src/user_interface/decompositions.md
+187-5Lines changed: 187 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -169,23 +169,205 @@ PolarNewton
169
169
170
170
## Orthogonal Subspaces
171
171
172
-
Often it is useful to compute orthogonal bases for a particular subspace defined by a matrix.
173
-
Given a matrix `A` we can compute an orthonormal basis for its image or coimage, and factorize the matrix accordingly.
172
+
Often it is useful to compute orthogonal bases for particular subspaces defined by a matrix.
173
+
Given a matrix `A`, we can compute an orthonormal basis for its image or coimage, and factorize the matrix accordingly.
174
174
These bases are accessible through [`left_orth`](@ref) and [`right_orth`](@ref) respectively.
175
-
This is implemented through a combination of the decompositions mentioned above, and serves as a convenient interface to these operations.
175
+
176
+
### Overview
177
+
178
+
The [`left_orth`](@ref) function computes an orthonormal basis `V` for the image (column space) of `A`, along with a corestriction matrix `C` such that `A = V * C`.
179
+
The resulting `V` has orthonormal columns (`V' * V ≈ I` or `isisometric(V)`).
180
+
181
+
Similarly, [`right_orth`](@ref) computes an orthonormal basis for the coimage (row space) of `A`, i.e., the image of `A'`.
182
+
It returns matrices `C` and `Vᴴ` such that `A = C * Vᴴ`, where `V = (Vᴴ)'` has orthonormal columns (`isisometric(Vᴴ; side = :right)`).
183
+
184
+
These functions serve as high-level interfaces that automatically select the most appropriate decomposition based on the specified options, making them convenient for users who want orthonormalization without worrying about the underlying implementation details.
176
185
177
186
```@docs; canonical=false
178
187
left_orth
179
188
right_orth
180
189
```
181
190
191
+
### Algorithm Selection
192
+
193
+
Both functions support multiple decomposition drivers, which can be selected through the `alg` keyword argument:
194
+
195
+
**For `left_orth`:**
196
+
-`alg = :qr` (default without truncation): Uses QR decomposition via [`qr_compact`](@ref)
197
+
-`alg = :polar`: Uses polar decomposition via [`left_polar`](@ref)
198
+
-`alg = :svd` (default with truncation): Uses SVD via [`svd_compact`](@ref) or [`svd_trunc`](@ref)
199
+
200
+
**For `right_orth`:**
201
+
-`alg = :lq` (default without truncation): Uses LQ decomposition via [`lq_compact`](@ref)
202
+
-`alg = :polar`: Uses polar decomposition via [`right_polar`](@ref)
203
+
-`alg = :svd` (default with truncation): Uses SVD via [`svd_compact`](@ref) or [`svd_trunc`](@ref)
204
+
205
+
When `alg` is not specified, the function automatically selects `:qr`/`:lq` for exact orthogonalization, or `:svd` when a truncation strategy is provided.
206
+
207
+
### Extending with Custom Algorithms
208
+
209
+
To register a custom algorithm type for use with these functions, you need to define the appropriate conversion function, for example:
The type parameter (`:qr`, `:lq`, `:polar`, or `:svd`) indicates which factorization backend will be used.
220
+
The wrapper algorithm types handle the dispatch to the appropriate implementation:
221
+
222
+
```@docs; canonical=false
223
+
left_orth_alg
224
+
right_orth_alg
225
+
LeftOrthAlgorithm
226
+
RightOrthAlgorithm
227
+
```
228
+
229
+
### Examples
230
+
231
+
Basic orthogonalization:
232
+
233
+
```jldoctest orthnull; output=false
234
+
using MatrixAlgebraKit
235
+
using LinearAlgebra
236
+
237
+
A = [1.0 2.0; 3.0 4.0; 5.0 6.0]
238
+
V, C = left_orth(A)
239
+
(V' * V) ≈ I && A ≈ V * C
240
+
241
+
# output
242
+
true
243
+
```
244
+
245
+
Using different algorithms:
246
+
247
+
```jldoctest orthnull; output=false
248
+
A = randn(4, 3)
249
+
V1, C1 = left_orth(A; alg = :qr)
250
+
V2, C2 = left_orth(A; alg = :polar)
251
+
V3, C3 = left_orth(A; alg = :svd)
252
+
A ≈ V1 * C1 ≈ V2 * C2 ≈ V3 * C3
253
+
254
+
# output
255
+
true
256
+
```
257
+
258
+
With truncation:
259
+
260
+
```jldoctest orthnull; output=false
261
+
A = [1.0 0.0; 0.0 1e-10; 0.0 0.0]
262
+
V, C = left_orth(A; trunc = (atol = 1e-8,))
263
+
size(V, 2) == 1 # Only one column retained
264
+
265
+
# output
266
+
true
267
+
```
268
+
269
+
182
270
## Null Spaces
183
271
184
272
Similarly, it can be convenient to obtain an orthogonal basis for the kernel or cokernel of a matrix.
185
-
These are the compliments of the coimage and image, respectively, and can be computed using the [`left_null`](@ref) and [`right_null`](@ref) functions.
186
-
Again, this is typically implemented through a combination of the decompositions mentioned above, and serves as a convenient interface to these operations.
273
+
These are the orthogonal complements of the coimage and image, respectively, and can be computed using the [`left_null`](@ref) and [`right_null`](@ref) functions.
274
+
275
+
### Overview
276
+
277
+
The [`left_null`](@ref) function computes an orthonormal basis `N` for the cokernel (left nullspace) of `A`, which is the nullspace of `A'`.
278
+
This means `A' * N ≈ 0` and `N' * N ≈ I`.
279
+
280
+
Similarly, [`right_null`](@ref) computes an orthonormal basis for the kernel (right nullspace) of `A`.
281
+
It returns `Nᴴ` such that `A * Nᴴ' ≈ 0` and `Nᴴ * Nᴴ' ≈ I`, where `N = (Nᴴ)'` has orthonormal columns.
282
+
283
+
These functions automatically handle rank determination and provide convenient access to nullspace computation without requiring detailed knowledge of the underlying decomposition methods.
187
284
188
285
```@docs; canonical=false
189
286
left_null
190
287
right_null
191
288
```
289
+
290
+
### Algorithm Selection
291
+
292
+
Both functions support multiple decomposition drivers, which can be selected through the `alg` keyword argument:
293
+
294
+
**For `left_null`:**
295
+
-`alg = :qr` (default without truncation): Uses QR-based nullspace computation via [`qr_null`](@ref)
296
+
-`alg = :svd` (default with truncation): Uses SVD via [`svd_full`](@ref) with appropriate truncation
297
+
298
+
**For `right_null`:**
299
+
-`alg = :lq` (default without truncation): Uses LQ-based nullspace computation via [`lq_null`](@ref)
300
+
-`alg = :svd` (default with truncation): Uses SVD via [`svd_full`](@ref) with appropriate truncation
301
+
302
+
When `alg` is not specified, the function automatically selects `:qr`/`:lq` for exact nullspace computation, or `:svd` when a truncation strategy is provided to handle numerical rank determination.
303
+
304
+
!!! note
305
+
For nullspace functions, [`notrunc`](@ref) has special meaning when used with the default QR/LQ algorithms.
306
+
It indicates that the nullspace should be computed from the exact zeros determined by the additional rows/columns of the extended matrix, without any tolerance-based truncation.
307
+
308
+
### Extending with Custom Algorithms
309
+
310
+
To register a custom algorithm type for use with these functions, you need to define the appropriate conversion function:
@@ -161,7 +161,9 @@ function MatrixAlgebraKit._avgdiff!(A::StridedROCMatrix, B::StridedROCMatrix)
161
161
return A, B
162
162
end
163
163
164
-
function MatrixAlgebraKit.truncate(::typeof(MatrixAlgebraKit.left_null!), US::Tuple{TU, TS}, strategy::MatrixAlgebraKit.TruncationStrategy) where {TU <:ROCArray, TS}
0 commit comments