Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  MajoranaAlgebras.gi   Sprache: unbekannt

 
#
# MajoranaAlgebras: A package for constructing Majorana algebras and representations.
#
# Implementations
#

################################################################################
##
## The main Majorana representation function.
##
################################################################################

InstallGlobalFunction(MajoranaRepresentation,

function(arg)

    local   input, index, options, rep, unknowns, main;

    input := arg[1]; index := arg[2];

    if Size(arg) = 2 then
        options := rec( );
    else
        options := arg[3];
    fi;

    # 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) > 120 then
        MAJORANA_MaximalSubgps(rep, options);
    fi;

    # While there are still unknown algebra product loop over the main part of the algorithm
    while true do

        unknowns := Positions(rep.algebraproducts, false);

        main := MAJORANA_MainLoop(rep);

        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

            u := SparseMatrix(1, dim, [[ j[1] ]], [[ 1 ]], Rationals);
            v := SparseMatrix(1, dim, [[ j[2] ]], [[ 1 ]], Rationals);

            # 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]) = 1 then
                        # 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
##

InstallGlobalFunction(MAJORANA_FindAlgebraProducts,

    function(rep)

    local   x, i, j, k, evals, system, u, a, b, c, bad, list, evecs_a, evecs_b, index, n, evals_list;

    evals_list := [["0", "1/4"], ["1/4", "0"], ["0", "1/32"], ["1/4", "1/32"]];

    # 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

            evecs_a := rep.evecs[i].(evals[1]);
            evecs_b := rep.evecs[i].(evals[2]);

            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]) = 1 then
                                        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) > 8000 then
                            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
##

InstallGlobalFunction( MAJORANA_FuseEigenvectorsNoForm,

    function(a, b, u, evals, new, rep)

    local   ev, x, y, z;

    ev := MAJORANA_FusionTable[ evals ][1];

    x := MAJORANA_AlgebraProduct(a, b, rep.algebraproducts, rep.setup);

    if x in [false, fail] then return; fi;

    if evals = ["1/4", "1/4"] then
        y := MAJORANA_AlgebraProduct(u, x, rep.algebraproducts, rep.setup);

        if y in [fail, false] then return; fi;

        new.("0") := MAJORANA_AddEvec(new.("0"), x - y);
    elif evals = ["1/32", "1/32"] then
        y := MAJORANA_AlgebraProduct(u, x, rep.algebraproducts, rep.setup);

        if y in [fail, false] then return; fi;

        z := MAJORANA_AlgebraProduct(u, y, rep.algebraproducts, rep.setup);

        if z in [fail, false] then return; fi;

        new.("1/4") := MAJORANA_AddEvec(new.("1/4"), y - z);
        new.("0") := MAJORANA_AddEvec(new.("0"), x - 5*y + 4*z);
    else
        new.(String(ev)) := MAJORANA_AddEvec(new.(String(ev)), x);
    fi;

    end );

##
## Returns true if we have full eigenspace decomposition, returns false otherwise
##

InstallGlobalFunction( MAJORANA_CheckBasis,

    function(dim, evecs, rep)

    local i, basis;

    # If there is no inner product then we cannot tell if we have a full eigenspace decomposition
    if rep.innerproducts = false then return false; fi;

    if Sum(List(evecs, Nrows)) + Nrows(rep.setup.nullspace.vectors) < dim - 1 then
        return false;
    fi;

    return true;

    end );

##
## Adds any nonzero intersection of eigenspaces to the nullspace
##

InstallGlobalFunction( MAJORANA_IntersectEigenspaces,

    function(rep)

    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

    null := ReversedEchelonMatDestructive(null).vectors;

    if Nrows(null) = 0 then return; fi;

    conj := SparseMatrix(0, dim, [], [], Rationals);
    conj := MAJORANA_UnionOfRows(conj, null);

    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;

    null := MAJORANA_UnionOfRows(rep.setup.nullspace.vectors, conj);

    rep.setup.nullspace := ReversedEchelonMatDestructive(null);

    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
##

InstallGlobalFunction(MAJORANA_EigenvectorsAlgebraUnknowns,

function(system, rep)

    local   i,          # loop over representatives
            ev,         # loop over eigenvalues
            u,          # vector with 1 in j th position
            v,          # eigenvector
            x;          # result of SeparateAlgebraProduct

    Info( InfoMajorana, 50, "Building eigenvector unknowns");

    # 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]) = 1 then
                        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
##

InstallGlobalFunction( MAJORANA_NullspaceUnknowns,

    function(system, rep)

    local   i, j, u, v, x, dim;

    if (rep.setup.nullspace.vectors) = 0 then return; fi;

    Info( InfoMajorana, 50, "Building nullspace unknowns" );

    dim := Size(rep.setup.coords);

    # 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]) = 1 then

                    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) > 8000 then
            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];

        proj := SparseMatrix(1, diff!.ncols, [[i]], [[GetEntry(diff, 1, i)]], Rationals);
        y := MAJORANA_InnerProduct(diff - proj, c, rep.innerproducts, rep.setup);

        if y <> false then
            eqn[2] := eqn[2] + (1/4)*y*u;
        else
            return fail;
        fi;
    fi;

    return eqn;

    end );

##
## Takes a system of linear equations and calculates the image of each row under
## the action of each of the elements in conjelts.
##

