# # MajoranaAlgebras: A package for constructing Majorana algebras and representations. # # Implementations #
################################################################################ ## ## The main Majorana representation function. ## ################################################################################
# Run the setup function
rep := MAJORANA_SetUp(input, index, options);
# Find representations of the maximal subgroups of G and embed them if IsBound(options.embeddings) and options.embeddings = true and Size(rep.group) > 120then
MAJORANA_MaximalSubgps(rep, options); fi;
# While there are still unknown algebra product loop over the main part of the algorithm while true do
Info(InfoMajorana, 20, STRINGIFY( "There are ", Size(Positions(rep.algebraproducts, false)), " unknown algebra products ") ); if IsBound(rep.innerproducts) then
Info(InfoMajorana, 20, STRINGIFY( "There are ", Size(Positions(rep.innerproducts, false)), " unknown inner products ") ); fi;
if not false in rep.algebraproducts then # We have completely constructed the algebra
Info( InfoMajorana, 10, "Success" );
return rep; elif ForAll(rep.algebraproducts{unknowns}, x -> x = false) then # No more algebra products have been found - the algebra is incomplete
Info( InfoMajorana, 10, "Fail" );
rep.system := main;
return rep; fi;
od;
end );
################################################################################ ## ## The main loop functions ## ################################################################################
## ## The main part of the algorithm that is looped over in the main function. ##
InstallGlobalFunction(MAJORANA_MainLoop,
function(rep)
MAJORANA_FindInnerProducts(rep);
MAJORANA_Fusion(rep);
return MAJORANA_FindAlgebraProducts(rep);
end);
## ## Uses axiom M1 to find inner products ##
InstallGlobalFunction(MAJORANA_FindInnerProducts,
function(rep)
local dim, system, i, j, k, u, v, w, x, y, z, eq;
# If the algebra does not have a form if not IsBound(rep.innerproducts) then return; fi;
# Or if all inner product values have been found if not false in rep.innerproducts then return; fi;
Info( InfoMajorana, 50, "Axiom M1");
dim := Size(rep.setup.coords);
# Create an empty system of unknowns where the indeterminants are the indices of the unknown inner products
system := rec( unknowns := Positions(rep.innerproducts, false) );
system.mat := SparseMatrix(0, Size(system.unknowns), [], [], Rationals);
system.vec := SparseMatrix(0, 1, [], [], Rationals);
# Loop over all known representative algebra products for i in Filtered([1..Size(rep.algebraproducts)], x -> not rep.algebraproducts[x] in [false, fail]) do
x := rep.algebraproducts[i]; # Do this both for the pair rep and also for the reverse of the pair rep for j in [rep.setup.pairreps[i], Reversed(rep.setup.pairreps[i])] do
# Loop over all elements of the spanning set for k in Filtered([1..dim], i -> rep.setup.nullspace.heads[i] = 0) do
w := SparseMatrix(1, dim, [[ k ]], [[ 1 ]], Rationals);
y := MAJORANA_AlgebraProduct(v, w, rep.algebraproducts, rep.setup);
if not y in [fail, false] then
# Use axiom M1 (i.e. that (uv, w) = (u,vw)) to find a new equation
eq := MAJORANA_SeparateInnerProduct(w, x, system.unknowns, rep.innerproducts, rep.setup);
eq := eq - MAJORANA_SeparateInnerProduct(y, u, system.unknowns, rep.innerproducts, rep.setup);
if Size(eq[1]!.indices[1]) = 1then # If there is only one unknown value in the equation then immediately record this value
MAJORANA_SingleInnerSolution( eq, system, rep.innerproducts ); elif eq[1]!.indices[1] <> [] then # Otherwise, add this equation to the system of unknowns
eq := eq*(1/eq[1]!.entries[1, 1]); if not _IsRowOfSparseMatrix(system.mat, eq[1]) then
system.mat := MAJORANA_UnionOfRows(system.mat, eq[1]);
system.vec := MAJORANA_UnionOfRows(system.vec, eq[2]); fi; fi; fi;
od;
od;
od;
# Solve this system of linear equations
MAJORANA_SolutionInnerProducts( system, rep.innerproducts );
return system;
end );
## ## Finds new eigenvectors using the fusion rules ##
InstallGlobalFunction( MAJORANA_Fusion,
function(rep)
local i, ev, a, b, dim, new, FUSE, u;
FUSE := MAJORANA_FuseEigenvectors;
# If specified by the optional second argument, do not assume that we have a Frobenius form if not IsBound(rep.innerproducts) then FUSE := MAJORANA_FuseEigenvectorsNoForm; fi;
# Loop over representatives of the orbits of G on T for i in rep.setup.orbitreps do
u := SparseMatrix(1, Size(rep.setup.coords), [[i]], [[1]], Rationals);
# Continue to loop until no new eigenvectors have been found while true do
Info( InfoMajorana, 50, STRINGIFY("Fusion of ", i, " evecs")) ;
# A record in which to store the new eigenvectors found from fusion
new := ShallowCopy(rep.evecs[i]);
# For pairs of eigenvalues for ev in UnorderedTuples(RecNames(rep.evecs[i]), 2) do for a in Iterator( rep.evecs[i].(ev[1]) ) do for b in Iterator( rep.evecs[i].(ev[2]) ) do # Fuse eigenvectors a and b
FUSE(a, b, u, ev, new, rep);
od;
od;
od;
# Find a basis of the new eigenspaces for ev in RecNames(new) do
new.(ev) := ReversedEchelonMatDestructive(new.(ev)).vectors;
od;
# If no new eigenvectors have been found then break if ForAll(RecNames(new), ev -> Nrows(new.(ev)) = Nrows(rep.evecs[i].(ev))) then
break; fi;
rep.evecs[i] := new;
# Calculate the intersection of the eigenspaces to find new nullspace vectors
MAJORANA_IntersectEigenspaces(rep);
od;
od;
end );
## ## Uses eigenvectors, the resurrection principle and nullspace vectors to find ## algebra product values ##
# If specified by the optional second argument, do not assume that we have a Frobenius form if not IsBound(rep.innerproducts) then evals_list := [["0", "1/4"], ["0", "1/32"]]; fi;
# Keep track of the number of unknown algebra products
n := Size(Positions(rep.algebraproducts, false));
# Setup the system of linear equations
system := rec( unknowns := [],
mat := SparseMatrix(0, 0, [], [], Rationals),
vec := SparseMatrix(0, Size(rep.setup.coords), [], [], Rationals) );
# Use the known eigenvectors to calculate more algebra products
MAJORANA_EigenvectorsAlgebraUnknowns(system, rep); if not false in rep.algebraproducts then return true; fi;
# Use the known nullspace vectors to calculate more algebra products
MAJORANA_NullspaceUnknowns(system, rep); if not false in rep.algebraproducts then return true; fi;
# Use the known eigenvectors and the resurrection principle to calculate more algebra products
Info( InfoMajorana, 50, "Building resurrection");
# For certain pairs of eigenvalues for evals in evals_list do for i in rep.setup.orbitreps do
u := SparseMatrix(1, Size(rep.setup.coords), [[i]], [[1]], Rationals);
list := MAJORANA_ListOfBadIndicesForResurrection(evecs_a, evecs_b, rep);
# Loop over eigevectors a, b and c where a and c are <evals[1]>-eigenvectors # and b is an <evals[2]>-eigenvectors. for index in [1,2] do for j in [1..Nrows(evecs_a)] do
c := CertainRows(evecs_a, [j]); for k in list[index, j] do
b := CertainRows(evecs_b, [k]);
bad := MAJORANA_FindBadIndices( c, rep );
for a in Iterator( evecs_a ) do
# If this is satisfied then the product (a - b)*c is known if CertainColumns(a, bad) = CertainColumns(b, bad) then
# Perform resurrection on these eigenvectors
x := MAJORANA_Resurrection( u, a, b, c, evals, system.unknowns, rep);
if x <> fail and x[1]!.indices[1] <> [] then # If this equation has only one unknown then record this value immediately if Size(x[1]!.indices[1]) = 1then
MAJORANA_SolveSingleSolution( x, system, rep );
if not false in rep.algebraproducts then return true; fi; elif not _IsRowOfSparseMatrix(system.mat, x[1]) then # Otherwise, add the equation to the system of linear equations
system.mat := MAJORANA_UnionOfRows(system.mat, x[1]);
system.vec := MAJORANA_UnionOfRows(system.vec, x[2]); fi; fi; fi;
od; # If the matrix is over a certain size then for performance reasons, solve it already if Nrows(system.mat) > Ncols(system.mat) or Nrows(system.mat) > 8000then
MAJORANA_SolutionAlgProducts(system, rep);
if not false in rep.algebraproducts then return true; fi; fi;
od;
od;
od;
od;
od;
MAJORANA_SolutionAlgProducts(system, rep);
# If no new algebra products have been found then also add the images of the current equations under the group action if n = Size(Positions(rep.algebraproducts, false)) then
return MAJORANA_AllConjugates(system, rep); else
return system; fi;
end );
################################################################################ ## ## Functions used in fusion ## ################################################################################
## ## Add a new eigenvector to a list of existing eigenvectors if not already a member ##
InstallGlobalFunction(MAJORANA_AddEvec,
function(mat, x)
# Don't add a zero row if x!.indices[1] = [] then return mat; fi;
# Scale the vector so that the last entry is equal to one
x!.entries[1] := x!.entries[1]/x!.entries[1, Size(x!.entries[1])];
if _IsRowOfSparseMatrix(mat, x) then
return mat; else
return MAJORANA_UnionOfRows(mat, x); fi;
end);
## ## Given two eigenvectors, if possible, finds product and adds it to appropriate set of evecs. ##
InstallGlobalFunction( MAJORANA_FuseEigenvectors,
function(a, b, u, evals, new, rep)
local ev, x, y, z;
# Find the eigenvalue of the new vector
ev := MAJORANA_FusionTable[ evals ][1];
# Find the product of the eigenvectors a and b
x := MAJORANA_AlgebraProduct(a, b, rep.algebraproducts, rep.setup);
if x in [fail, false] then return; fi;
# If the eigenvalues are both equal to 1/4 or to 1/32 then we need to # do more work to recover the eigenvectors if evals = ["1/4", "1/4"] then
y := MAJORANA_InnerProduct(a, b, rep.innerproducts, rep.setup);
if y = false then
return; fi;
new.("0") := MAJORANA_AddEvec(new.("0"), x - (1/4)*u*y); elif evals = ["1/32", "1/32"] then
y := MAJORANA_InnerProduct(a, b, rep.innerproducts, rep.setup);
if y = false then
return; fi;
z := MAJORANA_AlgebraProduct(u, x, rep.algebraproducts, rep.setup);
if z in [false, fail] then
return; fi;
new.("1/4") := MAJORANA_AddEvec(new.("1/4"), z - (1/32)*u*y);
new.("0") := MAJORANA_AddEvec(new.("0"), x + (3/32)*u*y - 4*z); else
new.(String(ev)) := MAJORANA_AddEvec(new.(String(ev)), x); fi;
end );
## ## Performs the same function as <MAJORANA_FuseEigenvectors> but does not assume ## the existence of a Frobenius form ##
local dim, null, i, ev, evecs_a, evecs_b, Z, x, u, v, g, conj;
dim := Size(rep.setup.coords);
null := [];
# Add intersection of eigenspaces to nullspace
for i in rep.setup.orbitreps do for ev in Combinations(RecNames(rep.evecs[i]), 2) do
evecs_a := ConvertSparseMatrixToMatrix(rep.evecs[i].(ev[1]));
evecs_b := ConvertSparseMatrixToMatrix(rep.evecs[i].(ev[2]));
Z := SumIntersectionMat(evecs_a, evecs_b);
Append(null, Z[2]);
od;
od;
null := SparseMatrix(null, Rationals);
null!.ncols := dim;
# Use eigenvectors to find potentially more nullspace vectors
for i in Filtered(rep.setup.orbitreps, x -> rep.setup.nullspace.heads[x] = 0) do
u := SparseMatrix(1, dim, [[i]], [[1]], Rationals);
for ev in rep.eigenvalues do for v in Iterator( rep.evecs[i].(String(ev)) ) do
x := MAJORANA_AlgebraProduct(u, v, rep.algebraproducts, rep.setup);
if not x in [fail, false] then
null := MAJORANA_UnionOfRows(null, x - ev*v); fi;
od;
od;
od;
# Find basis and remove null vecs from products and evecs
for g in rep.setup.conjelts do for i in [1..Nrows(null)] do
x := CertainRows(null, [i]);
conj := MAJORANA_UnionOfRows(conj, MAJORANA_ConjugateVec(x, g));
od;
od;
for i in [1..Size(rep.setup.pairreps)] do
x := Filtered([1..dim], j -> i in rep.setup.pairorbit[j]); if ForAll(x, j -> rep.setup.nullspace.heads[j] <> 0) then
rep.setup.pairreps[i] := fail;
rep.algebraproducts[i] := fail; fi;
od;
for i in [1..Size(rep.algebraproducts)] do if not rep.algebraproducts[i] in [false, fail] then
rep.algebraproducts[i] := RemoveMatWithHeads(rep.algebraproducts[i], rep.setup.nullspace); fi;
od;
for i in rep.setup.orbitreps do for ev in RecNames(rep.evecs[i]) do
rep.evecs[i].(ev) := RemoveMatWithHeads(rep.evecs[i].(ev), rep.setup.nullspace);
rep.evecs[i].(ev) := ReversedEchelonMatDestructive(rep.evecs[i].(ev)).vectors;
od;
od;
MAJORANA_IntersectEigenspaces(rep);
end );
################################################################################ ## ## Functions used in MAJORANA_FindAlgebraProducts ## ################################################################################
## ## Uses known eigenvectors to find more algebra products ##
local i, # loop over representatives
ev, # loop over eigenvalues
u, # vector with 1 in j th position
v, # eigenvector
x; # result of SeparateAlgebraProduct
# Loop over the representatives of the action of G on T for i in rep.setup.orbitreps do
u := SparseMatrix(1, Size(rep.setup.coords), [[i]], [[1]], Rationals);
# Loop over the three eigenvalues 0, 1/4 and 1/32 for ev in rep.eigenvalues do for v in Iterator(rep.evecs[i].(String(ev))) do
# Create the equation u*evec = 0
x := MAJORANA_SeparateAlgebraProduct(u, v, system.unknowns, rep.algebraproducts, rep.setup);
if x <> fail then
# Adjust to make the equation u*evec = ev*evec
x[2] := x[2] + ev*v;
# If this equation has only one unknown, record its value immediately if Size(x[1]!.indices[1]) = 1then
MAJORANA_SolveSingleSolution( x, system, rep );
if not false in rep.algebraproducts then return true; fi;
elif x[1]!.indices[1] <> [] and not _IsRowOfSparseMatrix(system.mat, x[1]) then # Otherwise add the equation to the linear system
system.mat := MAJORANA_UnionOfRows(system.mat, x[1]);
system.vec := MAJORANA_UnionOfRows(system.vec, x[2]); fi; fi;
od;
od;
od;
MAJORANA_SolutionAlgProducts(system, rep);
end);
## ## Uses known nullspace vectors to find new algebra products ##
# Calculate the orbits of G on the spanning set coords
x := MAJORANA_Orbits(rep.generators, rep.setup);
# TODO these should be in place but makes it slower :( # Append( rep.setup.conjelts, x.conjelts ); # rep.setup.conjelts := DuplicateFreeList(rep.setup.conjelts);
# Loop over the representatives of these orbits for i in x.orbitreps do if ForAny(rep.setup.pairorbit[i], k -> rep.algebraproducts[AbsInt(k)] = false) then
u := SparseMatrix(1, dim, [[i]], [[1]], Rationals);
for v in Iterator(rep.setup.nullspace.vectors) do # Calculate the equation u*v = 0
x := MAJORANA_SeparateAlgebraProduct(u,v,system.unknowns,rep.algebraproducts,rep.setup);
# If the equation has only one unknown then immediately record this value if x <> fail and Size(x[1]!.indices[1]) = 1then
MAJORANA_SolveSingleSolution( x, system, rep); if not false in rep.algebraproducts then return true; fi;
elif x <> fail and x[1]!.indices[1] <> [] then # Otherwise add this equation to the system of linear equations if not _IsRowOfSparseMatrix(system.mat, x[1]) then
system.mat := MAJORANA_UnionOfRows(system.mat, x[1]);
system.vec := MAJORANA_UnionOfRows(system.vec, x[2]); fi; fi;
od; fi;
# If the matrix is too big then for performance reasons, solve already if Nrows(system.mat) > 8000then
MAJORANA_SolutionAlgProducts(system, rep);
if not false in rep.algebraproducts then return; fi; fi;
od;
MAJORANA_SolutionAlgProducts(system, rep);
end );
## ## Performs the resurrection priciple on the eigenvectors a, b and c where ## a, c are <evals[1]>-eigenvectors and b in a <evals[2]>-eigenvector. ##
InstallGlobalFunction(MAJORANA_Resurrection,
function(u, a, b, c, evals, unknowns, rep)
local x, y, z, eqn, diff, proj, i, ev;
# Calculate the product ev*b*c
ev := MAJORANA_FusionTable[ evals ][1];
eqn := ev*MAJORANA_SeparateAlgebraProduct(b, c, unknowns, rep.algebraproducts, rep.setup);
# If this product has known unknowns then it is not useful to us if eqn[1]!.indices[1] = [] or eqn = fail then return fail; fi;
# Calculate the product (a - b)*c
x := MAJORANA_AlgebraProduct(c, a - b, rep.algebraproducts, rep.setup); if x = fail then return fail; fi;
# Calculate the product u*((a - b)*c)
z := MAJORANA_SeparateAlgebraProduct(u, x, unknowns, rep.algebraproducts, rep.setup); if z = fail then return fail; fi;
eqn := eqn + z;
diff := a - b;
# If a and c are 1/4-eigenvectors then we need to calculate the projection # of (a - b)*c onto the 1-eigenspace of u. if evals[1] = "1/4"then
i := u!.indices[1, 1];
# Loop over group elements and matrix rows for g in DuplicateFreeList(rep.setup.conjelts) do for i in [1 .. Nrows(system.mat)] do if system.mat!.indices[i] <> [] then
conj := [,];
# Calculate the images under g
conj[1] := MAJORANA_ConjugateRow(CertainRows(system.mat, [i]), g, new.unknowns );
conj[2] := MAJORANA_ConjugateVec(CertainRows(system.vec, [i]), g);
# If the matrix is sufficiently big then for performance reasons, solve already if Nrows(new.mat) > Ncols(new.mat) then
MAJORANA_SolutionAlgProducts(new, rep);
if not false in rep.algebraproducts then return true; fi;
# And also remove the known products from the original system
MAJORANA_RemoveKnownAlgProducts(system, rep, false); fi;
od;
MAJORANA_SolutionAlgProducts(new, rep);
return new;
end );
################################################################################ ## ## The product functions ## ################################################################################
## ## Takes two vectors and returns their algebra product if known and false or fail if not ##
InstallGlobalFunction( MAJORANA_AlgebraProduct,
function(u,v,algebraproducts,setup) # If all the relevant products are known, returns the algebra product of u and v. If not, returns 0
local i, # loop over u
j, # loop over v
k, # pair orbit index
x, # algebra product
g, # conjugating element
sign, # correct sign of 5A axes
vec, # output vec
vecs,
elts,
pos;
# <elts> will record the permutations that we have to conjugate by # <vecs> will record the corresponding vector that we are permuting
elts := [];
vecs := [];
# Loop over the non-zero coefficients of u and v in reverse order for i in Reversed([1..Size(u!.indices[1])]) do for j in Reversed([1..Size(v!.indices[1])]) do
# Find the representative of the orbital containing (i,j)
k := setup.pairorbit[u!.indices[1, i], v!.indices[1, j]];
# Adjust the sign if k > 0then
sign := 1; else
sign := -1;
k := -k; fi;
x := algebraproducts[k];
if not x in [fail, false] then
g := setup.pairconj[u!.indices[1, i], v!.indices[1, j]];
pos := Position(elts,g);
# If we have already seen this elt then add the product <x> to the corresponding # vector in vecs, else add the elt and the product to these lists. if pos <> fail then
AddRow(x!.indices[1], sign*u!.entries[1, i]*v!.entries[1, j]*x!.entries[1], vecs[pos]!.indices, vecs[pos]!.entries, 1); else
Add(elts, g);
Add(vecs, CopyMat(sign*u!.entries[1, i]*v!.entries[1, j]*x)); fi; elif x = false then # cannot calculate product
return false; else# product with a vector in the nullspace
return fail; fi;
od;
od;
# Now go over all group elements are permute their corresponding vectors, add the # result to the output vec as we go along for i in [1..Size(elts)] do
x := MAJORANA_ConjugateVec(vecs[i], setup.pairconjelts[elts[i]]);
AddRow(x!.indices[1], x!.entries[1], vec!.indices, vec!.entries, 1);
od;
## ## Takes two vectors and returns their inner product if known and false or fail if not ##
InstallGlobalFunction( MAJORANA_InnerProduct,
function(u, v, innerproducts, setup)
local i, # loop over u
j, # loop over v
k, # pair orbit index
sign, # correct for 5A axes
sum; # output value
sum := 0;
# Loop over the non-zero coefficients of u and v for i in Reversed([1..Size(u!.indices[1])]) do for j in Reversed([1..Size(v!.indices[1])]) do # Find the representative of the orbital containing the pair (i,j)
k := setup.pairorbit[u!.indices[1, i], v!.indices[1, j]];
# Adjust the sign if k > 0then
sign := 1; else
sign := -1;
k := -k; fi;
if innerproducts[k] <> false then
sum := sum + sign*u!.entries[1, i]*v!.entries[1, j]*innerproducts[k]; else
return false; fi;
od;
od;
return sum;
end );
################################################################################ ## ## Functions for finding indices that give unknown algebra products ## ################################################################################
## ## Finds the indices i such that v_i*v is not known ##
InstallGlobalFunction(MAJORANA_FindBadIndices,
function(v, rep)
local i, j, k, list, bad;
bad := [];
list := [1..Size(rep.setup.coords)];
# Loop over the non-zero coefficients of v for i in v!.indices[1] do # Loop over all vectors in coords for j in list do
k := rep.setup.pairorbit[i, j];
if k < 0then k := -k; fi;
if rep.algebraproducts[k] = false then # Add this index to the list of unknown indices and remove it # from <list> as we don't need to check it again.
Add(bad,j);
list := Difference(list,[j]); fi;
od;
od;
Sort(bad);
return bad;
end );
## ## For the each eigenvector a in <evecs_a> create a list of indices of the eigenvectors b in ## <evecs_b> such that the product ab involves only one unknown product. We will calculate ## with these eigenvectors first. ##
list[1] := List([1..Nrows(evecs_a)], i -> []);
list[2] := List([1..Nrows(evecs_a)], i -> []);
for j in [1..Nrows(evecs_a)] do
bad := MAJORANA_FindBadIndices( CertainRows(evecs_a,[j]), rep ); for k in [1..Nrows(evecs_b)] do
x := Size(Intersection(bad, evecs_b!.indices[k])); if x = 1then
Add(list[1, j], k); elif x > 1then
Add(list[2, j], k); fi;
od;
od;
return list;
end );
################################################################################ ## ## The conjugating functions ## ################################################################################
## ## Takes a matrix <mat> and conjugates it with respect to the signed perm <g> ##
InstallGlobalFunction( MAJORANA_ConjugateVec,
function(mat,g)
local i,
k,
sign,
res,
pos;
# If g is the identity on vec then return if ForAll(mat!.indices[1], i -> g[i] = i) then return mat; fi;
res := SparseMatrix(1, Ncols(mat), [[]], [[]], Rationals);
# Loop over the non-zero indices of vec and add their image to res for i in [1..Size(mat!.indices[1])] do
# Loop over the non-zero coefficients of row for i in [1..Size(row!.indices[1])] do
# Find the image of the corresponding element of unknowns
y := g{ unknowns[row!.indices[1, i]] };
Sort(y);
# Adjust the sign
sign := 1; if y[1] < 0then sign := -sign; y[1] := -y[1]; fi; if y[2] < 0then sign := -sign; y[2] := -y[2]; fi;
# find the position of the image in unknowns
k := Position(unknowns,y); if k = fail then Add(unknowns, y); k := Size(unknowns); fi;
# Add the value to the ouput row
pos := PositionSorted(output!.indices[1], k);
Add(output!.indices[1], k, pos);
Add(output!.entries[1], sign*row!.entries[1, i], pos);
od;
local row, # record values of unknowns
sum, # record values of knowns
i, # index for dim of u
j, # index for dim of v
l, # ordered version of [i,j]
k,
g,
sign,
elts,
vecs,
x, # vector with 1 in the ith position
y,
pos; # position of unknown product
# <elts> will record the permutations that we have to conjugate by # <vecs> will record the corresponding vector that we are permuting
elts := [];
vecs := [];
# Loop over the non-zero coefficients of u and v for i in [1..Size(u!.indices[1])] do for j in [1..Size(v!.indices[1])] do
# Find the representative of the orbital containing the pair (i,j)
k := setup.pairorbit[u!.indices[1, i], v!.indices[1, j]];
# Adjust the sign if k > 0then
sign := 1; else
sign := -1;
k := -k; fi;
x := algebraproducts[k];
if x = fail then return fail; fi;
# If product is known then calculate as usual if x <> false then
g := setup.pairconj[u!.indices[1, i], v!.indices[1, j]];
pos := Position(elts,g);
if pos <> fail then
vecs[pos] := vecs[pos] - sign*u!.entries[1, i]*v!.entries[1, j]*x; else
Add(elts,g);
Add(vecs,- sign*u!.entries[1, i]*v!.entries[1, j]*x); fi; else # Otherwise, record the coefficient of the unknown pair in the matrix # of the system of linear equations
l := [u!.indices[1, i], v!.indices[1, j]];
Sort(l);
pos := Position(unknowns,l);
if pos = fail then
Add(unknowns, l); pos := Size(unknowns); fi;
for i in [1..Size(elts)] do
x := MAJORANA_ConjugateVec(vecs[i], setup.pairconjelts[elts[i]]);
AddRow(x!.indices[1], x!.entries[1], sum!.indices, sum!.entries, 1);
od;
if Nrows(setup.nullspace.vectors) > 0then
sum := RemoveMatWithHeads(sum, setup.nullspace); fi;
local sol, # solution of system
sign, # correct sign of 5A axes
i, # loop over <unknowns>
d,
nonzero;
# If the matrix is zero then return if ForAll(system.mat!.indices, x -> x = []) then return; fi;
system.mat!.ncols := Size(system.unknowns);
Info( InfoMajorana, 40, STRINGIFY("Solving a ", Nrows(system.mat), " x ", Ncols(system.mat), " matrix") );
# Turn the matrix into an integer matrix for i in [1..Nrows(system.mat)] do
d := _FoldList2(system.mat!.entries[i], DenominatorRat, LcmInt);
system.mat!.entries[i] := system.mat!.entries[i]*d;
system.vec!.entries[i] := system.vec!.entries[i]*d;
od;
# Solve the system of linear equations
MAJORANA_SolveSystem_Whatever(system);
Info( InfoMajorana, 40, "Solved it!" );
# If no new solutions have been found then return if ForAll(system.solutions, x -> x = fail) then
Unbind(system.solutions);
return; fi;
# Otherwise, record the new solutions for i in [1..Size(system.unknowns)] do if system.solutions[i] <> fail then
MAJORANA_RecordSolution( system.solutions[i], system.unknowns[i], rep ); fi;
od;
if not false in rep.algebraproducts then return system; fi;
Unbind(system.solutions);
# Adjust the system of linear equations to take into account the new known products
MAJORANA_RemoveKnownAlgProducts(system, rep);
Info( InfoMajorana, 60, "Solved a single solution");
# Divide through by the coefficient of the indeterminant
elm := x[1]!.entries[1, 1];
x := x/elm;
# Record the new algebra product
MAJORANA_RecordSolution( x[2], system.unknowns[x[1]!.indices[1, 1]], rep );
# Reduce the system of linear equations using this new product
MAJORANA_RemoveKnownAlgProducts( system, rep );
# While we continue to find new products
switch := true;
while switch = true do
if Nrows(system.mat) = 0 or system.unknowns = [] then return; fi;
switch := false;
for i in [1..Nrows(system.mat)] do if Size(system.mat!.indices[i]) = 1then # We have found a new single solution
switch := true;
ind := system.unknowns[system.mat!.indices[i, 1]];
elm := system.mat!.entries[i, 1];
MAJORANA_RecordSolution( CertainRows(system.vec, [i])*(1/elm), ind, rep); fi;
od;
if switch = true then
Info( InfoMajorana, 60, "Solved a new single solution"); # Reduce the system of linear equations using this new product
MAJORANA_RemoveKnownAlgProducts( system, rep ); fi;
od;
MAJORANA_SolutionAlgProducts(system, rep);
end );
## ## Takes a vector that is the product of a pair of vectors given by x and records ## it in the correct place in the list rep.algebraproducts. ##
InstallGlobalFunction( MAJORANA_RecordSolution,
function( v, x, rep)
local y,
g,
sign;
y := rep.setup.pairorbit[x[1], x[2]];
g := SP_Inverse(rep.setup.pairconjelts[rep.setup.pairconj[x[1], x[2]]]);
# Adjust the sign
sign := 1; if y < 0then sign := -1; y := -y; fi;
# Record the new product if rep.algebraproducts[y] = false then
v := sign*MAJORANA_ConjugateVec(v,g);
rep.algebraproducts[y] := RemoveMatWithHeads(v, rep.setup.nullspace); fi;
end );
## ## Takes a system [mat, vec] of unknown algebra products and removes ## from the system any variables which have already been found ##
local system, rep, nonzero,
unsolved,
i,
j,
elm,
x,
y,
sign,
g,
pos,
prod,
nonzero_rows;
system := arg[1]; rep := arg[2];
nonzero := true;
if Length(arg) > 2then nonzero := arg[3]; fi;
if Nrows(system.mat) = 0then return; fi;
unsolved := [];
# Loop over the unknown algebra products for i in [1..Size(system.unknowns)] do
# Find the representative of the orbital containing the unknown value
x := system.unknowns[i];
y := rep.setup.pairorbit[x[1], x[2]];
# Adjust the sign
sign := 1; if y < 0then sign := -1; y := -y; fi;
prod := rep.algebraproducts[y];
# If the product is now known the remove its value from the rhs if prod <> false then
g := rep.setup.pairconjelts[rep.setup.pairconj[x[1], x[2]]];
prod := MAJORANA_ConjugateVec(prod,g);
for j in [1..Nrows(system.vec)] do
pos := Position(system.mat!.indices[j], i); if pos <> fail then
elm := system.mat!.entries[j, pos];
AddRow( prod!.indices[1],-sign*elm*prod!.entries[1],
system.vec!.indices, system.vec!.entries, j); fi;
od; else # Otherwise, we want to keep this column of the matrix
Add(unsolved,i); fi;
od;
if nonzero = true then # Take out any zero rows
nonzero_rows := Filtered([1..Nrows(system.mat)], j -> system.mat!.indices[j] <> []);
system.mat := CertainRows(system.mat, nonzero_rows);
system.vec := CertainRows(system.vec, nonzero_rows); fi;
local row, # record values of unknowns
sum, # record values of knowns
i, # index for dim of u
j, # index for dim of v
m, # orbit of i,j
pos, # position of m in unknowns
sign; # correct sign of 5A axes
sum := SparseZeroMatrix(1, 1, Rationals);
row := SparseZeroMatrix(1, Size(unknowns), Rationals);
# Loop over the nonzero coefficients of u and v for i in [1..Size(u!.indices[1])] do for j in [1..Size(v!.indices[1])] do
# Find the orbital containing the pair (i,j)
m := setup.pairorbit[u!.indices[1, i], v!.indices[1, j]];
# Adjust the sign if m > 0then
sign := 1; else
sign := -1;
m := -m; fi;
# If the product is known the calculate as usual. Otherwise, add the coefficient # to the matrix of the system of linear equations. if innerproducts[m] <> false then
AddToEntry(sum, 1, 1, - sign*u!.entries[1, i]*v!.entries[1, j]*innerproducts[m]); else
pos := Position(unknowns,m);
AddToEntry(row, 1, pos, sign*u!.entries[1, i]*v!.entries[1, j]); fi;
od;
od;
return [row,sum];
end );
## ## Takes a system of linear equations whose unknowns are inner product values and ## removes any unknowns from the system if there function has already been found ##
# Loop over the unknown inner product values for i in [1..Size(system.unknowns)] do
prod := innerproducts[system.unknowns[i]];
# If the product is now known then loop over the rows and remove this value from the rhs if prod <> false then for j in [1..Nrows(system.vec)] do
elm := GetEntry(system.mat, j, i);
if elm <> 0then
AddToEntry(system.vec, j, 1, -elm*prod); fi;
od; else
Add(unsolved, i); fi;
od;
# Otherwise, we want to keep this column of the matrix
system.mat := CertainColumns(system.mat, unsolved);
system.unknowns := system.unknowns{unsolved};
# Solve the system of linear equations
MAJORANA_SolveSystem(system);
# Record any new solutions that have been found for i in [1..Size(system.solutions)] do if system.solutions[i] <> fail then
x := system.unknowns[i]; if system.solutions[i]!.entries[1] = [] then
innerproducts[x] := 0; else
innerproducts[x] := system.solutions[i]!.entries[1, 1]; fi; fi;
od;
## ## For a given range of basis vectors, fill in the Gram matrix wrt those vectors ##
InstallGlobalFunction(MAJORANA_FillGramMatrix,
function(range, innerproducts, setup)
local i, j, k, mat, l;
l := Length(range);
mat := SparseZeroMatrix(l, l, Rationals);
for i in [1..l] do for j in [i..l] do
# Find the representative of the orbital containing the pair <range{[i,j]}>
k := setup.pairorbit[range[i], range[j]];
# Adjust for the sign if k > 0then
SetEntry(mat, i, j, innerproducts[k]);
SetEntry(mat, j, i, innerproducts[k]); else
SetEntry(mat, i, j, -innerproducts[-k]);
SetEntry(mat, j, i, -innerproducts[-k]); fi;
od;
od;
return mat;
end );
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.117Bemerkung:
(vorverarbeitet am 2026-10-12)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.