Frames Numerically

Working with frames exactly is often very slow, and not possible. Instead it may often be benificial to work with frames defined numerically. Here frames are defined with the Julia Matrix types with entries being any subtype of Number. Functionality for computing spectrums over matricies wiht entries of BigFloat is provided by GenericLinearAlgebra.jl.

Basic Functionality

FrameTheory.is_frameMethod
is_frame(gram) -> Tuple{Bool,Int}

Arguments

  • gram::Matrix{Number}: A square matrix defined over any sub type of Number

Returns

  • frame_bool::Bool
  • d::Int

Determines if the matrix gram is the Gram matrix for some frame. Returns a boolean frame_bool if the provided matrix is the Gram matrix of a frame for some d-dimensional space. If frame_bool' is 'false then d would be nothing.

Examples

julia> ζ = exp(2*pi*im/7);

julia> Phi = [1.0 ζ   ζ^2 ζ^3 ζ^4 ζ^5 ζ^6;
              1 ζ^2 ζ^4 ζ^6 ζ   ζ^3 ζ^5;
              1 ζ^4 ζ   ζ^5 ζ^2 ζ^6 ζ^3];

julia> gram = Phi'*Phi;

julia> is_frame(gram)
(true, 3)
source
FrameTheory.is_equiangularMethod
is_equiangular(gram) -> Tuple{Bool,Number,Number}

Arguments

  • gram::Matrix{Number}: A square matrix.

Returns

  • equiangular_bool::Bool
  • a::Number
  • b::Number

Determines if the matrix gram is the Gram matrix for some collection of equiangular vectors. Returns a boolean equiangular_bool if the provided matrix is the Gram matrix of a collection of equiangular lines. With a being the vectors common 'magnatudes' and b the 'angle'. If equiangular_bool is False, then a and b will be nothing.

Examples

julia> ζ = exp(2*pi*im/7);

julia> Phi = [1.0 ζ   ζ^2 ζ^3 ζ^4 ζ^5 ζ^6;
              1 ζ^2 ζ^4 ζ^6 ζ   ζ^3 ζ^5;
              1 ζ^4 ζ   ζ^5 ζ^2 ζ^6 ζ^3];

julia> gram = Phi'*Phi;

julia> is_equiangular(gram)
(true, 3.0, 2.0000000000000004)
source
FrameTheory.is_frame_tightMethod
is_frame_tight(gram) -> Tuple{Bool,Number}

Arguments

  • gram::Matrix{Number}: A square matrix which is the Gram matrix for a frame.

Returns

  • tight_bool::Bool
  • c::Number

Determines if the matrix gram is the Gram matrix for frame which is tight. If so returns c being the constant such that gram^2=c*gram. If tight_bool is False, then c will be nothing.

Examples

julia> ζ = exp(2*pi*im/7);

julia> Phi = [1.0 ζ   ζ^2 ζ^3 ζ^4 ζ^5 ζ^6;
              1 ζ^2 ζ^4 ζ^6 ζ   ζ^3 ζ^5;
              1 ζ^4 ζ   ζ^5 ζ^2 ζ^6 ζ^3];

julia> gram = Phi'*Phi;

julia> is_frame_tight(gram)
(true, 7.000000000000001)
source
FrameTheory.is_ETFMethod
is_ETF(gram) -> Tuple{Bool,Number,Number,Number}

Arguments

  • gram::Matrix{Number}: A square matrix defined over the Reals or Complexes

Returns

  • etf_bool::Bool
  • a::Number
  • b::Number
  • c::Number
  • d::Int

Determines if the matrix gram is the Gram matrix for some collection of vectors which form an equiangular tight frame (ETF). Calls and returns the same parameters from is_frame, is_equiangular, and is_frame_tight.

Examples

A 3x7 Paley (3,2,7)-ETF.

julia> ζ = exp(2*pi*im/7);

julia> Phi = [1.0 ζ   ζ^2 ζ^3 ζ^4 ζ^5 ζ^6;
              1 ζ^2 ζ^4 ζ^6 ζ   ζ^3 ζ^5;
              1 ζ^4 ζ   ζ^5 ζ^2 ζ^6 ζ^3];

