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 8 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
13 changes: 10 additions & 3 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,28 +1,35 @@
name = "TensorAlgebra"
uuid = "68bd88dc-f39d-4e12-b2ca-f046b68fcc6a"
authors = ["ITensor developers <[email protected]> and contributors"]
version = "0.2.1"
version = "0.2.2"

[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,27 @@
module TensorAlgebraBlockSparseArraysGradedUnitRangesExt

using BlockArrays: Block, blocksize
using BlockSparseArrays: BlockSparseMatrix, @view!
using GradedUnitRanges: AbstractGradedUnitRange, dual
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}},
)
# 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 24 in ext/TensorAlgebraBlockSparseArraysGradedUnitRangesExt/TensorAlgebraBlockSparseArraysGradedUnitRangesExt.jl

View check run for this annotation

Codecov / codecov/patch

ext/TensorAlgebraBlockSparseArraysGradedUnitRangesExt/TensorAlgebraBlockSparseArraysGradedUnitRangesExt.jl#L21-L24

Added lines #L21 - L24 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
55 changes: 55 additions & 0 deletions src/random_unitary.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
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

# Imports `..` into the namespace.
using EllipsisNotation

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 18 in src/random_unitary.jl

View check run for this annotation

Codecov / codecov/patch

src/random_unitary.jl#L11-L18

Added lines #L11 - L18 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 24 in src/random_unitary.jl

View check run for this annotation

Codecov / codecov/patch

src/random_unitary.jl#L21-L24

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

function random_unitary(

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
rng::AbstractRNG, elt::Type, ax::Tuple{AbstractUnitRange,Vararg{AbstractUnitRange}}
)
return random_unitary!(rng, square_zero_map(elt, ax))

Check warning on line 30 in src/random_unitary.jl

View check run for this annotation

Codecov / codecov/patch

src/random_unitary.jl#L30

Added line #L30 was not covered by tests
end

# Canonicalizing other kinds of inputs.
function random_unitary(

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
rng::AbstractRNG, elt::Type, dims::Tuple{Vararg{Union{AbstractUnitRange,Integer}}}
)
return random_unitary(Random.default_rng(), elt, map(to_axis, dims))

Check warning on line 37 in src/random_unitary.jl

View check run for this annotation

Codecov / codecov/patch

src/random_unitary.jl#L37

Added line #L37 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 40 in src/random_unitary.jl

View check run for this annotation

Codecov / codecov/patch

src/random_unitary.jl#L39-L40

Added lines #L39 - L40 were not covered by tests
end
function random_unitary(

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
rng::AbstractRNG, elt::Type, dims::Union{AbstractUnitRange,Integer}...
)
return random_unitary(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#L45

Added line #L45 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 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(rng::AbstractRNG, dims::Union{AbstractUnitRange,Integer}...)
return random_unitary(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
function random_unitary(dims::Union{AbstractUnitRange,Integer}...)
return random_unitary(Random.default_rng(), Float64, dims)

Check warning on line 54 in src/random_unitary.jl

View check run for this annotation

Codecov / codecov/patch

src/random_unitary.jl#L53-L54

Added lines #L53 - L54 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