Skip to content

Commit 097ee39

Browse files
authored
Allow two int-tuple inputs to represent biperm in factorizations and matrix functions (#97)
1 parent 10f6e1a commit 097ee39

File tree

6 files changed

+126
-43
lines changed

6 files changed

+126
-43
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "TensorAlgebra"
22
uuid = "68bd88dc-f39d-4e12-b2ca-f046b68fcc6a"
33
authors = ["ITensor developers <[email protected]> and contributors"]
4-
version = "0.5.0"
4+
version = "0.5.1"
55

66
[deps]
77
ArrayLayouts = "4c555306-a7a7-4459-81d9-ec55ddd5c99a"

src/factorizations.jl

Lines changed: 97 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,33 +5,42 @@ for f in (
55
:qr, :lq, :left_polar, :right_polar, :polar, :left_orth, :right_orth, :orth, :factorize,
66
)
77
@eval begin
8-
function $f(A::AbstractArray, labels_A, labels_codomain, labels_domain; kwargs...)
9-
biperm = blockedperm_indexin(Tuple.((labels_A, labels_codomain, labels_domain))...)
10-
return $f(A, biperm; kwargs...)
11-
end
12-
function $f(A::AbstractArray, biperm::AbstractBlockPermutation{2}; kwargs...)
8+
function $f(
9+
A::AbstractArray,
10+
codomain_perm::Tuple{Vararg{Int}}, domain_perm::Tuple{Vararg{Int}};
11+
kwargs...,
12+
)
1313
# tensor to matrix
14-
A_mat = matricize(A, biperm)
14+
A_mat = matricize(A, codomain_perm, domain_perm)
1515

1616
# factorization
1717
X, Y = MatrixAlgebra.$f(A_mat; kwargs...)
1818

1919
# matrix to tensor
20+
biperm = permmortar((codomain_perm, domain_perm))
2021
axes_codomain, axes_domain = blocks(axes(A)[biperm])
2122
axes_X = tuplemortar((axes_codomain, (axes(X, 2),)))
2223
axes_Y = tuplemortar(((axes(Y, 1),), axes_domain))
2324
return unmatricize(X, axes_X), unmatricize(Y, axes_Y)
2425
end
26+
function $f(A::AbstractArray, labels_A, labels_codomain, labels_domain; kwargs...)
27+
biperm = blockedperm_indexin(Tuple.((labels_A, labels_codomain, labels_domain))...)
28+
return $f(A, blocks(biperm)...; kwargs...)
29+
end
30+
function $f(A::AbstractArray, biperm::AbstractBlockPermutation{2}; kwargs...)
31+
return $f(A, blocks(biperm)...; kwargs...)
32+
end
2533
end
2634
end
2735

2836
"""
2937
qr(A::AbstractArray, labels_A, labels_codomain, labels_domain; kwargs...) -> Q, R
38+
qr(A::AbstractArray, codomain_perm::Tuple{Vararg{Int}}, domain_perm::Tuple{Vararg{Int}}; kwargs...) -> Q, R
3039
qr(A::AbstractArray, biperm::AbstractBlockPermutation{2}; kwargs...) -> Q, R
3140
3241
Compute the QR decomposition of a generic N-dimensional array, by interpreting it as
3342
a linear map from the domain to the codomain indices. These can be specified either via
34-
their labels, or directly through a `biperm`.
43+
their labels or directly through a bi-permutation.
3544
3645
## Keyword arguments
3746
@@ -45,11 +54,12 @@ qr
4554

4655
"""
4756
lq(A::AbstractArray, labels_A, labels_codomain, labels_domain; kwargs...) -> L, Q
57+
lq(A::AbstractArray, codomain_perm::Tuple{Vararg{Int}}, domain_perm::Tuple{Vararg{Int}}; kwargs...) -> L, Q
4858
lq(A::AbstractArray, biperm::AbstractBlockPermutation{2}; kwargs...) -> L, Q
4959
5060
Compute the LQ decomposition of a generic N-dimensional array, by interpreting it as
5161
a linear map from the domain to the codomain indices. These can be specified either via
52-
their labels, or directly through a `biperm`.
62+
their labels or directly through a bi-permutation.
5363
5464
## Keyword arguments
5565
@@ -63,11 +73,12 @@ lq
6373

6474
"""
6575
left_polar(A::AbstractArray, labels_A, labels_codomain, labels_domain; kwargs...) -> W, P
76+
left_polar(A::AbstractArray, codomain_perm::Tuple{Vararg{Int}}, domain_perm::Tuple{Vararg{Int}}; kwargs...) -> W, P
6677
left_polar(A::AbstractArray, biperm::AbstractBlockPermutation{2}; kwargs...) -> W, P
6778
6879
Compute the left polar decomposition of a generic N-dimensional array, by interpreting it as
6980
a linear map from the domain to the codomain indices. These can be specified either via
70-
their labels, or directly through a `biperm`.
81+
their labels or directly through a bi-permutation.
7182
7283
## Keyword arguments
7384
@@ -79,11 +90,12 @@ left_polar
7990

8091
"""
8192
right_polar(A::AbstractArray, labels_A, labels_codomain, labels_domain; kwargs...) -> P, W
93+
right_polar(A::AbstractArray, codomain_perm::Tuple{Vararg{Int}}, domain_perm::Tuple{Vararg{Int}}; kwargs...) -> P, W
8294
right_polar(A::AbstractArray, biperm::AbstractBlockPermutation{2}; kwargs...) -> P, W
8395
8496
Compute the right polar decomposition of a generic N-dimensional array, by interpreting it as
8597
a linear map from the domain to the codomain indices. These can be specified either via
86-
their labels, or directly through a `biperm`.
98+
their labels or directly through a bi-permutation.
8799
88100
## Keyword arguments
89101
@@ -95,11 +107,12 @@ right_polar
95107

96108
"""
97109
left_orth(A::AbstractArray, labels_A, labels_codomain, labels_domain; kwargs...) -> V, C
110+
left_orth(A::AbstractArray, codomain_perm::Tuple{Vararg{Int}}, domain_perm::Tuple{Vararg{Int}}; kwargs...) -> V, C
98111
left_orth(A::AbstractArray, biperm::AbstractBlockPermutation{2}; kwargs...) -> V, C
99112
100113
Compute the left orthogonal decomposition of a generic N-dimensional array, by interpreting it as
101114
a linear map from the domain to the codomain indices. These can be specified either via
102-
their labels, or directly through a `biperm`.
115+
their labels or directly through a bi-permutation.
103116
104117
## Keyword arguments
105118
@@ -111,11 +124,12 @@ left_orth
111124

112125
"""
113126
right_orth(A::AbstractArray, labels_A, labels_codomain, labels_domain; kwargs...) -> C, V
127+
right_orth(A::AbstractArray, codomain_perm::Tuple{Vararg{Int}}, domain_perm::Tuple{Vararg{Int}}; kwargs...) -> C, V
114128
right_orth(A::AbstractArray, biperm::AbstractBlockPermutation{2}; kwargs...) -> C, V
115129
116130
Compute the right orthogonal decomposition of a generic N-dimensional array, by interpreting it as
117131
a linear map from the domain to the codomain indices. These can be specified either via
118-
their labels, or directly through a `biperm`.
132+
their labels or directly through a bi-permutation.
119133
120134
## Keyword arguments
121135
@@ -127,11 +141,12 @@ right_orth
127141

128142
"""
129143
factorize(A::AbstractArray, labels_A, labels_codomain, labels_domain; kwargs...) -> X, Y
144+
factorize(A::AbstractArray, codomain_perm::Tuple{Vararg{Int}}, domain_perm::Tuple{Vararg{Int}}; kwargs...) -> X, Y
130145
factorize(A::AbstractArray, biperm::AbstractBlockPermutation{2}; kwargs...) -> X, Y
131146
132147
Compute the decomposition of a generic N-dimensional array, by interpreting it as
133148
a linear map from the domain to the codomain indices. These can be specified either via
134-
their labels, or directly through a `biperm`.
149+
their labels or directly through a bi-permutation.
135150
136151
## Keyword arguments
137152
@@ -143,11 +158,12 @@ factorize
143158

144159
"""
145160
eigen(A::AbstractArray, labels_A, labels_codomain, labels_domain; kwargs...) -> D, V
161+
eigen(A::AbstractArray, codomain_perm::Tuple{Vararg{Int}}, domain_perm::Tuple{Vararg{Int}}; kwargs...) -> D, V
146162
eigen(A::AbstractArray, biperm::AbstractBlockPermutation{2}; kwargs...) -> D, V
147163
148164
Compute the eigenvalue decomposition of a generic N-dimensional array, by interpreting it as
149165
a linear map from the domain to the codomain indices. These can be specified either via
150-
their labels, or directly through a `biperm`.
166+
their labels or directly through a bi-permutation.
151167
152168
## Keyword arguments
153169
@@ -161,28 +177,37 @@ See also `MatrixAlgebraKit.eig_full!`, `MatrixAlgebraKit.eig_trunc!`, `MatrixAlg
161177
"""
162178
function eigen(A::AbstractArray, labels_A, labels_codomain, labels_domain; kwargs...)
163179
biperm = blockedperm_indexin(Tuple.((labels_A, labels_codomain, labels_domain))...)
164-
return eigen(A, biperm; kwargs...)
180+
return eigen(A, blocks(biperm)...; kwargs...)
165181
end
166182
function eigen(A::AbstractArray, biperm::AbstractBlockPermutation{2}; kwargs...)
183+
return eigen(A, blocks(biperm)...; kwargs...)
184+
end
185+
function eigen(
186+
A::AbstractArray,
187+
codomain_perm::Tuple{Vararg{Int}}, domain_perm::Tuple{Vararg{Int}};
188+
kwargs...,
189+
)
167190
# tensor to matrix
168-
A_mat = matricize(A, biperm)
191+
A_mat = matricize(A, codomain_perm, domain_perm)
169192

170193
# factorization
171194
D, V = MatrixAlgebra.eigen!(A_mat; kwargs...)
172195

173196
# matrix to tensor
197+
biperm = permmortar((codomain_perm, domain_perm))
174198
axes_codomain, = blocks(axes(A)[biperm])
175199
axes_V = tuplemortar((axes_codomain, (axes(V, ndims(V)),)))
176200
return D, unmatricize(V, axes_V)
177201
end
178202

179203
"""
180204
eigvals(A::AbstractArray, labels_A, labels_codomain, labels_domain; kwargs...) -> D
205+
eigvals(A::AbstractArray, codomain_perm::Tuple{Vararg{Int}}, domain_perm::Tuple{Vararg{Int}}; kwargs...) -> D
181206
eigvals(A::AbstractArray, biperm::AbstractBlockPermutation{2}; kwargs...) -> D
182207
183208
Compute the eigenvalues of a generic N-dimensional array, by interpreting it as
184209
a linear map from the domain to the codomain indices. These can be specified either via
185-
their labels, or directly through a `biperm`. The output is a vector of eigenvalues.
210+
their labels or directly through a bi-permutation. The output is a vector of eigenvalues.
186211
187212
## Keyword arguments
188213
@@ -194,20 +219,28 @@ See also `MatrixAlgebraKit.eig_vals!` and `MatrixAlgebraKit.eigh_vals!`.
194219
"""
195220
function eigvals(A::AbstractArray, labels_A, labels_codomain, labels_domain; kwargs...)
196221
biperm = blockedperm_indexin(Tuple.((labels_A, labels_codomain, labels_domain))...)
197-
return eigvals(A, biperm; kwargs...)
222+
return eigvals(A, blocks(biperm)...; kwargs...)
198223
end
199224
function eigvals(A::AbstractArray, biperm::AbstractBlockPermutation{2}; kwargs...)
200-
A_mat = matricize(A, biperm)
225+
return eigvals(A, blocks(biperm)...; kwargs...)
226+
end
227+
function eigvals(
228+
A::AbstractArray,
229+
codomain_perm::Tuple{Vararg{Int}}, domain_perm::Tuple{Vararg{Int}};
230+
kwargs...,
231+
)
232+
A_mat = matricize(A, codomain_perm, domain_perm)
201233
return MatrixAlgebra.eigvals!(A_mat; kwargs...)
202234
end
203235

204236
"""
205237
svd(A::AbstractArray, labels_A, labels_codomain, labels_domain; kwargs...) -> U, S, Vᴴ
238+
svd(A::AbstractArray, codomain_perm::Tuple{Vararg{Int}}, domain_perm::Tuple{Vararg{Int}}; kwargs...) -> U, S, Vᴴ
206239
svd(A::AbstractArray, biperm::AbstractBlockPermutation{2}; kwargs...) -> U, S, Vᴴ
207240
208241
Compute the SVD decomposition of a generic N-dimensional array, by interpreting it as
209242
a linear map from the domain to the codomain indices. These can be specified either via
210-
their labels, or directly through a `biperm`.
243+
their labels or directly through a bi-permutation.
211244
212245
## Keyword arguments
213246
@@ -220,16 +253,24 @@ See also `MatrixAlgebraKit.svd_full!`, `MatrixAlgebraKit.svd_compact!`, and `Mat
220253
"""
221254
function svd(A::AbstractArray, labels_A, labels_codomain, labels_domain; kwargs...)
222255
biperm = blockedperm_indexin(Tuple.((labels_A, labels_codomain, labels_domain))...)
223-
return svd(A, biperm; kwargs...)
256+
return svd(A, blocks(biperm)...; kwargs...)
224257
end
225258
function svd(A::AbstractArray, biperm::AbstractBlockPermutation{2}; kwargs...)
259+
return svd(A, blocks(biperm)...; kwargs...)
260+
end
261+
function svd(
262+
A::AbstractArray,
263+
codomain_perm::Tuple{Vararg{Int}}, domain_perm::Tuple{Vararg{Int}};
264+
kwargs...,
265+
)
226266
# tensor to matrix
227-
A_mat = matricize(A, biperm)
267+
A_mat = matricize(A, codomain_perm, domain_perm)
228268

229269
# factorization
230270
U, S, Vᴴ = MatrixAlgebra.svd!(A_mat; kwargs...)
231271

232272
# matrix to tensor
273+
biperm = permmortar((codomain_perm, domain_perm))
233274
axes_codomain, axes_domain = blocks(axes(A)[biperm])
234275
axes_U = tuplemortar((axes_codomain, (axes(U, 2),)))
235276
axes_Vᴴ = tuplemortar(((axes(Vᴴ, 1),), axes_domain))
@@ -238,30 +279,38 @@ end
238279

239280
"""
240281
svdvals(A::AbstractArray, labels_A, labels_codomain, labels_domain) -> S
282+
svdvals(A::AbstractArray, codomain_perm::Tuple{Vararg{Int}}, domain_perm::Tuple{Vararg{Int}}) -> S
241283
svdvals(A::AbstractArray, biperm::AbstractBlockPermutation{2}) -> S
242284
243285
Compute the singular values of a generic N-dimensional array, by interpreting it as
244286
a linear map from the domain to the codomain indices. These can be specified either via
245-
their labels, or directly through a `biperm`. The output is a vector of singular values.
287+
their labels or directly through a bi-permutation. The output is a vector of singular values.
246288
247289
See also `MatrixAlgebraKit.svd_vals!`.
248290
"""
249291
function svdvals(A::AbstractArray, labels_A, labels_codomain, labels_domain)
250292
biperm = blockedperm_indexin(Tuple.((labels_A, labels_codomain, labels_domain))...)
251-
return svdvals(A, biperm)
293+
return svdvals(A, blocks(biperm)...)
252294
end
253295
function svdvals(A::AbstractArray, biperm::AbstractBlockPermutation{2})
254-
A_mat = matricize(A, biperm)
296+
return svdvals(A, blocks(biperm)...)
297+
end
298+
function svdvals(
299+
A::AbstractArray,
300+
codomain_perm::Tuple{Vararg{Int}}, domain_perm::Tuple{Vararg{Int}}
301+
)
302+
A_mat = matricize(A, codomain_perm, domain_perm)
255303
return MatrixAlgebra.svdvals!(A_mat)
256304
end
257305

258306
"""
259307
left_null(A::AbstractArray, labels_A, labels_codomain, labels_domain; kwargs...) -> N
308+
left_null(A::AbstractArray, codomain_perm::Tuple{Vararg{Int}}, domain_perm::Tuple{Vararg{Int}}; kwargs...) -> N
260309
left_null(A::AbstractArray, biperm::AbstractBlockPermutation{2}; kwargs...) -> N
261310
262311
Compute the left nullspace of a generic N-dimensional array, by interpreting it as
263312
a linear map from the domain to the codomain indices. These can be specified either via
264-
their labels, or directly through a `biperm`.
313+
their labels or directly through a bi-permutation.
265314
The output satisfies `N' * A ≈ 0` and `N' * N ≈ I`.
266315
267316
## Keyword arguments
@@ -274,23 +323,32 @@ The output satisfies `N' * A ≈ 0` and `N' * N ≈ I`.
274323
"""
275324
function left_null(A::AbstractArray, labels_A, labels_codomain, labels_domain; kwargs...)
276325
biperm = blockedperm_indexin(Tuple.((labels_A, labels_codomain, labels_domain))...)
277-
return left_null(A, biperm; kwargs...)
326+
return left_null(A, blocks(biperm)...; kwargs...)
278327
end
279328
function left_null(A::AbstractArray, biperm::AbstractBlockPermutation{2}; kwargs...)
280-
A_mat = matricize(A, biperm)
329+
return left_null(A, blocks(biperm)...; kwargs...)
330+
end
331+
function left_null(
332+
A::AbstractArray,
333+
codomain_perm::Tuple{Vararg{Int}}, domain_perm::Tuple{Vararg{Int}};
334+
kwargs...,
335+
)
336+
A_mat = matricize(A, codomain_perm, domain_perm)
281337
N = MatrixAlgebraKit.left_null!(A_mat; kwargs...)
338+
biperm = permmortar((codomain_perm, domain_perm))
282339
axes_codomain = first(blocks(axes(A)[biperm]))
283340
axes_N = tuplemortar((axes_codomain, (axes(N, 2),)))
284341
return unmatricize(N, axes_N)
285342
end
286343

287344
"""
288345
right_null(A::AbstractArray, labels_A, labels_codomain, labels_domain; kwargs...) -> Nᴴ
346+
right_null(A::AbstractArray, codomain_perm::Tuple{Vararg{Int}}, domain_perm::Tuple{Vararg{Int}}; kwargs...) -> Nᴴ
289347
right_null(A::AbstractArray, biperm::AbstractBlockPermutation{2}; kwargs...) -> Nᴴ
290348
291349
Compute the right nullspace of a generic N-dimensional array, by interpreting it as
292350
a linear map from the domain to the codomain indices. These can be specified either via
293-
their labels, or directly through a `biperm`.
351+
their labels or directly through a bi-permutation.
294352
The output satisfies `A * Nᴴ' ≈ 0` and `Nᴴ * Nᴴ' ≈ I`.
295353
296354
## Keyword arguments
@@ -303,11 +361,19 @@ The output satisfies `A * Nᴴ' ≈ 0` and `Nᴴ * Nᴴ' ≈ I`.
303361
"""
304362
function right_null(A::AbstractArray, labels_A, labels_codomain, labels_domain; kwargs...)
305363
biperm = blockedperm_indexin(Tuple.((labels_A, labels_codomain, labels_domain))...)
306-
return right_null(A, biperm; kwargs...)
364+
return right_null(A, blocks(biperm)...; kwargs...)
307365
end
308366
function right_null(A::AbstractArray, biperm::AbstractBlockPermutation{2}; kwargs...)
309-
A_mat = matricize(A, biperm)
367+
return right_null(A, blocks(biperm)...; kwargs...)
368+
end
369+
function right_null(
370+
A::AbstractArray,
371+
codomain_perm::Tuple{Vararg{Int}}, domain_perm::Tuple{Vararg{Int}};
372+
kwargs...,
373+
)
374+
A_mat = matricize(A, codomain_perm, domain_perm)
310375
Nᴴ = MatrixAlgebraKit.right_null!(A_mat; kwargs...)
376+
biperm = permmortar((codomain_perm, domain_perm))
311377
axes_domain = last(blocks((axes(A)[biperm])))
312378
axes_Nᴴ = tuplemortar(((axes(Nᴴ, 1),), axes_domain))
313379
return unmatricize(Nᴴ, axes_Nᴴ)

src/matricize.jl

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -154,16 +154,11 @@ function unmatricize(
154154
)
155155
end
156156

157-
function unmatricize(
158-
m::AbstractMatrix,
159-
blocked_axes::BlockedTuple{2, <:Any, <:Tuple{Vararg{AbstractUnitRange}}},
160-
)
157+
function unmatricize(m::AbstractMatrix, blocked_axes::AbstractBlockTuple{2})
161158
return unmatricize(FusionStyle(m), m, blocked_axes)
162159
end
163160
function unmatricize(
164-
style::FusionStyle,
165-
m::AbstractMatrix,
166-
blocked_axes::BlockedTuple{2, <:Any, <:Tuple{Vararg{AbstractUnitRange}}},
161+
style::FusionStyle, m::AbstractMatrix, blocked_axes::AbstractBlockTuple{2}
167162
)
168163
return unmatricize(style, m, blocks(blocked_axes)...)
169164
end

0 commit comments

Comments
 (0)