julia> gram = Phi'*Phi;

julia> is_ETF(gram)
(true, 3.0, 2.0000000000000004, 7.000000000000001, 3)
source

Constructions

A common method for numerically constructing ETFs is by the method of Alternating Projections. This method is not guaranteed to converge but can be used to try and determine if such an ETF exists.

FrameTheory.NumCons.rand_etf_from_alt_projFunction
NumCons.rand_etf_from_alt_proj(T, d, n[; iters]) -> Matrix{T}

Arguments

  • T::Type: A Type for a number such as Float64, Complex{Float64}
  • d::Int: dimension.
  • n::Int: number of vectors.
  • iters::Int=1000: number of iterations to try and converge.

Returns

  • gram::Matrix{T}: The Gram matrix, if one exists, of a d by n ETF. Or non-sense if the algorithm failed to converege

This doesnt seem to be working for T=Complex{BigFloat}

Examples

A real 3x6 ETF

julia> gram = NumCons.rand_etf_from_alt_proj(Float64, 3, 6);

julia> is_ETF(gram)
(true, 1.0, 0.19999999999999998, 1.9999999999999998, 3)

A complex 2x4 ETF

julia> gram = NumCons.rand_etf_from_alt_proj(Complex{Float64}, 2, 4);

julia> is_ETF(gram)
(true, 1.0, 0.3333333333333331, 1.9999999999999996, 2)

No real 2x4 ETF exists A complex 2x4 ETF

julia> gram = NumCons.rand_etf_from_alt_proj(Float64, 2, 4);

julia> is_ETF(gram)
(false, nothing, nothing, nothing, 4)
source

Binder Finder

FrameTheory.binder_finderMethod
binder_finder(gram) -> Matrix{Int}

Arguments

  • gram::Matrix{Number}: The Gram matrix of an ETF.

Returns

  • binder::Matrix{Int}: The Binder of the provided frame, where each row denotes a simplex.

Examples

julia> ζ = exp(2*pi*im/3);

julia> hessa_sic = [
          1    1       1    -1 -1  -1    0   0      0;
          0    0       0     1  ζ  ζ^2  -1 -1*ζ   -1*ζ^2;
         -1  -1*ζ^2  -1*ζ    0  0   0    1  ζ^2     ζ
       ];

julia> hessa_gram = hessa_sic'*hessa_sic;

julia> is_ETF(hessa_gram)
(true, 2.0, 0.9999999999999992, 6.0, 3)

julia> binder_finder(hessa_gram)
12×9 Matrix{Int64}:
 1  1  1  0  0  0  0  0  0
 1  0  0  1  0  0  1  0  0
 1  0  0  0  1  0  0  0  1
 1  0  0  0  0  1  0  1  0
 0  1  0  1  0  0  0  0  1
 0  1  0  0  1  0  0  1  0
 0  1  0  0  0  1  1  0  0
 0  0  1  1  0  0  0  1  0
 0  0  1  0  1  0  1  0  0
 0  0  1  0  0  1  0  0  1
 0  0  0  1  1  1  0  0  0
 0  0  0  0  0  0  1  1  1
source

The Projective Symmetry Group of an ETF

FrameTheory.projective_symmetry_groupMethod
projective_symmetry_group(gram) -> PermGroup

Arguments

  • gram::Matrix{Number}: A square matrix which is the Gram matrix of some ETF.
  • verbose::Bool: (Default false).

Returns

  • G::PermGroup: The group of permutations of the vector of the frame, that correspond to switching equivalences.

BFS backen Adapted from the following Gap code by Joey Iverson: https://github.com/jwiverson/frame-symmetries/blob/main/symp.gap both backends implement the algorithm from section 4 of [7]. Over R or C this algorithm utilizes Proposition 3.3 from the same paper.

Examples

The following is an example of a 2x4 ETF with S4 its symmetry group.

julia> gram = numericalize(ExactCons.dx2d_etf_from_prime_power(3));

julia> typeof(gram)
Matrix{Complex{BigFloat}}

julia> G = projective_symmetry_group(gram)
Permutation group of degree 4

julia> transitivity(G, 1:4)
2

julia> describe(G)
"A4"
source