InstallGlobalFunction( MAJORANA_AllConjugates,

    function(system, rep)

    local i, new, g, conj, x;

    Info(   InfoMajorana, 50, "All conjugates") ;

    new := rec( mat := SparseMatrix( 0, 0, [], [], Rationals ),
                vec := SparseMatrix( 0, Ncols(system.vec), [], [], Rationals ),
                unknowns := system.unknowns );

    # 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);

                new.mat := MAJORANA_UnionOfRows(new.mat, conj[1]);
                new.vec := MAJORANA_UnionOfRows(new.vec, conj[2]);
            fi;
        od;

        # 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;

    vec := SparseMatrix(1, Ncols(u), [[]], [[]],  Rationals);

    # <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 > 0 then
                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;

    if Nrows(setup.nullspace.vectors) > 0 then
        return RemoveMatWithHeads(vec, setup.nullspace);
    else
        return vec;
    fi;

    end );

##
## 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 > 0 then
                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 < 0 then 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.
##

InstallGlobalFunction(MAJORANA_ListOfBadIndicesForResurrection,

    function(evecs_a, evecs_b, rep)

    local list, j, k, x, bad;

    list := [,];

    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 = 1 then
                Add(list[1, j], k);
            elif x > 1 then
                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

        k := g[mat!.indices[1, i]];

        sign := 1;

        if k < 0 then k := -k; sign := -1; fi;

        pos := PositionSorted(res!.indices[1], k);

        Add(res!.indices[1], k, pos);
        Add(res!.entries[1], sign*mat!.entries[1, i], pos);
    od;

    return res;

    end );

InstallGlobalFunction(MAJORANA_ConjugateRow,

    function(row, g, unknowns)

    local   output,     # output row
            i,          # loop over length of row
            y,
            k,
            sign,       # corrects sign of 5A axis
            pos;        # position of new product

    # If the elt is the identity then return
    if ForAll(g, i -> g[i] = i) then return row; fi;

    output  := SparseMatrix(1, Ncols(row), [[]], [[]], Rationals);

    # 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] < 0 then sign := -sign; y[1] := -y[1]; fi;
        if y[2] < 0 then 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;

    return output;

    end);

################################################################################
##
## Ancilliary functions for finding unknown algebra products
##
################################################################################

InstallGlobalFunction(MAJORANA_SeparateAlgebraProduct,

    function(u,v,unknowns,algebraproducts,setup)

    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

    row := SparseMatrix( 1, Size(unknowns), [[]], [[]], Rationals);
    sum := SparseMatrix( 1, Size(setup.coords), [[]], [[]], Rationals);

    # <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 > 0 then
                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;

                AddToEntry(row, 1, pos, u!.entries[1, i]*v!.entries[1, j]);
            fi;
        od;
    od;

    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) > 0 then
        sum := RemoveMatWithHeads(sum, setup.nullspace);
    fi;

    return [row, sum];

    end);

MAJORANA_SolveSystem_Whatever := MAJORANA_SolveSystem;
InstallGlobalFunction( MAJORANA_SolutionAlgProducts,

    function( system, rep)

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

    MAJORANA_SolutionAlgProducts(system, rep);

    end );

InstallGlobalFunction( MAJORANA_SolveSingleSolution,

    function(x, system, rep)

    local   elm, ind, y, switch, i;

    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]) = 1 then
            # 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 < 0 then 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
##

InstallGlobalFunction( MAJORANA_RemoveKnownAlgProducts,

    function( arg )

    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) > 2 then nonzero := arg[3]; fi;

    if Nrows(system.mat) = 0 then 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 < 0 then 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;

    system.mat := CertainColumns(system.mat, unsolved);
    system.unknowns := system.unknowns{unsolved};

    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;

    end );

################################################################################
##
## Ancilliary functions for finding unknown inner products
##
################################################################################

InstallGlobalFunction(MAJORANA_SeparateInnerProduct,

    function(u,v,unknowns,innerproducts,setup)

    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 > 0 then
                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
##

InstallGlobalFunction( MAJORANA_RemoveKnownInnProducts,

    function(system, innerproducts)

    local   unsolved, i, j, elm, prod, nonzero_rows;

    unsolved := [];

    if Nrows(system.mat) = 0 then return; fi;

    # 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 <> 0 then
                    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};

    # Remove 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);

    end );

##
## Takes a linear equation with just one unknown inner product value and
## records the new value.
##

InstallGlobalFunction( MAJORANA_SingleInnerSolution,

    function(eq, system, innerproducts)

    local x;

    x := system.unknowns[eq[1]!.indices[1, 1]];

    if eq[2]!.entries[1] = [] then
        innerproducts[x] := 0;
    else
        innerproducts[x] := eq[2]!.entries[1, 1]/eq[1]!.entries[1, 1];
    fi;

    MAJORANA_RemoveKnownInnProducts(system, innerproducts);

    end );

##
## Takes a system of linear equations where are the unknowns are inner products,
## solves the system and records any new values.
##

InstallGlobalFunction( MAJORANA_SolutionInnerProducts,

    function( system, innerproducts)

    local   i, x;

    if Nrows(system.mat) = 0 then return; fi;

    # 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;

    Unbind(system.solutions);

    MAJORANA_RemoveKnownInnProducts( system, innerproducts);

    end );

##
## 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 > 0 then
                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 );

[ Dauer der Verarbeitung: 0.7 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge