Frames Exactly

To compute frames exxactly we utilize CalciumField (documentation: here) from Oscar.jl to compute real and complex numbers exactly. Oscar loads a wrapper, for the c library Calcium, from Nemo.jl. Exact number can be loaded as follows

julia> using Oscar;

julia> C = CalciumField();

julia> C(2)
2

julia> sqrt(C(2))
1.41421 {a where a = 1.41421 [a^2-2=0]}

julia exp(C(2)*C(pi)*C(1im)/C(3))
-0.500000 + 0.866025*I {a where a = -0.500000 + 0.866025*I [a^2+a+1=0]}

Basic Functionality

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

Arguments

  • gram::MatElem{CalciumFieldElem}: A square matrix defined over Oscar's Calcium Field

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> C = CalciumField();

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

julia> Phi = matrix(C, [1 ζ   ζ^2 ζ^3 ζ^4 ζ^5 ζ^6;
                     1 ζ^2 ζ^4 ζ^6 ζ   ζ^3 ζ^5
                     1 ζ^4 ζ   ζ^5 ζ^2 ζ^6 ζ^3]);

julia> gram = conjugate_transpose(Phi)*Phi;

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

Arguments

  • gram::MatElem{CalciumFieldElem}: A square matrix defined over CalciumField.

Returns

  • equiangular_bool::Bool
  • a::CalciumFieldElem
  • b::CalciumFieldElem

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> C = CalciumField();

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

julia> Phi = matrix(C, [1 ζ   ζ^2 ζ^3 ζ^4 ζ^5 ζ^6;
                     1 ζ^2 ζ^4 ζ^6 ζ   ζ^3 ζ^5
                     1 ζ^4 ζ   ζ^5 ζ^2 ζ^6 ζ^3]);

julia> gram = conjugate_transpose(Phi)*Phi;

julia> (equi_bool, a, b) = is_equiangular(gram)
(true, 3, 2.00000 {a^2+b^2 where a = 1.32288 [Im(-0.500000 + 1.32288*I {c^4+c^2-c})], b = -0.500000 [Re(-0.500000 + 1.32288*I {c^4+c^2-c})], c = 0.900969 + 0.433884*I [c^6-c^5+c^4-c^3+c^2-c+1=0]})

julia> QQ(b)
2
source
FrameTheory.is_frame_tightMethod
is_frame_tight(gram) -> Tuple{Bool,CalciumFieldElem}

Arguments

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

Returns

  • tight_bool::Bool
  • c::CalciumFieldElem

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> C = CalciumField();

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

julia> Phi = matrix(C, [1 ζ   ζ^2 ζ^3 ζ^4 ζ^5 ζ^6;
                     1 ζ^2 ζ^4 ζ^6 ζ   ζ^3 ζ^5
                     1 ζ^4 ζ   ζ^5 ζ^2 ζ^6 ζ^3]);

julia> gram = conjugate_transpose(Phi)*Phi;

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

Arguments

  • gram::MatElem{CalciumFieldElem}: A square matrix defined over the Reals or Complexes through CalciumField.

Returns

  • etf_bool::Bool
  • a::CalciumFieldElem
  • b::CalciumFieldElem
  • c::CalciumFieldElem
  • 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> C = CalciumField();

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

julia> Phi = matrix(C, [1 ζ   ζ^2 ζ^3 ζ^4 ζ^5 ζ^6;
                     1 ζ^2 ζ^4 ζ^6 ζ   ζ^3 ζ^5
                     1 ζ^4 ζ   ζ^5 ζ^2 ζ^6 ζ^3]);

julia> gram = conjugate_transpose(Phi)*Phi;

julia> is_ETF(gram)
(true, 3, 2.00000 {a^2+b^2 where a = 1.32288 [Im(-0.500000 + 1.32288*I {c^4+c^2-c})], b = -0.500000 [Re(-0.500000 + 1.32288*I {c^4+c^2-c})], c = 0.900969 + 0.433884*I [c^6-c^5+c^4-c^3+c^2-c+1=0]}, 7, 3)
source

Constructions

FrameTheory.ExactCons.dx2d_etf_from_prime_powerMethod
ExactCons.dx2d_etf_from_prime_power(prime_power) -> MatElem{CalciumFieldElem}

Arguments

  • prime_power::Int: an odd prime power

Returns

  • gram::MatElem{CalciumFieldElem} the Gram matrix of a (prime_power^2+1)/2 by prime_power^2+1 ETF.

Examples

A real Example

julia> gram = ExactCons.dx2d_etf_from_prime_power(5^2);

julia> is_ETF(gram)
(true, 5,1,10,13)

julia> n = size(gram)[1]
26

julia> all(isreal.(gram))
true

A complex example

julia> gram = ExactCons.dx2d_etf_from_prime_power(3);

julia> is_ETF(gram)
(true, 1.73205 {a where a = 1.73205 [a^2-3=0]}, 1, 3.46410 {2*a where a = 1.73205 [a^2-3=0]}, 2)

julia> n = size(gram)[1]
4

julia> all(isreal.(gram))
false
source

Binder Finder

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

Arguments

  • gram::MatElem{CalciumFieldElem}: The Gram matrix of an ETF.

Returns

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

Examples

julia> C = CalciumField();

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

julia> hessa_sic = matrix(C, [
          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 = conjugate_transpose(hessa_sic)*hessa_sic;

julia> is_ETF(hessa_gram)
(true, 2, 1.00000 {a^2+b^2 where a = -0.866025 [Im(0.500000 - 0.866025*I {-c})], b = 0.500000 [Re(0.500000 - 0.866025*I {-c})], c = -0.500000 + 0.866025*I [c^2+c+1=0]}, 6, 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
julia> C = CalciumField();

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

julia> hessa_sic = matrix(C, [
          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 = conjugate_transpose(hessa_sic)*hessa_sic;

julia> is_ETF(hessa_gram)
(true, 2, 1.00000 {a^2+b^2 where a = -0.866025 [Im(0.500000 - 0.866025*I {-c})], b = 0.500000 [Re(0.500000 - 0.866025*I {-c})], c = -0.500000 + 0.866025*I [c^2+c+1=0]}, 6, 3)

julia> binder_finder(hessa_gram)
3×9 Matrix{Int64}:
 1  1  1  0  0  0  0  0  0
 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::MatElem{CalciumFieldElem}: 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 = ExactCons.dx2d_etf_from_prime_power(3);

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

julia> transitivity(G, 1:4)
2

julia> describe(G)
"A4"
source