-
Notifications
You must be signed in to change notification settings - Fork 2
[WIP] Define random_unitary
constructor
#39
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
d132d0b
8a1b555
6a849a7
219ea49
2e0e672
e47a544
bab22ac
eb86d46
0678785
9440534
30999f2
879ef7d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,30 +1,35 @@ | ||
name = "TensorAlgebra" | ||
uuid = "68bd88dc-f39d-4e12-b2ca-f046b68fcc6a" | ||
authors = ["ITensor developers <[email protected]> and contributors"] | ||
version = "0.2.3" | ||
version = "0.2.4" | ||
|
||
[deps] | ||
ArrayLayouts = "4c555306-a7a7-4459-81d9-ec55ddd5c99a" | ||
BlockArrays = "8e7c35d0-a365-5155-bbbb-fb81a777f24e" | ||
EllipsisNotation = "da5c29d0-fa7d-589e-88eb-ea29b0a81949" | ||
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" | ||
MatrixAlgebraKit = "6c742aac-3347-4629-af66-fc926824e5e4" | ||
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" | ||
TupleTools = "9d95972d-f1c8-5527-a6e0-b4b365fa01f6" | ||
TypeParameterAccessors = "7e5a90cf-f82e-492e-a09b-e3e26432c138" | ||
|
||
[weakdeps] | ||
BlockSparseArrays = "2c9a651f-6452-4ace-a6ac-809f4280fbb4" | ||
GradedUnitRanges = "e2de450a-8a67-46c7-b59c-01d5a3d041c5" | ||
|
||
[extensions] | ||
TensorAlgebraBlockSparseArraysGradedUnitRangesExt = ["BlockSparseArrays", "GradedUnitRanges"] | ||
TensorAlgebraGradedUnitRangesExt = "GradedUnitRanges" | ||
|
||
[compat] | ||
ArrayLayouts = "1.10.4" | ||
BlockArrays = "1.2.0" | ||
BlockSparseArrays = "0.3.6" | ||
EllipsisNotation = "1.8.0" | ||
GradedUnitRanges = "0.1.0" | ||
LinearAlgebra = "1.10" | ||
LinearAlgebra = "1.10.0" | ||
MatrixAlgebraKit = "0.1.1" | ||
Random = "1.10.0" | ||
TupleTools = "1.6.0" | ||
TypeParameterAccessors = "0.2.1, 0.3" | ||
TypeParameterAccessors = "0.2.1, 0.3.0" | ||
julia = "1.10" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
module TensorAlgebraBlockSparseArraysGradedUnitRangesExt | ||
|
||
using BlockArrays: Block, blocksize | ||
using BlockSparseArrays: BlockSparseArray, BlockSparseMatrix, @view! | ||
using GradedUnitRanges: AbstractGradedUnitRange, dual, space_isequal | ||
using Random: AbstractRNG | ||
using TensorAlgebra: TensorAlgebra, random_unitary! | ||
|
||
function TensorAlgebra.square_zero_map( | ||
Check warning on line 9 in ext/TensorAlgebraBlockSparseArraysGradedUnitRangesExt/TensorAlgebraBlockSparseArraysGradedUnitRangesExt.jl
|
||
elt::Type, ax::Tuple{AbstractGradedUnitRange,Vararg{AbstractGradedUnitRange}} | ||
) | ||
return BlockSparseArray{elt}(undef, (dual.(ax)..., ax...)) | ||
Check warning on line 12 in ext/TensorAlgebraBlockSparseArraysGradedUnitRangesExt/TensorAlgebraBlockSparseArraysGradedUnitRangesExt.jl
|
||
end | ||
|
||
function TensorAlgebra.random_unitary!( | ||
Check warning on line 15 in ext/TensorAlgebraBlockSparseArraysGradedUnitRangesExt/TensorAlgebraBlockSparseArraysGradedUnitRangesExt.jl
|
||
rng::AbstractRNG, | ||
a::BlockSparseMatrix{<:Any,<:Any,<:Any,<:NTuple{2,AbstractGradedUnitRange}}, | ||
) | ||
space_isequal(axes(a, 1), dual(axes(a, 2))) || | ||
Check warning on line 19 in ext/TensorAlgebraBlockSparseArraysGradedUnitRangesExt/TensorAlgebraBlockSparseArraysGradedUnitRangesExt.jl
|
||
throw(ArgumentError("Codomain and domain spaces must be equal.")) | ||
# TODO: Define and use `blockdiagindices` | ||
# or `blockdiaglength`. | ||
for i in 1:blocksize(a, 1) | ||
random_unitary!(rng, @view!(a[Block(i, i)])) | ||
end | ||
return a | ||
Check warning on line 26 in ext/TensorAlgebraBlockSparseArraysGradedUnitRangesExt/TensorAlgebraBlockSparseArraysGradedUnitRangesExt.jl
|
||
end | ||
|
||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,10 @@ | ||
module TensorAlgebraGradedUnitRangesExt | ||
|
||
using GradedUnitRanges: AbstractGradedUnitRange, tensor_product | ||
using TensorAlgebra: TensorAlgebra | ||
|
||
function TensorAlgebra.:⊗(a1::AbstractGradedUnitRange, a2::AbstractGradedUnitRange) | ||
return tensor_product(a1, a2) | ||
end | ||
|
||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
using MatrixAlgebraKit: qr_full! | ||
using Random: Random, AbstractRNG, randn! | ||
|
||
function square_zero_map(elt::Type, ax::Tuple{AbstractUnitRange,Vararg{AbstractUnitRange}}) | ||
return zeros(elt, (ax..., ax...)) | ||
end | ||
|
||
function random_unitary!(rng::AbstractRNG, a::AbstractArray) | ||
@assert iseven(ndims(a)) | ||
ndims_codomain = ndims(a) ÷ 2 | ||
biperm = blockedperm(ntuple(identity, ndims(a)), (ndims_codomain, ndims_codomain)) | ||
a_mat = fusedims(a, biperm) | ||
random_unitary!(rng, a_mat) | ||
splitdims!(a, a_mat, biperm) | ||
return a | ||
end | ||
|
||
function random_unitary!(rng::AbstractRNG, a::AbstractMatrix) | ||
mtfishman marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Q, _ = qr_full!(randn!(rng, a); positive=true) | ||
a .= Q | ||
return a | ||
end | ||
|
||
function random_unitary( | ||
rng::AbstractRNG, elt::Type, ax::Tuple{AbstractUnitRange,Vararg{AbstractUnitRange}} | ||
) | ||
return random_unitary!(rng, square_zero_map(elt, ax)) | ||
end | ||
|
||
# Canonicalizing other kinds of inputs. | ||
function random_unitary( | ||
rng::AbstractRNG, elt::Type, dims::Tuple{Vararg{Union{AbstractUnitRange,Integer}}} | ||
) | ||
return random_unitary(rng, elt, map(to_axis, dims)) | ||
end | ||
function random_unitary(elt::Type, dims::Tuple{Vararg{Union{AbstractUnitRange,Integer}}}) | ||
return random_unitary(Random.default_rng(), elt, dims) | ||
end | ||
function random_unitary( | ||
rng::AbstractRNG, elt::Type, dims::Union{AbstractUnitRange,Integer}... | ||
) | ||
return random_unitary(rng, elt, dims) | ||
end | ||
function random_unitary(elt::Type, dims::Union{AbstractUnitRange,Integer}...) | ||
return random_unitary(Random.default_rng(), elt, dims) | ||
end | ||
function random_unitary(rng::AbstractRNG, dims::Union{AbstractUnitRange,Integer}...) | ||
return random_unitary(rng, Float64, dims) | ||
end | ||
function random_unitary(dims::Union{AbstractUnitRange,Integer}...) | ||
return random_unitary(Random.default_rng(), Float64, dims) | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Something worth considering: in this function we are not guaranteed the user inputted a square matrix, in which case this function would still work, but spit out a random left- or right- isometry. I think if we call the function
unitary
, we probably want to check for this, either by an explicitchecksquare
, or some other means.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, I had that in mind but forgot to add that check. We should definitely check it is square (and more specifically, the blocks are the same and the codomain is the dual of the domain).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The idea is definitely that it is unitary in a strict sense, in that it literally maps the space back to itself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After adding this check, I realized there is a crucial thing missing from this PR, which is specifying that the codomain and domain are duals of each other. That will require a separate PR to
fusedims
to support that, though @ogauthe is reworkingfusedims
/splitdims
to accommodate FusionTensors so I'll hold off on that for now.