1
+ using LinearAlgebra: LinearAlgebra
1
2
using MatrixAlgebraKit:
2
3
eig_full!,
3
4
eig_trunc!,
@@ -6,16 +7,19 @@ using MatrixAlgebraKit:
6
7
eigh_trunc!,
7
8
eigh_vals!,
8
9
left_null!,
10
+ left_orth!,
11
+ left_polar!,
9
12
lq_full!,
10
13
lq_compact!,
11
14
qr_full!,
12
15
qr_compact!,
13
16
right_null!,
17
+ right_orth!,
18
+ right_polar!,
14
19
svd_full!,
15
20
svd_compact!,
16
21
svd_trunc!,
17
22
svd_vals!
18
- using LinearAlgebra: LinearAlgebra
19
23
20
24
"""
21
25
qr(A::AbstractArray, labels_A, labels_codomain, labels_domain; kwargs...) -> Q, R
@@ -76,7 +80,7 @@ function lq(A::AbstractArray, biperm::BlockedPermutation{2}; full::Bool=false, k
76
80
A_mat = fusedims (A, biperm)
77
81
78
82
# factorization
79
- L, Q = full ? lq_full! (A_mat; kwargs ... ) : lq_compact! (A_mat; kwargs... )
83
+ L, Q = ( full ? lq_full! : lq_compact!) (A_mat; kwargs... )
80
84
81
85
# matrix to tensor
82
86
axes_codomain, axes_domain = blockpermute (axes (A), biperm)
@@ -120,11 +124,12 @@ function eigen(
120
124
ishermitian = @something ishermitian LinearAlgebra. ishermitian (A_mat)
121
125
122
126
# factorization
123
- if ! isnothing (trunc)
124
- D, V = ( ishermitian ? eigh_trunc! : eig_trunc!)(A_mat; trunc, kwargs ... )
127
+ f! = if ! isnothing (trunc)
128
+ ishermitian ? eigh_trunc! : eig_trunc!
125
129
else
126
- D, V = ( ishermitian ? eigh_full! : eig_full!)(A_mat; kwargs ... )
130
+ ishermitian ? eigh_full! : eig_full!
127
131
end
132
+ D, V = f! (A_mat; kwargs... )
128
133
129
134
# matrix to tensor
130
135
axes_codomain, = blockpermute (axes (A), biperm)
@@ -284,3 +289,163 @@ function right_null(A::AbstractArray, biperm::BlockedPermutation{2}; kwargs...)
284
289
axes_Nᴴ = (axes (Nᴴ, 1 ), axes_domain... )
285
290
return splitdims (Nᴴ, axes_Nᴴ)
286
291
end
292
+
293
+ """
294
+ left_polar(A::AbstractArray, labels_A, labels_codomain, labels_domain; kwargs...) -> W, P
295
+ left_polar(A::AbstractArray, biperm::BlockedPermutation{2}; kwargs...) -> W, P
296
+
297
+ Compute the left polar decomposition of a generic N-dimensional array, by interpreting it as
298
+ a linear map from the domain to the codomain indices. These can be specified either via
299
+ their labels, or directly through a `biperm`.
300
+
301
+ ## Keyword arguments
302
+
303
+ - Keyword arguments are passed on directly to MatrixAlgebraKit.
304
+
305
+ See also `MatrixAlgebraKit.left_polar!`.
306
+ """
307
+ function left_polar (A:: AbstractArray , labels_A, labels_codomain, labels_domain; kwargs... )
308
+ biperm = blockedperm_indexin (Tuple .((labels_A, labels_codomain, labels_domain))... )
309
+ return left_polar (A, biperm; kwargs... )
310
+ end
311
+ function left_polar (A:: AbstractArray , biperm:: BlockedPermutation{2} ; kwargs... )
312
+ # tensor to matrix
313
+ A_mat = fusedims (A, biperm)
314
+
315
+ # factorization
316
+ W, P = left_polar! (A_mat; kwargs... )
317
+
318
+ # matrix to tensor
319
+ axes_codomain, axes_domain = blockpermute (axes (A), biperm)
320
+ axes_W = (axes_codomain... , axes (W, 2 ))
321
+ axes_P = (axes (P, 1 ), axes_domain... )
322
+ return splitdims (W, axes_W), splitdims (P, axes_P)
323
+ end
324
+
325
+ """
326
+ right_polar(A::AbstractArray, labels_A, labels_codomain, labels_domain; kwargs...) -> P, W
327
+ right_polar(A::AbstractArray, biperm::BlockedPermutation{2}; kwargs...) -> P, W
328
+
329
+ Compute the right polar decomposition of a generic N-dimensional array, by interpreting it as
330
+ a linear map from the domain to the codomain indices. These can be specified either via
331
+ their labels, or directly through a `biperm`.
332
+
333
+ ## Keyword arguments
334
+
335
+ - Keyword arguments are passed on directly to MatrixAlgebraKit.
336
+
337
+ See also `MatrixAlgebraKit.right_polar!`.
338
+ """
339
+ function right_polar (A:: AbstractArray , labels_A, labels_codomain, labels_domain; kwargs... )
340
+ biperm = blockedperm_indexin (Tuple .((labels_A, labels_codomain, labels_domain))... )
341
+ return right_polar (A, biperm; kwargs... )
342
+ end
343
+ function right_polar (A:: AbstractArray , biperm:: BlockedPermutation{2} ; kwargs... )
344
+ # tensor to matrix
345
+ A_mat = fusedims (A, biperm)
346
+
347
+ # factorization
348
+ P, W = right_polar! (A_mat; kwargs... )
349
+
350
+ # matrix to tensor
351
+ axes_codomain, axes_domain = blockpermute (axes (A), biperm)
352
+ axes_P = (axes_codomain... , axes (P, ndims (P)))
353
+ axes_W = (axes (W, 1 ), axes_domain... )
354
+ return splitdims (P, axes_P), splitdims (W, axes_W)
355
+ end
356
+
357
+ """
358
+ left_orth(A::AbstractArray, labels_A, labels_codomain, labels_domain; kwargs...) -> V, C
359
+ left_orth(A::AbstractArray, biperm::BlockedPermutation{2}; kwargs...) -> V, C
360
+
361
+ Compute the left orthogonal decomposition of a generic N-dimensional array, by interpreting it as
362
+ a linear map from the domain to the codomain indices. These can be specified either via
363
+ their labels, or directly through a `biperm`.
364
+
365
+ ## Keyword arguments
366
+
367
+ - Keyword arguments are passed on directly to MatrixAlgebraKit.
368
+
369
+ See also `MatrixAlgebraKit.left_orth!`.
370
+ """
371
+ function left_orth (A:: AbstractArray , labels_A, labels_codomain, labels_domain; kwargs... )
372
+ biperm = blockedperm_indexin (Tuple .((labels_A, labels_codomain, labels_domain))... )
373
+ return left_orth (A, biperm; kwargs... )
374
+ end
375
+ function left_orth (A:: AbstractArray , biperm:: BlockedPermutation{2} ; kwargs... )
376
+ # tensor to matrix
377
+ A_mat = fusedims (A, biperm)
378
+
379
+ # factorization
380
+ V, C = left_orth! (A_mat; kwargs... )
381
+
382
+ # matrix to tensor
383
+ axes_codomain, axes_domain = blockpermute (axes (A), biperm)
384
+ axes_V = (axes_codomain... , axes (V, 2 ))
385
+ axes_C = (axes (C, 1 ), axes_domain... )
386
+ return splitdims (V, axes_V), splitdims (C, axes_C)
387
+ end
388
+
389
+ """
390
+ right_orth(A::AbstractArray, labels_A, labels_codomain, labels_domain; kwargs...) -> C, V
391
+ right_orth(A::AbstractArray, biperm::BlockedPermutation{2}; kwargs...) -> C, V
392
+
393
+ Compute the right orthogonal decomposition of a generic N-dimensional array, by interpreting it as
394
+ a linear map from the domain to the codomain indices. These can be specified either via
395
+ their labels, or directly through a `biperm`.
396
+
397
+ ## Keyword arguments
398
+
399
+ - Keyword arguments are passed on directly to MatrixAlgebraKit.
400
+
401
+ See also `MatrixAlgebraKit.right_orth!`.
402
+ """
403
+ function right_orth (A:: AbstractArray , labels_A, labels_codomain, labels_domain; kwargs... )
404
+ biperm = blockedperm_indexin (Tuple .((labels_A, labels_codomain, labels_domain))... )
405
+ return right_orth (A, biperm; kwargs... )
406
+ end
407
+ function right_orth (A:: AbstractArray , biperm:: BlockedPermutation{2} ; kwargs... )
408
+ # tensor to matrix
409
+ A_mat = fusedims (A, biperm)
410
+
411
+ # factorization
412
+ P, W = right_orth! (A_mat; kwargs... )
413
+
414
+ # matrix to tensor
415
+ axes_codomain, axes_domain = blockpermute (axes (A), biperm)
416
+ axes_P = (axes_codomain... , axes (P, ndims (P)))
417
+ axes_W = (axes (W, 1 ), axes_domain... )
418
+ return splitdims (P, axes_P), splitdims (W, axes_W)
419
+ end
420
+
421
+ """
422
+ factorize(A::AbstractArray, labels_A, labels_codomain, labels_domain; kwargs...) -> X, Y
423
+ factorize(A::AbstractArray, biperm::BlockedPermutation{2}; kwargs...) -> X, Y
424
+
425
+ Compute the decomposition of a generic N-dimensional array, by interpreting it as
426
+ a linear map from the domain to the codomain indices. These can be specified either via
427
+ their labels, or directly through a `biperm`.
428
+
429
+ ## Keyword arguments
430
+
431
+ - `orth::Symbol=:left`: specify the orthogonality of the decomposition.
432
+ Currently only `:left` and `:right` are supported.
433
+ - Other keywords are passed on directly to MatrixAlgebraKit.
434
+ """
435
+ function factorize (A:: AbstractArray , labels_A, labels_codomain, labels_domain; kwargs... )
436
+ biperm = blockedperm_indexin (Tuple .((labels_A, labels_codomain, labels_domain))... )
437
+ return factorize (A, biperm; kwargs... )
438
+ end
439
+ function factorize (A:: AbstractArray , biperm:: BlockedPermutation{2} ; orth= :left , kwargs... )
440
+ # tensor to matrix
441
+ A_mat = fusedims (A, biperm)
442
+
443
+ # factorization
444
+ X, Y = (orth == :left ? left_orth! : right_orth!)(A_mat; kwargs... )
445
+
446
+ # matrix to tensor
447
+ axes_codomain, axes_domain = blockpermute (axes (A), biperm)
448
+ axes_X = (axes_codomain... , axes (X, ndims (X)))
449
+ axes_Y = (axes (Y, 1 ), axes_domain... )
450
+ return splitdims (X, axes_X), splitdims (Y, axes_Y)
451
+ end
0 commit comments