Skip to content

[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

Draft
wants to merge 12 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions Project.toml
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

View check run for this annotation

Codecov / codecov/patch

ext/TensorAlgebraBlockSparseArraysGradedUnitRangesExt/TensorAlgebraBlockSparseArraysGradedUnitRangesExt.jl#L9

Added line #L9 was not covered by tests
elt::Type, ax::Tuple{AbstractGradedUnitRange,Vararg{AbstractGradedUnitRange}}
)
return BlockSparseArray{elt}(undef, (dual.(ax)..., ax...))

Check warning on line 12 in ext/TensorAlgebraBlockSparseArraysGradedUnitRangesExt/TensorAlgebraBlockSparseArraysGradedUnitRangesExt.jl

View check run for this annotation

Codecov / codecov/patch

ext/TensorAlgebraBlockSparseArraysGradedUnitRangesExt/TensorAlgebraBlockSparseArraysGradedUnitRangesExt.jl#L12

Added line #L12 was not covered by tests
end

function TensorAlgebra.random_unitary!(

Check warning on line 15 in ext/TensorAlgebraBlockSparseArraysGradedUnitRangesExt/TensorAlgebraBlockSparseArraysGradedUnitRangesExt.jl

View check run for this annotation

Codecov / codecov/patch

ext/TensorAlgebraBlockSparseArraysGradedUnitRangesExt/TensorAlgebraBlockSparseArraysGradedUnitRangesExt.jl#L15

Added line #L15 was not covered by tests
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

View check run for this annotation

Codecov / codecov/patch

ext/TensorAlgebraBlockSparseArraysGradedUnitRangesExt/TensorAlgebraBlockSparseArraysGradedUnitRangesExt.jl#L19

Added line #L19 was not covered by tests
throw(ArgumentError("Codomain and domain spaces must be equal."))
# TODO: Define and use `blockdiagindices`
Copy link
Contributor

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 explicit checksquare, or some other means.

Copy link
Member Author

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).

Copy link
Member Author

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.

Copy link
Member Author

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 reworking fusedims/splitdims to accommodate FusionTensors so I'll hold off on that for now.

# 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

View check run for this annotation

Codecov / codecov/patch

ext/TensorAlgebraBlockSparseArraysGradedUnitRangesExt/TensorAlgebraBlockSparseArraysGradedUnitRangesExt.jl#L23-L26

Added lines #L23 - L26 were not covered by tests
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
1 change: 1 addition & 0 deletions src/TensorAlgebra.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ include("contract/blockedperms.jl")
include("contract/allocate_output.jl")
include("contract/contract_matricize/contract.jl")
include("factorizations.jl")
include("random_unitary.jl")

end
52 changes: 52 additions & 0 deletions src/random_unitary.jl
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...))

Check warning on line 5 in src/random_unitary.jl

View check run for this annotation

Codecov / codecov/patch

src/random_unitary.jl#L4-L5

Added lines #L4 - L5 were not covered by tests
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

Check warning on line 15 in src/random_unitary.jl

View check run for this annotation

Codecov / codecov/patch

src/random_unitary.jl#L8-L15

Added lines #L8 - L15 were not covered by tests
end

function random_unitary!(rng::AbstractRNG, a::AbstractMatrix)
Q, _ = qr_full!(randn!(rng, a); positive=true)
a .= Q
return a

Check warning on line 21 in src/random_unitary.jl

View check run for this annotation

Codecov / codecov/patch

src/random_unitary.jl#L18-L21

Added lines #L18 - L21 were not covered by tests
end

function random_unitary(

Check warning on line 24 in src/random_unitary.jl

View check run for this annotation

Codecov / codecov/patch

src/random_unitary.jl#L24

Added line #L24 was not covered by tests
rng::AbstractRNG, elt::Type, ax::Tuple{AbstractUnitRange,Vararg{AbstractUnitRange}}
)
return random_unitary!(rng, square_zero_map(elt, ax))

Check warning on line 27 in src/random_unitary.jl

View check run for this annotation

Codecov / codecov/patch

src/random_unitary.jl#L27

Added line #L27 was not covered by tests
end

# Canonicalizing other kinds of inputs.
function random_unitary(

Check warning on line 31 in src/random_unitary.jl

View check run for this annotation

Codecov / codecov/patch

src/random_unitary.jl#L31

Added line #L31 was not covered by tests
rng::AbstractRNG, elt::Type, dims::Tuple{Vararg{Union{AbstractUnitRange,Integer}}}
)
return random_unitary(rng, elt, map(to_axis, dims))

Check warning on line 34 in src/random_unitary.jl

View check run for this annotation

Codecov / codecov/patch

src/random_unitary.jl#L34

Added line #L34 was not covered by tests
end
function random_unitary(elt::Type, dims::Tuple{Vararg{Union{AbstractUnitRange,Integer}}})
return random_unitary(Random.default_rng(), elt, dims)

Check warning on line 37 in src/random_unitary.jl

View check run for this annotation

Codecov / codecov/patch

src/random_unitary.jl#L36-L37

Added lines #L36 - L37 were not covered by tests
end
function random_unitary(

Check warning on line 39 in src/random_unitary.jl

View check run for this annotation

Codecov / codecov/patch

src/random_unitary.jl#L39

Added line #L39 was not covered by tests
rng::AbstractRNG, elt::Type, dims::Union{AbstractUnitRange,Integer}...
)
return random_unitary(rng, elt, dims)

Check warning on line 42 in src/random_unitary.jl

View check run for this annotation

Codecov / codecov/patch

src/random_unitary.jl#L42

Added line #L42 was not covered by tests
end
function random_unitary(elt::Type, dims::Union{AbstractUnitRange,Integer}...)
return random_unitary(Random.default_rng(), elt, dims)

Check warning on line 45 in src/random_unitary.jl

View check run for this annotation

Codecov / codecov/patch

src/random_unitary.jl#L44-L45

Added lines #L44 - L45 were not covered by tests
end
function random_unitary(rng::AbstractRNG, dims::Union{AbstractUnitRange,Integer}...)
return random_unitary(rng, Float64, dims)

Check warning on line 48 in src/random_unitary.jl

View check run for this annotation

Codecov / codecov/patch

src/random_unitary.jl#L47-L48

Added lines #L47 - L48 were not covered by tests
end
function random_unitary(dims::Union{AbstractUnitRange,Integer}...)
return random_unitary(Random.default_rng(), Float64, dims)

Check warning on line 51 in src/random_unitary.jl

View check run for this annotation

Codecov / codecov/patch

src/random_unitary.jl#L50-L51

Added lines #L50 - L51 were not covered by tests
end
1 change: 1 addition & 0 deletions test/Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[deps]
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
BlockArrays = "8e7c35d0-a365-5155-bbbb-fb81a777f24e"
BlockSparseArrays = "2c9a651f-6452-4ace-a6ac-809f4280fbb4"
EllipsisNotation = "da5c29d0-fa7d-589e-88eb-ea29b0a81949"
GradedUnitRanges = "e2de450a-8a67-46c7-b59c-01d5a3d041c5"
JLArrays = "27aeb0d3-9eb9-45fb-866b-73c2ecf80fcb"
Expand Down
Loading