home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-05-05 | 75.1 KB | 2,665 lines |
- #############################################################################
- ##
- #A ctlattic.g GAP library Ansgar Kaup
- ##
- #A @(#)$Id: ctlattic.g,v 3.10 1993/02/09 14:25:55 martin Rel $
- ##
- #Y Copyright 1990-1992, Lehrstuhl D fuer Mathematik, RWTH Aachen, Germany
- ##
- ## This file contains those functions which mainly deal with lattices in the
- ## context of character tables.
- ##
- #H $Log: ctlattic.g,v $
- #H Revision 3.10 1993/02/09 14:25:55 martin
- #H made undefined globals local
- #H
- #H Revision 3.9 1992/12/08 09:08:38 sam
- #H fixed bug in 'OrthogonalEmbeddings'
- #H
- #H Revision 3.8 1992/10/20 15:24:46 sam
- #H fixed little bug in 'LLL'
- #H
- #H Revision 3.7 1992/09/23 08:40:08 sam
- #H added some comments
- #H
- #H Revision 3.6 1992/09/14 13:24:04 sam
- #H fixed bug in 'Decreased'
- #H
- #H Revision 3.5 1992/08/07 12:04:51 sam
- #H bug in 'DnLattice' fixed
- #H
- #H Revision 3.4 1992/07/10 10:09:36 sam
- #H corrected calls of 'Reduced' in 'DnLattice'
- #H
- #H Revision 3.3 1992/07/02 13:01:12 sam
- #H changed test for solution of D4 lattice in 'DnLattice'
- #H
- #H Revision 3.2 1992/06/25 10:51:45 sam
- #H fixed bug in 'Decreased': No return of 'false' if the indicators
- #H cannot be computed, just warning
- #H
- #H Revision 3.1 1992/06/12 15:24:56 sam
- #H bug in OESD fixed
- #H
- #H Revision 3.0 1992/06/04 07:57:05 sam
- #H initial revision under RCS
- #H
- ##
-
-
- #############################################################################
- ##
- #F InfoCharTable1
- #F InfoCharTable2
- ##
- if not IsBound( InfoCharTable1 ) then InfoCharTable1:= Ignore; fi;
- if not IsBound( InfoCharTable2 ) then InfoCharTable2:= Ignore; fi;
-
-
- #############################################################################
- ##
- #F 'LLL( <tbl>, <reducibles>, [<y>], [\"sort\"], [\"linearcomb\"] )'
- ##
- ##
- LLL := function( arg )
- local
- # help fields
- perm, muezw, mmue, Bz, Bzw, sczw,
- # group
- tbl,
- # sensibility
- y,
- # matrices
- a, b, lcmat, bs, mue,
- # records
- c,
- # vectors
- bsn, bz, B, nullv, scvec,
- # computational fields
- q, ggt, kgv,
- # indices
- i, j, k, ka, l, m, n,
- # booleans
- sort, lc,
- # sub-procedures
- so, reduce;
-
- reduce := function( k, l )
- local r, j;
- if AbsInt( mue[k][l] ) * 2 > 1 then
- r := Int( mue[k][l] );
- if AbsInt( mue[k][l] - r ) * 2 > 1 then
- r := r + SignInt( mue[k][l] );
- fi;
- if r <> 0 then
- if lc then
- lcmat[k] := lcmat[k] - r * lcmat[l];
- fi;
- b[k] := b[k] -r * b[l];
- for j in [1..l-1] do
- if mue[l][j] <> 0 then
- mue[k][j] := mue[k][j] - r * mue[l][j];
- fi;
- od;
- mue[k][l] := mue[k][l] - r;
- fi;
- fi;
- end;
-
- # check input parameters
- if not IsRec( arg[1] ) then
- Error( "first argument must be character table\n",
- "usage: LLL( <tbl>, <reducibles>, [<y>], [\"sort\"],",
- " [\"linearcomb\"] )" );
- fi;
- if not( IsList( arg[2] ) and IsList( arg[2][1] ) ) then
- Error( "second argument must be list of characters\n",
- "usage: LLL( <tbl>, <seq of seq>, [<y>], [\"sort\"],",
- " [\"linearcomb\"] )" );
- fi;
- y := 3/4;
- if IsBound( arg[3] ) and IsRat( arg[3] ) then
- y := arg[3];
- fi;
- tbl := arg[1];
- a := Filtered( arg[2], x -> ForAny( x, y -> y <> 0 ) );
- sort := false;
- lc := false;
- for i in [2..5] do
- if IsBound( arg[i] ) then
- if arg[i] = "sort" then
- sort := true;
- fi;
- if arg[i] = "linearcomb" then
- lc := true;
- fi;
- fi;
- od;
-
- n := Length( a );
- while a[n] = [] do
- n := n - 1;
- od;
- if lc then
- lcmat := IdentityMat( n );
- fi;
- if sort then
- perm := SortCharactersCharTable( tbl, a, "degree" );
- if lc then
- lcmat := Permuted( lcmat, perm );
- fi;
- fi;
- m := Length( a[1] );
- bs := [];
- bsn := [];
- B := [];
- mue := [];
- nullv := [];
- ka := 1;
- b := [];
- for j in [1..m] do
- nullv[j] := 0;
- od;
- for i in [1..n] do
- b[i] := Copy( a[i] );
- mue[i] := [];
- bs[i] := b[i];
- bsn[i] := 1;
- od;
-
- # calculate orthogonal base 'bs' (start with 'bs' = 'b' = 'a')
- B[1] := tbl.operations.ScalarProduct( tbl, a[1], a[1] );
- for i in [ 2 .. n ] do
- for j in [ 1 .. i-1 ] do
- Bzw := tbl.operations.ScalarProduct( tbl, a[i], bs[j] );
- if Bzw = 0 then
-
- # 'bs[j]' is already orthogonal to 'a[i]'
- mue[i][j] := 0;
- else
- mue[i][j] := ( Bzw / B[j] ) / bsn[j];
- q := Denominator( mue[i][j] ) * bsn[j];
- ggt := GcdInt( Numerator( mue[i][j] ), bsn[j] );
- kgv := LcmInt( q / ggt, bsn[i] );
- bs[i] := bs[i] * ( kgv/bsn[i] )
- - bs[j] * ( ( kgv*mue[i][j] )/bsn[j] );
- bsn[i] := kgv;
- fi;
- od;
- B[i] := tbl.operations.ScalarProduct( tbl, bs[i], bs[i] )/
- ( bsn[i]*bsn[i] );
- od;
- InfoCharTable2( "#I LLL: orthogonal base calculated, ", n,
- " actual characters\n" );
-
- # calculate vectors
- k := 1;
- InfoCharTable2( "#I LLL: calculating vector 1\n" );
- k := 2;
- repeat
- if k > ka then
- ka := k;
- InfoCharTable2( "#I LLL: calculating vector", k, "\n" );
- fi;
- reduce( k, k-1 );
- q := mue[k][k-1] * mue[k][k-1] * B[k-1];
- if y * B[k-1] - q - B[k] > 0 then
- if b[k] = nullv then
-
- # delete!
- if lc then
- for i in [k..n-1] do
- lcmat[i] := lcmat[i+1];
- od;
- fi;
- for i in [k..n-1] do
- b[i] := b[i+1];
- B[i] := B[i+1];
- for j in [1..k-1] do
- mue[i][j] := mue[i+1][j];
- od;
- for j in [k..i-1] do
- mue[i][j] := mue[i+1][j+1];
- od;
- od;
- b[n] := [];
- mue[n] := [];
- n := n - 1;
- InfoCharTable2( "#I LLL: ", n, " actual characters\n" );
-
- else
- mmue := mue[k][k-1];
- Bz := B[k] + q;
- if ( B[k] <> 0 and mmue <> 0 ) then
- mue[k][k-1] := mmue * B[k-1] / Bz;
- B[k] := B[k] * B[k-1] / Bz;
- for i in [k+1..n] do
- muezw := mue[i][k];
- mue[i][k] := mue[i][k-1] - mmue * mue[i][k];
- mue[i][k-1] := muezw + mue[k][k-1] * mue[i][k];
- od;
- else
- if mmue <> 0 then
- for i in [k+1..n] do
- mue[i][k-1] := mue[i][k-1] / mmue;
- mue[i][k] := ( mue[i][k-1] - mue[i][k] ) * mmue;
- od;
- mue[k][k-1] := 1/mmue;
- else
- for i in [k+1..n] do
- muezw := mue[i][k-1];
- mue[i][k-1] := mue[i][k];
- mue[i][k] := muezw;
- od;
- B[k] := B[k-1];
- fi;
- fi;
- B[k-1] := Bz;
- bz := b[k-1];
- b[k-1] := b[k];
- b[k] := bz;
- if lc then
- bz := lcmat[k-1];
- lcmat[k-1] := lcmat[k];
- lcmat[k] := bz;
- fi;
- for j in [1..k-2] do
- muezw := mue[k-1][j];
- mue[k-1][j] := mue[k][j];
- mue[k][j] := muezw;
- od;
- if k > 2 then
- k := k - 1;
- fi;
- fi;
- else
- for l in [0..k-3] do
- reduce( k, k-2-l );
- od;
- k := k + 1;
- fi;
- until k > n;
-
- for i in [1..n] do
- if b[i][1] < 0 then
- b[i] := - b[i];
- if lc then
- lcmat[i] := - lcmat[i];
- fi;
- fi;
- od;
-
- # look for irreducibles
- scvec := [];
- for j in [1..n] do
- scvec[j] := tbl.operations.ScalarProduct( tbl, b[j], b[j] );
- od;
- if ForAny( scvec, x -> x = 1 ) then
- InfoCharTable2( "#I LLL: ", Length( Filtered( scvec, x -> x = 1 ) ),
- " irreducible characters found\n" );
- fi;
-
- # prepare the output
- c := rec( irreducibles := [], remainders := [], norms := [] );
- if lc then
- c.irreddecomp:= [];
- c.reddecomp:= [];
- for i in [1..n] do
- if scvec[i] = 1 then
- Add( c.irreducibles, b[i] );
- Add( c.irreddecomp, lcmat[i] );
- else
- Add( c.remainders, b[i] );
- Add( c.reddecomp, lcmat[i] );
- Add( c.norms, scvec[i] );
- fi;
- od;
- if sort then
- perm := SortCharactersCharTable( tbl, c.irreducibles, "degree" );
- c.irreddecomp := Permuted( c.irreddecomp, perm );
- perm := SortCharactersCharTable( tbl, c.remainders, "degree" );
- c.reddecomp := Permuted( c.reddecomp, perm );
- c.norms := Permuted( c.norms, perm );
- fi;
- else
- for i in [1..n] do
- if scvec[i] = 1 then
- Add( c.irreducibles, b[i] );
- else
- Add( c.remainders, b[i] );
- Add( c.norms, scvec[i] );
- fi;
- od;
- if sort then
- SortCharactersCharTable( tbl, c.irreducibles, "degree" );
- perm := SortCharactersCharTable( tbl, c.remainders, "degree" );
- c.norms := Permuted( c.norms, perm );
- fi;
- fi;
- return c;
- end;
-
-
- #############################################################################
- ##
- #F LLLReducedGramMat( <grammat> )
- ##
- ## LLL, working with Gram matrix <grammat>
- ##
- LLLReducedGramMat := function( grammat )
- local
- # variables
- y, i, j, k, n, IdMat,
- m, q, bz, l, ba, b, mue, B, v,
- # procedures
- red, chg, ort, scp, model;
-
- # shortening of vectors
- red := function( l )
- local i, j, q;
- if mue[k][l] - 501/1000 > 0 then
- q := Int( mue[k][l] );
- if AbsInt( mue[k][l] - q ) * 2 - 1 > 0 then
- q := q + SignInt( mue[k][l] );
- fi;
- if q <> 0 then
- mue[k] := mue[k] - q * mue[l];
- b[k] := b[k] - q * b[l];
- ba[k] := ba[k] - q * ba[l];
- for i in [1..n] do
- b[i][k] := b[i][k] - q * b[i][l];
- od;
- fi;
- fi;
- end;
-
- # exchange of vectors
- chg := function( )
- local i, l;
- bz := ba[k];
- ba[k] := ba[k-1];
- ba[k-1] := bz;
- for l in [1..n] do
- q := b[k][l];
- b[k][l] := b[k-1][l];
- b[k-1][l] := q;
- od;
- for l in [1..n] do
- q := b[l][k];
- b[l][k] := b[l][k-1];
- b[l][k-1] := q;
- od;
- if k > 2 then
- k := k - 1;
- fi;
- end;
-
- # Norms of b_i^*
- ort := function( i )
- local l, k;
- k := b[i][i];
- for l in [1..i-1] do
- k := k - mue[i][l] * mue[i][l] * B[l];
- od;
- B[i] := k;
- end;
-
- # Scalar Product
- scp := function( i, j )
- local l, k;
- k := b[i][j];
- for l in [1..j-1] do
- k := k - B[l] * mue[i][l] * mue[j][l];
- od;
- mue[i][j] := k/B[j];
- end;
-
- # making a model
- model := function( )
- if k = 2 then
- B[1] := b[1][1];
- i := 2;
- else
- i := k-1;
- fi;
- while i <= k do
- j := 1;
- while j < i do
- scp( i, j );
- j := j + 1;
- od;
- ort( i );
- i := i + 1;
- od;
- end;
-
- # main program
- # check the input
- if not IsList( grammat ) or not IsList( grammat[1] ) then
- Error( "usage: LLLReducedGramMat( <grammat> )" );
- fi;
- n := Length( grammat );
- y := 3/4;
- b := [];
- for i in [1..n] do
- b[i] := Copy( grammat[i] );
- od;
- B := [];
- IdMat := IdentityMat( n );
- ba := Copy( IdMat );
- mue := Copy( IdMat );
- k := 2;
- while k <= n do
- model( );
- red( k-1 );
- if B[k] - ( y-mue[k][k-1]*mue[k][k-1] )*B[k-1] < 0 then
- chg( );
- model( );
- red( k-1 );
- fi;
- if k > 2 then
- for l in [2..k-1] do
- red( k-l );
- od;
- fi;
- k := k + 1;
- od;
- return rec( remainder:= b, transformation:=ba, scalarproducts:=mue,
- bsnorms := B);
- end;
-
-
- #############################################################################
- ##
- #F ShortestVectors( <mat>, <bound> [, \"positive\" ] )
- ##
- ## kurvec
- ##
- ShortestVectors := function( arg )
- local
- # variables
- n, i, checkpositiv, a, llg, nullv, m, c, q, anz, con, b, v,
- # procedures
- kur, srt, vschr;
-
- # sub-procedures
- kur := function( )
- local l;
- for l in [1..n] do
- v[l] := 0;
- od;
- anz := 0;
- con := true;
- srt( n, 0 );
- end;
-
- # search for shortest vectors
- srt := function( d, dam )
- local i, j, x, k, k1, q;
- if d = 0 then
- if v = nullv then
- con := false;
- else
- anz := anz + 1;
- vschr( dam );
- fi;
- else
- x := 0;
- for j in [d+1..n] do
- x := x + v[j] * llg.scalarproducts[j][d];
- od;
- i := - Int( x );
- if AbsInt( -x-i ) * 2 - 1 > 0 then
- i := i - SignInt( x );
- fi;
- k := i + x;
- q := ( m + 1/1000 - dam ) / llg.bsnorms[d];
- if k * k - q < 0 then
- repeat
- i := i + 1;
- k := k + 1;
- until k * k - q > 0 and k > 0;
- i := i - 1;
- k := k - 1;
- while k * k - q < 0 and con do
- v[d] := i;
- k1 := llg.bsnorms[d] * k * k + dam;
- srt( d-1, k1 );
- i := i - 1;
- k := k - 1;
- od;
- fi;
- fi;
- end;
-
- # output of vector
- vschr := function( dam )
- local i, j, w, neg;
- c.vectors[anz] := [];
- neg := false;
- for i in [1..n] do
- w := 0;
- for j in [1..n] do
- w := w + v[j] * llg.transformation[j][i];
- od;
- if w < 0 then
- neg := true;
- fi;
- c.vectors[anz][i] := w;
- od;
- if checkpositiv and neg then
- c.vectors[anz] := [];
- anz := anz - 1;
- else
- c.norms[anz] := dam;
- fi;
- end;
-
- # main program
- # check input
- if not IsBound( arg[1] )
- or not IsList( arg[1] ) or not IsList( arg[1][1] ) then
- Error ( "first argument must be Gram matrix\n",
- "usage: ShortestVectors( <mat>, <integer> [,<\"positive\">] )" );
- fi;
- if not IsBound( arg[2] ) or not IsInt( arg[2] ) then
- Error ( "second argument must be integer\n",
- "usage: ShortestVectors( <mat>, <integer> [,<\"positive\">] )");
- fi;
- if IsBound( arg[3] ) then
- if IsString( arg[3] ) then
- if arg[3] = "positive" then
- checkpositiv := true;
- else
- checkpositiv := false;
- fi;
- else
- Error ( "third argument must be string\n",
- "usage: ShortestVectors( <mat>, <integer> [,<\"positive\">] )");
- fi;
- else
- checkpositiv := false;
- fi;
- a := arg[1];
- m := arg[2];
- n := Length( a );
- b := [];
- for i in [1..n] do
- b[i] := Copy( a[i] );
- od;
- c := rec( vectors:=[],norms:=[]);
- v := [];
- nullv := [];
- for i in [1..n] do
- nullv[i] := 0;
- od;
- llg:=LLLReducedGramMat(b);
- kur();
- InfoCharTable2( "#I ShortestVectors: ",
- Length( c.vectors ), " vectors found\n" );
- return( c );
- end;
-
-
- #############################################################################
- ##
- #F Extract( <tbl>, <reducibles>, <gram-matrix> [, <missing> ] )
- ##
- Extract := function( arg )
- local
-
- # indices
- i, j, k, l, n,
- # input arrays
- tbl, y, gram, missing,
- # booleans
- deeper, iszero, used, nullbegin, nonmissing,
- maxnorm, minnorm, normbound, maxsum, solmat,
- f, squares, sfind, choicecollect, sequence,
- dependies, solcollect, sum, solcount, max, sumac, kmax,
- solution,
- # functions
- next, zeroset, possiblies, update, correctnorm,
- maxsquare, square, ident, begin;
-
- # choosing next vector for combination
- next := function( lines, solumat, acidx )
- local i, j, solmat, testvec, idxback;
-
- while acidx <= n and k + n - acidx >= kmax do
- solmat := Copy( solumat );
- if k = 0 then
- i := acidx;
- while i <= n and not begin( sequence[i] ) do
- i := i + 1;
- od;
- if i > n then
- nullbegin := true;
- else
- nullbegin := false;
- if i > acidx then
- idxback := sequence[i];
- for j in [acidx + 1..1] do
- sequence[j] := sequence[j -1];
- od;
- sequence[acidx] := idxback;
- fi;
- fi;
- fi;
- k := k + 1;
- f[k] := sequence[acidx];
- testvec := [];
- for i in [1..k] do
- testvec[i] := gram[f[k]][f[i]];
- od;
- zeroset( solmat, testvec, lines );
- acidx := acidx + 1;
- possiblies( 1, solmat, testvec, acidx, lines );
- k := k - 1;
- od;
- end;
-
- # filling zero in places that fill already the conditions
- zeroset := function( solmat, testvec, lines )
- local i, j;
-
- for i in [1..k-1] do
- if testvec[i] = 0 then
- for j in [1..lines] do
- if solmat[j][i] <> 0 and not IsBound( solmat[j][k] ) then
- solmat[j][k] := 0;
- fi;
- od;
- fi;
- od;
- end;
-
- # try and error for the chosen vector
- possiblies := function( start, solmat, testvect, acidx, lines )
- local i, j, remainder, toogreat, equal, solmatback, testvec;
-
- testvec := Copy( testvect );
- toogreat := false;
- equal := true;
- if k > 1 then
- for i in [1..k-1] do
- if testvec[i] < 0 then
- toogreat := true;
- fi;
- if testvec[i] <> 0 then
- equal := false;
- fi;
- od;
- if testvec[k] < 0 then
- toogreat := true;
- fi;
- else
- if not nullbegin then
- while start <= gram[f[k]][f[k]] and start < missing do
- solmat[start][k] := 1;
- start := start + 1;
- od;
- testvec[k] := 0;
- if gram[f[k]][f[k]] > lines then
- lines := gram[f[k]][f[k]];
- fi;
- else
- lines := 0;
- fi;
- fi;
- if not equal and not toogreat then
- while start < lines and IsBound( solmat[start][k] ) do
- start := start + 1;
- od;
- if start <= lines and not IsBound( solmat[start][k] ) then
- solmat[start][k] := 0;
- while not toogreat and not equal do
- solmat[start][k] := solmat[start][k] + 1;
- testvec := update( -1, testvec, start, solmat );
- equal := true;
- for i in [1..k-1] do
- if testvec[i] < 0 then
- toogreat := true;
- fi;
- if testvec[i] <> 0 then
- equal := false;
- fi;
- od;
- if testvec[k] < 0 then
- toogreat := true;
- fi;
- od;
- fi;
- fi;
- if equal and not toogreat then
- solmatback := Copy( solmat );
- for i in [1..missing] do
- if not IsBound( solmat[i][k] ) then
- solmat[i][k] := 0;
- fi;
- od;
- correctnorm( testvec[k], solmat, lines + 1, testvec[k], acidx, lines );
- solmat := Copy( solmatback );
- fi;
- if k > 1 then
- while start <= lines and solmat[start][k] > 0 do
- solmat[start][k] := solmat[start][k] - 1;
- testvec := update( 1, testvec, start, solmat );
- solmatback := Copy( solmat );
- zeroset( solmat, testvec, lines );
- deeper := false;
- for i in [1..k-1] do
- if solmat[start][i] <> 0 then
- deeper := false;
- if testvec[i] = 0 then
- deeper := true;
- else
- for j in [1..missing] do
- if solmat[j][i] <> 0 and not IsBound(solmat[j][k]) then
- deeper := true;
- fi;
- od;
- fi;
- fi;
- od;
- if deeper then
- possiblies( start + 1, solmat, testvec, acidx, lines );
- fi;
- solmat := Copy( solmatback );
- od;
- fi;
- end;
-
- # update the remaining conditions to fill
- update := function( x, testvec, start, solmat )
- local i;
- for i in [1..k-1] do
- if solmat[start][i] <> 0 then
- testvec[i] := testvec[i] + solmat[start][i] * x;
- fi;
- od;
- testvec[k] := testvec[k] - square( solmat[start][k] )
- + square( solmat[start][k] + x );
- return( testvec );
- end;
-
- # correct the norm if all other conditions are filled
- correctnorm := function( remainder, solmat, pos, max, acidx, lines )
- local i, r, newsol, ret;
- if remainder = 0 and pos <= missing + 1 then
- newsol := true;
- for i in [1..solcount[k]] do
- if ident( solcollect[k][i], solmat ) = missing then
- newsol := false;
- fi;
- od;
- if newsol then
- if k > kmax then
- kmax := k;
- fi;
- solcount[k] := solcount[k] + 1;
- solcollect[k][solcount[k]] := [];
- choicecollect[k][solcount[k]] := Copy( f );
- for i in [1..Length( solmat )] do
- solcollect[k][solcount[k]][i] := Copy( solmat[i] );
- od;
- if k = n and pos = missing + 1 then
- ret := 0;
- else
- ret := max;
- if k <> n then
- next( lines, solmat, acidx );
- fi;
- fi;
- else
- ret := max;
- fi;
- else
- if pos <= missing then
- i := maxsquare( remainder, max );
- while i > 0 do
- solmat[pos][k] := i;
- i := correctnorm( remainder-square( i ),
- solmat, pos+1, i, acidx, lines + 1);
- i := i - 1;
- od;
- if i < 0 then
- ret := 0;
- else
- ret := max;
- fi;
- else
- ret := 0;
- fi;
- fi;
- return( ret );
- end;
-
- # compute the maximum squarenumber lower then given integer
- maxsquare := function( value, max )
- local i;
-
- i := 1;
- while square( i ) <= value and i <= max do
- i := i + 1;
- od;
- return( i-1 );
- end;
-
- square := function( i )
- if i = 0 then
- return( 0 );
- else
- if not IsBound( squares[i] ) then
- squares[i] := i * i;
- fi;
- return( squares[i] );
- fi;
- end;
-
- ident := function( a, b )
- # lists the identities of the two given sequences and counts them
- local i, j, k, zi, zz, la, lb;
- la := Length( a );
- lb := Length( b );
- zi := [];
- zz := 0;
- for i in [1..la] do
- j := 1;
- repeat
- if a[i] = b[j] then
- k :=1;
- while k <= zz and j <> zi[k] do
- k := k + 1;
- od;
- if k > zz then
- zz := k;
- zi[zz] := j;
- j := lb;
- fi;
- fi;
- j := j + 1;
- until j > lb;
- od;
- return( zz );
- end;
-
- # looking for character that can stand at the beginning
- begin := function( i )
- local ind;
- if y = [] or gram[i][i] < 4 then
- return true;
- else
- if IsBound( tbl.powermap ) and IsBound( tbl.powermap[2] ) then
- if IsList( tbl.powermap[2] ) and ForAll( tbl.powermap[2], IsInt ) then
- ind := AbsInt( Indicator( tbl, [y[i]], 2 )[1]);
- if gram[i][i] - 1 <= ind
- or ( gram[i][i] = 4 and ind = 1 ) then
- return true;
- fi;
- fi;
- fi;
- fi;
- return false;
- end;
-
- # check input parameters
- if IsCharTable( arg[1] ) then
- tbl := arg[1];
- else
- Error( "first argument must be character-table\n \
- usage: Extract( <tbl>, <reducibles>, <gram-matrix> [, <missing>] )" );
- fi;
- if IsBound( arg[2] ) and IsList( arg[2] ) and IsList( arg[2][1] ) then
- y := Copy( arg[2] );
- else
- Error( "second argument must be list of reducible characters\n \
- usage: Extract( <tbl>, <reducibles>, <gram-matrix> [, <missing>] )" );
- fi;
- if IsBound( arg[2] ) and IsList( arg[3] ) and IsList( arg[3][1] ) then
- gram := Copy( arg[3] );
- else
- Error( "third argument must be gram-matrix of reducible characters\n \
- usage: Extract( <tbl>, <reducibles>, <gram-matrix> [, <missing>] )" );
- fi;
- n := Length( gram );
- if IsBound( arg[4] ) and IsInt( arg[4] ) then
- missing := arg[4];
- else
- missing := n;
- nonmissing := true;
- fi;
-
- # main program
- maxnorm := 0;
- minnorm := gram[1][1];
- normbound := [];
- maxsum := [];
- solcollect := [];
- choicecollect := [];
- sum := [];
- solmat := [];
- used := [];
- solcount := [];
- sfind := [];
- f := [];
- squares := [];
- kmax := 0;
- for i in [1..missing] do
- solmat[i] := [];
- od;
- for i in [1..n] do
- solcount[i] := 0;
- used[i] := false;
- solcollect[i] := [];
- choicecollect[i] := [];
- od;
- for i in [1..n] do
- if gram[i][i] > maxnorm then
- maxnorm := gram[i][i];
- else
- if gram[i][i] < minnorm then
- minnorm := gram[i][i];
- fi;
- fi;
- od;
- j := 0;
- for i in [minnorm..maxnorm] do
- k := 1;
- while k <= n and gram[k][k] <> i do
- k := k + 1;
- od;
- if k <= n then
- j := j + 1;
- normbound[j] := rec( norm:=i, first:=k, last:=0 );
- if k = n then
- normbound[j].last := k;
- else
- k := n;
- while gram[k][k] <> i and k > 0 do
- k := k - 1;
- od;
- if k > 0 then
- normbound[j].last := k;
- fi;
- fi;
- fi;
- od;
- for j in [1..Length( normbound )] do
- maxsum[j] := 0;
- for i in [normbound[j].first..normbound[j].last] do
- if gram[i][i] = normbound[j].norm then
- sum[i] := 0;
- for k in [1..n] do
- sum[i] := sum[i] + gram[i][k];
- od;
- if sum[i] > maxsum[j] then
- maxsum[j] := sum[i];
- fi;
- fi;
- od;
- od;
- k := 1;
- sequence := [];
- i:= 1;
- while i <= Length( normbound ) do
- max := maxsum[i];
- sumac := 0;
- for j in [normbound[i].first..normbound[i].last] do
- if gram[j][j] = normbound[i].norm and sum[j] > sumac
- and sum[j] <= max and not used[j] then
- sequence[k] := j;
- sumac := sum[j];
- fi;
- od;
- if IsBound( sequence[k] ) then
- max := sumac;
- used[sequence[k]] := true;
- k := k + 1;
- else
- i := i + 1;
- fi;
- od;
- k := 0;
- next( 1, solmat, 1 );
- solution := rec( solution := [], choice := choicecollect[kmax] );
- for i in [1..solcount[kmax]] do
- solution.solution[i] := [];
- l := 0;
- for j in [1..missing] do
- iszero := true;
- for k in [1..kmax] do
- if solcollect[kmax][i][j][k] <> 0 then
- iszero := false;
- fi;
- od;
- if not iszero then
- l := l + 1;
- solution.solution[i][l] := solcollect[kmax][i][j];
- fi;
- od;
- od;
- return( solution );
- end;
-
-
- #############################################################################
- ##
- #F Decreased( <tbl>, <chars>, <decompmat>, [ <choice> ] )
- ##
- Decreased := function( arg )
- local
- # indices
- m, n, m1, n1, i, i1, i2, i3, i4, j, jj, j1, j2, j3,
- # booleans
- ende1, ende2, ok, change, delline, delcolumn,
- # help fields
- deleted, kgv, l1, l2, l3, dim, ident,
- # matrices
- invmat, remmat, remmat2, solmat, nonzero,
- # double-indices
- columnidx, lineidx, system, components, compo2,
- # output-fields
- sol, red, redcount, irred,
- # help fields
- IRS, SFI, lc, nc, char, char1, entries,
- # input fields
- tbl, y, solmat, choice,
- # functions
- Idxset, Identset, Invadd, Invmult, Nonzeroset;
-
- Idxset := function()
- # update indices
- local i1, j1;
- i1 := 0;
- for i in [1..m] do
- if not delline[i] then
- i1 := i1 + 1;
- lineidx[i1] := i;
- fi;
- od;
- m1 := i1;
- j1 := 0;
- for j in [1..n] do
- if not delcolumn[j] then
- j1 := j1 + 1;
- columnidx[j1] := j;
- fi;
- od;
- n1 := j1;
- end;
-
- Identset := function( veca, vecb )
- # count identities of veca and vecb and store "non-identities"
- local la, lb, i, j, n, nonid, nic, r;
- n := 0;
- la := Length( veca );
- lb := Length( vecb );
- j := 1;
- nonid := [];
- nic := 0;
- for i in [1..la] do
- while j <= lb and veca[i] > vecb[j] do
- nic := nic + 1;
- nonid[nic] := vecb[j];
- j := j + 1;
- od;
- if j <= lb and veca[i] = vecb[j] then
- n := n + 1;
- j := j + 1;
- fi;
- od;
- while j <= lb do
- nic := nic + 1;
- nonid[nic] := vecb[j];
- j := j + 1;
- od;
- r := rec( nonid := nonid, id := n );
- return( r );
- end;
-
- Invadd := function( j1, j2, l )
- # addition of two lines of invmat
- local i;
- for i in [1..n] do
- if invmat[i][j2] <> 0 then
- invmat[i][j1] := invmat[i][j1] - l * invmat[i][j2];
- fi;
- od;
- end;
-
- Invmult := function( j1, l )
- # multiply line of invmat
- local i;
- if l <> 1 then
- for i in [1..n] do
- if invmat[i][j1] <> 0 then
- invmat[i][j1] := invmat[i][j1] * l;
- fi;
- od;
- fi;
- end;
-
- Nonzeroset := function( j )
- # entries <> 0 in j-th column
-
- local i, j1;
- nonzero[j] := [];
- j1 := 0;
- for i in [1..m] do
- if solmat[i][j] <> 0 then
- j1 := j1 + 1;
- nonzero[j][j1] := i;
- fi;
- od;
- entries[j] := j1;
- end;
-
- # check input parameters
- if IsCharTable( arg[1] ) then
- tbl := arg[1];
- else
- Error( "first argument must be character-table\n",
- "usage: Decreased( <tbl>, <list of char>,\n",
- "<decomposition-matrix>, [<choice>] )" );
- fi;
- if IsList( arg[2] ) and IsList( arg[2][1] ) then
- y := arg[2];
- else
- Error( "second argument must be list of characters\n",
- "usage: Decreased( <tbl>, <list of char>,\n",
- "<decomposition-matrix>, [<choice>] )" );
- fi;
- if IsList( arg[3] ) and IsList( arg[3][1] ) then
- solmat := Copy( arg[3] );
- else
- Error( "third argument must be decomposition matrix\n",
- "usage: Decreased( <tbl>, <list of char>,\n",
- "<decomposition-matrix>, [<choice>] )" );
- fi;
- if not IsBound( arg[4] ) then
- choice := [];
- for i in [1..Length( y )] do
- choice[i] := i;
- od;
- else
- if IsList( arg[4] ) then
- choice := arg[4];
- else
- Error( "forth argument contains choice of characters\n",
- "usage: Decreased( <tbl>, <list of char>,\n",
- "<decomposition-matrix>, [<choice>] )" );
- fi;
- fi;
-
- # initialisations
- lc := Length( y[1] );
- nc := [];
- for i in [1..lc] do
- nc[i] := 0;
- od;
- columnidx := [];
- lineidx := [];
- nonzero := [];
- entries := [];
- delline := [];
- delcolumn := [];
-
- # number of lines
- m := Length( solmat );
-
- # number of columns
- n := Length( solmat[1] );
- invmat := [];
- for i in [1..n] do
- invmat[i] := [];
- for j in [1..n] do
- invmat[i][j] := 0;
- od;
- od;
- invmat := invmat^0;
- for i in [1..m] do
- delline[i] := false;
- od;
- for j in [1..n] do
- delcolumn[j] := false;
- od;
- i := 1;
-
- # check lines for information
- while i <= m do
- if not delline[i] then
- entries[i] := 0;
- for j in [1..n] do
- if solmat[i][j] <> 0 and not delcolumn[j] then
- entries[i] := entries[i] + 1;
- if entries[i] = 1 then
- nonzero[i] := j;
- fi;
- fi;
- od;
- if entries[i] = 1 then
- delcolumn[nonzero[i]] := true;
- delline[i] := true;
- j := 1;
- while j < i and solmat[j][nonzero[i]] = 0 do
- j := j + 1;
- od;
- if j < i then
- i := j;
- else
- i := i + 1;
- fi;
- else
- if entries[i] = 0 then
- delline[i] := true;
- fi;
- i := i + 1;
- fi;
- else
- i := i + 1;
- fi;
- od;
- Idxset();
-
- deleted := m - Length(lineidx);
- for j in [1..n] do
- Nonzeroset( j );
- od;
- ende1 := false;
- while not ende1 and deleted < m do
- j := 1;
-
- # check solo-entry-columns
- while j <= n do
- if entries[j] = 1 then
- change := false;
- for jj in [1..n] do
- if (delcolumn[j] and delcolumn[jj])
- or not delcolumn[j] then
- if solmat[nonzero[j][1]][jj] <> 0 and jj <> j then
- change := true;
- kgv := Lcm( solmat[nonzero[j][1]][j],
- solmat[nonzero[j][1]][jj] );
- l1 := kgv / solmat[nonzero[j][1]][jj];
- Invmult( jj, l1 );
- for i1 in [1..Length( nonzero[jj] )] do
- solmat[nonzero[jj][i1]][jj]
- := solmat[nonzero[jj][i1]][jj] * l1;
- od;
- Invadd( jj, j, kgv/solmat[nonzero[j][1]][j] );
- solmat[nonzero[j][1]][jj] := 0;
- Nonzeroset( jj );
- fi;
- fi;
- od;
- if not delline[nonzero[j][1]] then
- delline[nonzero[j][1]] := true;
- delcolumn[j] := true;
- deleted := deleted + 1;
- Idxset();
- fi;
- if change then
- j := 1;
- else
- j := j + 1;
- fi;
- else
- j := j + 1;
- fi;
- od;
-
- # search for Equality-System
- # system : chosen columns
- # components : entries <> 0 in the chosen columns
- dim := 2;
- change := false;
- ende2 := false;
- while dim <= n1 and not ende2 do
- j3 := 1;
- while j3 <= n1 and not ende2 do
- j2 := j3;
- j1 := 0;
- system := [];
- components := [];
- while j2 <= n1 do
- while j2 <= n1 and entries[columnidx[j2]] > dim do
- j2 := j2 + 1;
- od;
- if j2 <= n1 then
- if j1 = 0 then
- j1 := 1;
- system[j1] := columnidx[j2];
- components := Copy( nonzero[columnidx[j2]] );
- else
- ident := Identset( components, nonzero[columnidx[j2]] );
- if dim - Length( components ) >= entries[columnidx[j2]]
- - ident.id then
- j1 := j1 + 1;
- system[j1] := columnidx[j2];
- if ident.id < entries[columnidx[j2]] then
- compo2 := Copy( components );
- components := [];
- i1 := 1;
- i2 := 1;
- i3 := 1;
-
- # append new entries to "components"
- while i1 <= Length( ident.nonid )
- or i2 <= Length( compo2 ) do
- if i1 <= Length( ident.nonid ) then
- if i2 <= Length( compo2 ) then
- if ident.nonid[i1] < compo2[i2] then
- components[i3] := ident.nonid[i1];
- i1 := i1 + 1;
- else
- components[i3] := compo2[i2];
- i2 := i2 + 1;
- fi;
- else
- components[i3] := ident.nonid[i1];
- i1 := i1 + 1;
- fi;
- else
- if i2 <= Length( compo2 ) then
- components[i3] := compo2[i2];
- i2 := i2 + 1;
- fi;
- fi;
- i3 := i3 + 1;
- od;
- fi;
- fi;
- fi;
- j2 := j2 + 1;
- fi;
- od;
-
- # try to solve system with Gauss
- if Length( system ) > 1 then
- for i1 in [1..Length( components )] do
- i2 := 1;
- repeat
- ok := true;
- if solmat[components[i1]][system[i2]] = 0 then
- ok := false;
- else
- for i3 in [1..i1-1] do
- if solmat[components[i3]][system[i2]] <> 0 then
- ok := false;
- fi;
- od;
- fi;
- if not ok then
- i2 := i2 + 1;
- fi;
- until ok or i2 > Length( system );
- if ok then
- for i3 in [1..Length( system )] do
- if i3 <> i2
- and solmat[components[i1]][system[i3]] <> 0 then
- change := true;
- kgv := Lcm( solmat[components[i1]][system[i3]],
- solmat[components[i1]][system[i2]] );
- l2 := kgv / solmat[components[i1]][system[i2]];
- l3 := kgv / solmat[components[i1]][system[i3]];
- for i4 in [1..Length( nonzero[system[i3]] )] do
- solmat[nonzero[system[i3]][i4]][system[i3]]
- := solmat[nonzero[system[i3]][i4]][system[i3]]*l3;
- od;
- Invmult( system[i3], l3 );
- for i4 in [1..Length( nonzero[system[i2]] )] do
- solmat[nonzero[system[i2]][i4]][system[i3]]
- := solmat[nonzero[system[i2]][i4]][system[i3]]
- - solmat[nonzero[system[i2]][i4]][system[i2]]*l2;
- od;
- Invadd( system[i3], system[i2], l2 );
- Nonzeroset( system[i3] );
- if entries[system[i3]] = 0 then
- delcolumn[system[i3]] := true;
- Idxset();
- fi;
- fi;
- od;
- fi;
- od;
-
- # check for columns with only one entry <> 0
- for i1 in [1..Length( system )] do
- if entries[system[i1]] = 1 then
- ende2 := true;
- fi;
- od;
- if not ende2 then
- j3 := j3 + 1;
- fi;
- else
- j3 := j3 + 1;
- fi;
- od;
- dim := dim + 1;
- od;
- if dim > n1 and not change and j3 > n1 then
- ende1 := true;
- fi;
- od;
-
- # check, if
- # the transformation of solmat allows computation of new irreducibles
- remmat := [];
- for i in [1..m] do
- remmat[i] := [];
- delline[i] := true;
- od;
- redcount := 0;
- red := [];
- irred := [];
- j := 1;
- sol := true;
- while j <= n and sol do
-
- # computation of character
- char := Copy( nc );
- for i in [1..n] do
- if invmat[i][j] <> 0 then
- char := char + invmat[i][j] * y[choice[i]];
- fi;
- od;
-
- # probably irreducible ==> has to pass tests
- if entries[j] = 1 then
- if solmat[nonzero[j][1]][j] <> 1 then
- char1 := char/solmat[nonzero[j][1]][j];
- else
- char1 := char;
- fi;
- if char1[1] < 0 then
- char1 := - char1;
- fi;
-
- # is 'char1' real?
- IRS := ForAll( char1, x -> GaloisCyc(x,-1) = x );
-
- # Frobenius Schur indicator
- if IsBound( tbl.powermap ) and IsBound( tbl.powermap[2] ) then
- SFI:= Indicator( tbl, [ char1 ], 2 )[1];
- else
- SFI:= Unknown();
- fi;
- if IsUnknown( SFI ) then
- InfoCharTable2( "#I Decreased: 2nd power map not available ",
- "or not unique,\n",
- "#I no test with 'Indicator'\n" );
- fi;
-
- # test if 'char1' can be an irreducible character
- if ForAny( char1, x -> IsRat(x) and not IsInt(x) )
- or ScalarProduct( tbl, char1, char1 ) <> 1
- or char1[1] = 0
- or ( IsInt( SFI ) and ( ( IRS and AbsInt( SFI ) <> 1 ) or
- ( not IRS and SFI <> 0 ) ) ) then
- InfoCharTable2( "#E Decreased : computation of ",
- Ordinal( Length( irred ) ), " character failed\n" );
- return false;
- else
-
- # irreducible character found
- Add( irred, Copy( char1 ) );
- fi;
- else
-
- # what a pity (!), some reducible character remaining
- if char[1] < 0 then
- char := - char;
- fi;
- if char <> nc then
- redcount := redcount + 1;
- red[redcount] := Copy( char );
- for i in [1..m] do
- remmat[i][redcount] := solmat[i][j];
- if solmat[i][j] <> 0 then
- delline[i] := false;
- fi;
- od;
- fi;
- fi;
- j := j+1;
- od;
- i1 := 0;
- remmat2 := [];
- for i in [1..m] do
- if not delline[i] then
- i1 := i1 + 1;
- remmat2[i1] := remmat[i];
- fi;
- od;
- return rec( irreducibles := irred,
- remainders := red, matrix := remmat2 );
- end;
-
-
- #############################################################################
- ##
- #F OrthogonalEmbeddings( <grammat> [, \"positive\" ] [, <integer> ] )
- ##
- OrthogonalEmbeddings := function( arg )
- local
- # sonstige prozeduren
- Symmatinv,
- # variablen fuer Embed
- maxdim, M, D, s, phi, mult, m, x, t, x2, sumg, sumh,
- f, invg, sol, solcount, out,
- l, g, nullv, i, j, k, n, kgv, a, IdMat, chpo,
- # booleans
- positiv, checkpositiv, checkdim,
- # prozeduren fuer Embed
- comp1, comp2, scp2, multiples, solvevDMtr,
- Dextend, Mextend, inca, rnew,
- deca, algorithm;
-
- Symmatinv := function( b )
- # inverts symmetric matrices
-
- local n, i, j, l, k, c, d, ba, B, kgv, kgv1;
- n := Length( b );
- c := Copy( IdMat );
- d := [];
- B := [];
- kgv1 := 1;
- ba := Copy( IdMat );
- for i in [1..n] do
- k := b[i][i];
- for j in [1..i-1] do
- k := k - c[i][j] * c[i][j] * B[j];
- od;
- B[i] := k;
- for j in [i+1..n] do
- k := b[j][i];
- for l in [1..i-1] do
- k := k - c[i][l] * c[j][l] * B[l];
- od;
- if B[i] <> 0 then
- c[j][i] := k / B[i];
- else
- Error ( "matrix not invertable, ", Ordinal( i ),
- " column is linearly dependent" );
- fi;
- od;
- od;
- if B[n] = 0 then
- Error ( "matrix not invertable, ", Ordinal( i ),
- " column is linearly dependent" );
- fi;
- for i in [1..n-1] do
- for j in [i+1..n] do
- if c[j][i] <> 0 then
- for l in [1..i] do
- ba[j][l] := ba[j][l] - c[j][i] * ba[i][l];
- od;
- fi;
- od;
- od;
- for i in [1..n] do
- for j in [1..i-1] do
- ba[j][i] := ba[i][j];
- ba[i][j] := ba[i][j] / B[i];
- od;
- ba[i][i] := 1/B[i];
- od;
- for i in [1..n] do
- d[i] := [];
- for j in [1..n] do
- if i >= j then
- k := ba[i][j];
- l := i + 1;
- else
- l := j;
- k := 0;
- fi;
- while l <= n do
- k := k + ba[i][l] * ba[l][j];
- l := l + 1;
- od;
- d[i][j] := k;
- kgv1 := Lcm( kgv1, Denominator( k ) );
- od;
- od;
- for i in [1..n] do
- for j in [1..n] do
- d[i][j] := kgv1 * d[i][j];
- od;
- od;
- return rec( inverse := d, enuminator := kgv1 );
- end;
-
- # program embed
-
- comp1 := function( a, b )
- local i;
- if ( a[n+1] < b[n+1] ) then
- return false;
- elif ( a[n+1] > b[n+1] ) then
- return true;
- else
- for i in [ 1 .. n ] do
- if AbsInt( a[i] ) > AbsInt( b[i] ) then
- return true;
- elif AbsInt( a[i] ) < AbsInt( b[i] ) then
- return false;
- fi;
- od;
- fi;
- return false;
- end;
-
- comp2 := function( a, b )
- local i, t;
- t := Length(a)-1;
- if a[t+1] < b[t+1] then
- return true;
- elif a[t+1] > b[t+1] then
- return false;
- else
- for i in [ 1 .. t ] do
- if a[i] < b[i] then
- return false;
- elif a[i] > b[i] then
- return true;
- fi;
- od;
- fi;
- return false;
- end;
-
- scp2 := function( k, l )
- # uses x, invg,
- # changes
- local i, j, sum, sum1;
-
- sum := 0;
- for i in [1..n] do
- sum1 := 0;
- for j in [1..n] do
- sum1 := sum1 + x[k][j] * invg[j][i];
- od;
- sum := sum + sum1 * x[l][i];
- od;
- return sum;
- end;
-
- multiples := function( l )
- # uses m, phi,
- # changes mult, s, k, a, sumh, sumg,
- local v, r, i, j, break;
-
- for j in [1..n] do
- sumh[j] := 0;
- od;
- i := l;
- while i <= t and ( not checkdim or s <= maxdim ) do
- if mult[i] * phi[i][i] < m then
- break := false;
- repeat
- v := solvevDMtr( i );
- if not IsBound( v[1] ) or not IsList( v[1] ) then
- r := rnew( v, i );
- if r >= 0 then
- if r > 0 then
- Dextend( r );
- fi;
- Mextend( v, i );
- a[i] := a[i] + 1;
- else
- break := true;
- fi;
- else
- break := true;
- fi;
- until a[i] * phi[i][i] >= m or ( checkdim and s > maxdim )
- or break;
- mult[i] := a[i];
- while a[i] > 0 do
- s := s - 1;
- if M[s][Length( M[s] )] = 1 then
- k := k -1;
- fi;
- a[i] := a[i] - 1;
- od;
- fi;
- if mult[i] <> 0 then
- for j in [1..n] do
- sumh[j] := sumh[j] + mult[i] * x2[i][j];
- od;
- fi;
- i := i + 1;
- od;
- end;
-
- solvevDMtr := function( l )
- # uses M, D, phi, f,
- # changes
- local M1, M2, i, j, k1, v, sum;
-
- k1 := 1;
- v := [];
- i := 1;
- while i < s do
- sum := 0;
- M1 := Length( M[i] );
- M2 := M[i][M1];
- for j in [1..M1-1] do
- sum := sum + v[j] * M[i][j];
- od;
- if M2 = 1 then
- v[k1] := -( phi[l][f[i]] + sum ) / D[k1];
- k1 := k1 + 1;
- else
- if Denominator( sum ) <> 1
- or Numerator( sum ) <> -phi[l][f[i]] then
- v[1] := [];
- i := s;
- fi;
- fi;
- i := i + 1;
- od;
- return( v );
- end;
-
- inca := function( l )
- # uses x2,
- # changes l, a, sumg, sumh,
- local v, r, break, i;
-
- while l <= t and ( not checkdim or s <= maxdim ) do
- break := false;
- repeat
- v := solvevDMtr( l );
- if not IsBound( v[1] ) or not IsList( v[1] ) then
- r := rnew( v, l );
- if r >= 0 then
- if r > 0 then
- Dextend( r );
- fi;
- Mextend( v, l );
- a[l] := a[l] + 1;
- for i in [1..n] do
- sumg[i] := sumg[i] + x2[l][i];
- od;
- else
- break := true;
- fi;
- else
- break := true;
- fi;
- until a[l] >= mult[l] or ( checkdim and s > maxdim ) or break;
- mult[l] := 0;
- l := l + 1;
- od;
- return l;
- end;
-
- rnew := function( v, l )
- # uses phi, m, k, D,
- # changes v,
- local sum, i;
- sum := m - phi[l][l];
- for i in [1..k-1] do
- sum := sum - v[i] * D[i] * v[i];
- od;
- if sum >= 0 then
- if sum > 0 then
- v[k] := 1;
- else
- v[k] := 0;
- fi;
- fi;
- return sum;
- end;
-
- Mextend := function( line, l )
- # uses D,
- # changes M, s, f,
- local i;
- for i in [1..Length( line )-1] do
- line[i] := line[i] * D[i];
- od;
- M[s] := line;
- f[s] := l;
- s := s + 1;
- end;
-
- Dextend := function( r )
- # uses a,
- # changes k, D,
- D[k] := r;
- k := k + 1;
- end;
-
- deca := function( l )
- # uses x2, t, M,
- # changes l, k, s, a, sumg,
- local i;
- if l <> 1 then
- l := l - 1;
- if l = t - 1 then
- while a[l] > 0 do
- s := s -1;
- if M[s][Length( M[s] )] = 1 then
- k := k - 1;
- fi;
- a[l] := a[l] - 1;
- for i in [1..n] do
- sumg[i] := sumg[i] - x2[l][i];
- od;
- od;
- l := deca( l );
- else
- if a[l] <> 0 then
- s := s - 1;
- if M[s][Length( M[s] )] = 1 then
- k := k - 1;
- fi;
- a[l] := a[l] - 1;
- for i in [1..n] do
- sumg[i] := sumg[i] - x2[l][i];
- od;
- l := l + 1;
- else
- l := deca( l );
- fi;
- fi;
- fi;
- return l;
- end;
-
- # check input
- if not IsList( arg[1] ) or not IsList( arg[1][1] ) then
- Error( "first argument must be symmetric Gram matrix\n",
- "usage : Orthog... ( < gram-matrix > \n",
- " [, <\"positive\"> ] [, < integer > ] )" );
- fi;
- if Length( arg[1] ) <> Length( arg[1][1] ) then
- Error( "number of lines and columns not identic\n",
- "usage : Orthog... ( < gram-matrix >\n",
- " [, <\"positive\"> ] [, < integer > ] )" );
- fi;
- g := Copy ( arg[1] );
- checkpositiv := false;
- checkdim := false;
- chpo := "xxx";
- if IsBound( arg[2] ) then
- if IsString( arg[2] ) then
- chpo := arg[2];
- if arg[2] = "positive" then
- checkpositiv := true;
- fi;
- else
- if IsInt( arg[2] ) then
- maxdim := arg[2];
- checkdim := true;
- else
- Error( "second argument must be string or integer\n",
- "usage : Orthog... ( < gram-matrix >\n",
- " [, <\"positive\"> ] [, < integer > ] )" );
- fi;
- fi;
- fi;
- if IsBound( arg[3] ) then
- if IsString( arg[3] ) then
- chpo := arg[3];
- if arg[3] = "positive" then
- checkpositiv := true;
- fi;
- else
- if IsInt( arg[3] ) then
- maxdim := arg[3];
- checkdim := true;
- else
- Error( "third argument must be string or integer\n",
- "usage : Orthog... ( < gram-matrix >\n",
- " [, <\"positive\"> ] [, < integer > ] )" );
- fi;
- fi;
- fi;
- n := Length( g );
- for i in [1..n] do
- for j in [1..i-1] do
- if g[i][j] <> g[j][i] then
- Error( "matrix not symmetric \n",
- "usage : Orthog... ( < gram-matrix >\n",
- " [, <\"positive\"> ] [, < integer > ] )" );
- fi;
- od;
- od;
-
- # main program
- IdMat := IdentityMat( n );
- invg := Symmatinv( g );
- m := invg.enuminator;
- invg := invg.inverse;
- x := ShortestVectors( invg, m, chpo );
- t := Length(x.vectors);
- for i in [1..t] do
- x.vectors[i][n+1] := x.norms[i];
- od;
- x := x.vectors;
- M := [];
- M[1] := [];
- D := [];
- mult := [];
- sol := [];
- f := [];
- solcount := 0;
- s := 1;
- k := 1;
- l := 1;
- a := [];
- for i in [1..t] do
- a[i] := 0;
- x[i][n+2] := 0;
- mult[i] := 0;
- od;
- sumg := [];
- sumh := [];
- for i in [1..n] do
- sumg[i] := 0;
- sumh[i] := 0;
- od;
- Sort(x,comp1);
- x2 := [];
- for i in [1..t] do
- x2[i] := [];
- for j in [1..n] do
- x2[i][j] := x[i][j] * x[i][j];
- x[i][n+2] := x[i][n+2] + x2[i][j];
- od;
- od;
- phi := [];
- for i in [1..t] do
- phi[i] := [];
- for j in [1..i-1] do
- phi[i][j] := scp2( i, j );
- od;
- phi[i][i] := x[i][n+1];
- od;
- repeat
- multiples( l );
-
- # (former call of 'tracecond')
- if ForAll( [ 1 .. n ], i -> g[i][i] - sumg[i] <= sumh[i] ) then
- l := inca( l );
- if s-k = n then
- solcount := solcount + 1;
- InfoCharTable2("#I OrthogonalEmbeddings: ",
- solcount," solutions found\n");
- sol[solcount] := [];
- for i in [1..t] do
- sol[solcount][i] := a[i];
- od;
- sol[solcount][t+1] := s - 1;
- fi;
- fi;
- l := deca( l );
- until l <= 1;
- out := rec( vectors := [], norms := [], solutions := [] );
- for i in [1..t] do
- out.vectors[i] := [];
- out.norms[i] := x[i][n+1]/m;
- for j in [1..n] do
- out.vectors[i][j] := x[i][j];
- od;
- od;
- Sort( sol, comp2 );
- for i in [1..solcount] do
- out.solutions[i] := [];
- for j in [1..t] do
- for k in [1..sol[i][j]] do
- Add( out.solutions[i], j );
- od;
- od;
- od;
- return out;
- end;
-
-
- #############################################################################
- ##
- #F OrthogonalEmbeddingsSpecialDimension( <tbl>, <reducibles>, <grammat>,
- #F [, \"positive\" ], <integer> )
- ##
- OrthogonalEmbeddingsSpecialDimension := function ( arg )
- local red, dim, reducibles, matrix, tbl, emb, dec, i, s, irred;
- # check input
- if Length( arg ) < 4 then
- Error( "please specify desired dimension\n",
- "usage : Orthog...( <tbl>, <reducibles>,\n",
- "<gram-matrix>, [, \"positive\" ], <integer> )" );
- fi;
- if IsInt( arg[4] ) then
- dim := arg[4];
- else
- if IsBound( arg[5] ) then
- if IsInt( arg[5] ) then
- dim := arg[5];
- else
- Error( "please specify desired dimension\n",
- "usage : Orthog...( <tbl>, < reducibles >,\n",
- "< gram-matrix >, [, <\"positive\"> ], < integer > )" );
- fi;
- fi;
- fi;
- tbl := arg[1];
- reducibles := arg[2];
- if Length( arg ) = 4 then
- emb := OrthogonalEmbeddings( arg[3], arg[4] );
- else
- emb := OrthogonalEmbeddings( arg[3], arg[4], arg[5] );
- fi;
- s := [];
- for i in [1..Length(emb.solutions)] do
- if Length( emb.solutions[i] ) = dim then
- Add( s, Sublist( emb.vectors, emb.solutions[i] ) );
- fi;
- od;
- dec:= List( s, x -> Decreased( tbl, reducibles, x ) );
- dec:= Filtered( dec, x -> x <> false );
- if dec = [] then
- InfoCharTable2( "#I OrthogonalE...: no embedding",
- " corresp. to characters\n" );
- return rec( irreducibles:= [], remainders:= reducibles );
- fi;
- irred:= Set( dec[1].irreducibles );
- for i in [2..Length(dec)] do
- IntersectSet( irred, dec[i].irreducibles );
- od;
- red:= Reduced( tbl, irred, reducibles );
- Append( irred, red.irreducibles );
- return rec( irreducibles:= irred, remainders:= red.remainders );
- end;
-
-
- #############################################################################
- ##
- #F DnLattice( <tbl>, <g1>, <y1> )
- ##
- DnLattice := function( tbl, g1, y1 )
- local
- # indices
- i, i1, j, j1, k, k1, l, next,
- # booleans
- empty, change, used, addable, SFIbool,
- # dimensions
- m, n,
- # help fields
- found, foundpos,
- z, zw, nullcount, nullgenerate,
- maxentry, max, ind, irred, irredcount, red,
- blockcount, blocks, perm, addtest, preirred,
- # Gram matrix
- g, gblock,
- # characters
- y, y2,
- # variables for recursion
- root, rootcount, solution, ligants, ligantscount, glblock, begin,
- depth, choice, ende, sol,
- # functions
- callreduced, nullset, maxset, Search, Add, DnSearch, test;
-
- # counts zeroes in given line
- nullset := function( g, i )
- local j;
-
- nullcount[ i ] := 0;
- for j in [ 1..n ] do
- if g[ j ] = 0 then
- nullcount[ i ] := nullcount[ i ] + 1;
- fi;
- od;
- end;
-
- # searches line with most non-zero-entries
- maxset := function( )
- local i;
-
- maxentry := 1;
- max := n;
- for i in [ 1..n ] do
- if nullcount[ i ] < max then
- max := nullcount[ i ];
- maxentry := i;
- fi;
- od;
- end;
-
- # searches lines to add in order to produce zeroes
- Search := function( j )
- local signum;
-
- nullgenerate := 0;
- if g[ j ][ maxentry ] > 0 then
- signum := -1;
- for k in [ 1..n ] do
- if k <> maxentry and k <> j then
- if g[ maxentry ][ k ] <> 0 then
- if g[ j ][ k ] = g[ maxentry ][ k ] then
- nullgenerate := nullgenerate + 1;
- else
- nullgenerate := nullgenerate - 1;
- fi;
- fi;
- fi;
- od;
- else
- if g[ j ][ maxentry ] < 0 then
- signum := 1;
- for k in [ 1..n ] do
- if k <> maxentry and k <> j then
- if g[ maxentry ][ k ] <> 0 then
- if g[ j ][ k ] = -g[ maxentry ][ k ] then
- nullgenerate := nullgenerate + 1;
- else
- nullgenerate := nullgenerate - 1;
- fi;
- fi;
- fi;
- od;
- fi;
- fi;
- if nullgenerate > 0 then
- change := true;
- Add( j, maxentry );
- j := j + 1;
- fi;
- end;
-
- # adds two lines/columns
- Add := function( i, j )
- local k;
-
- y[ i ] := y[ i ] - g[ i ][ j ] * y[ j ];
- g[ i ] := g[ i ] - g[ i ][ j ] * g[ j ];
- for k in [ 1..i-1 ] do
- g[ k ][ i ] := g[ i ][ k ];
- od;
- g[ i ][ i ] := 2;
- for k in [ i+1..n ] do
- g[ k ][ i ] := g[ i ][ k ];
- od;
- end;
-
- # backtrack-search for dn-lattice
- DnSearch := function( begin, depth, oldchoice )
- local connections, connect, i1, j1, choice, found;
-
- choice := Copy( oldchoice );
- if depth = 3 then
- # d4-lattice found !!!
- solution := 1;
- ende := true;
- if n > 4 then
- i1 := 0;
- found := false;
- while not found and i1 < n do
- i1 := i1 + 1;
- if i1 <> root[ j ] and i1 <> choice[ 1 ]
- and i1 <> choice[ 2 ] and i1 <> choice[ 3 ] then
- connections := 0;
- for j1 in [1..3] do
- if gblock[ i1 ][ choice[ j1 ] ] <> 0 then
- connections := connections + 1;
- connect := choice[ j1 ];
- fi;
- od;
- if connections = 1 then
- found := true;
- choice[ 4 ] := connect;
- solution := solution + 1;
- fi;
- fi;
- i1 := i1 + 1;
- od;
- fi;
- sol := choice;
- else
- i1 := begin;
- while not ende and i1 <= ligantscount do
- found := true;
- for j1 in [1..depth] do
- if gblock[ ligants[ i1 ] ][ choice[ j1 ] ] <> 0 then
- found := false;
- fi;
- od;
- if found then
- depth := depth + 1;
- choice[ depth ] := ligants[ i1 ];
- DnSearch( i1 + 1, depth, choice );
- depth := depth - 1;
- else
- i1 := i1 + 1;
- fi;
- if ligantscount - i1 + 1 + depth < 3 then
- ende := true;
- fi;
- od;
- fi;
- end;
-
- test := function(z)
- # some tests for the found characters
- local result, IRS, SFI, i1, y1, ind, testchar;
- testchar := Copy( z )/2;
- result := true;
- IRS := ForAll( testchar, x -> GaloisCyc(x,-1) = x );
- if IsBound( tbl.powermap ) and IsBound( tbl.powermap[2] ) then
- if IsList( tbl.powermap[2] ) and
- ForAll( tbl.powermap[2], IsInt ) then
- SFI := Indicator( tbl, [testchar], 2 )[1];
- SFIbool := true;
- else
- InfoCharTable2
- ("#I DnLattice: 2nd power map not available or not unique,\n",
- "#I cannot test with Indicator\n");
- SFIbool := false;
- fi;
- else
- InfoCharTable2
- ("#I DnLattice: 2nd power map not availabe\n",
- "#I cannot test with Indicator\n");
- SFIbool := false;
- fi;
- if SFIbool then
- if ForAny( testchar, x -> IsRat(x) and not IsInt(x) )
- or ScalarProduct( tbl, testchar, testchar ) <> 1
- or testchar[1] = 0
- or ( IRS and AbsInt( SFI ) <> 1 )
- or ( not IRS and SFI <> 0 ) then
- result := false;
- fi;
- else
- if ForAny( testchar, x -> IsRat(x) and not IsInt(x) )
- or ScalarProduct( tbl, testchar, testchar ) <> 1
- or testchar[1] = 0 then
- result := false;
- fi;
- fi;
- return result;
- end;
-
- # reduce whole lattice with the found irreducible
- callreduced := function()
- z[ 1 ] := z[ 1 ]/ 2 ;
- if ScalarProduct( tbl, z[ 1 ], z[ 1 ] ) = 1 then
- irredcount := irredcount + 1;
- if z[ 1 ][ 1 ] > 0 then
- irred[ irredcount ] := z[ 1 ];
- else
- irred[ irredcount ] := -z[ 1 ];
- fi;
- y1 := Sublist( y, [ blocks.begin[i] .. blocks.ende[i] ] );
- red := Reduced( tbl, z, y1 );
- irred := Concatenation( irred, red.irreducibles );
- irredcount := Length( irred );
- y2 := Concatenation( y2, red.remainders );
- fi;
- end;
-
- # check input parameters
- if not IsCharTable( tbl ) then
- Error( "first argument must be character-table\n",
- "usage: DnLattice( <tbl>, <gram-matrix>, <reducibles> )" );
- fi;
- empty := false;
- if g1 <> [] then
- if IsList( g1 ) and IsBound( g1[1] ) and IsList( g1[1] ) then
- g := Copy( g1 );
- else
- Error( "second argument must be Gram matrix of reducible characters\n",
- "usage: DnLattice( <tbl>, <grammat>, <reducibles> )" );
- fi;
- else
- empty := true;
- fi;
- if y1 <> [] then
- if IsList( y1 ) and IsBound( y1[1] ) and IsList( y1[1] ) then
- y := Copy( y1 );
- else
- Error( "third argument must be list of reducible characters\n",
- "usage: DnLattice( <tbl>, <gram-matrix>, <reducibles> )" );
- fi;
- else
- empty := true;
- fi;
- y2 := [ ];
- irred := [ ];
-
- if not empty then
-
- n := Length( y );
- for i in [1..n] do
- if g[i][i] <> 2 then
- Error( "reducible characters don't have norm 2\n",
- "usage: DnLattice( <tbl>, <gram-matrix>, <reducibles> )" );
- fi;
- od;
- # initialisations
- z := [ ];
- used := [ ];
- next := [ ];
- nullcount := [ ];
- m := Length( y[ 1 ] );
- for i in [1..n] do
- used[i] := false;
- od;
- blocks := rec( begin := [ ], ende := [ ] );
- blockcount := 0;
- irredcount := 0;
- change := true;
- while change do
- change := false;
- for i in [ 1..n ] do
- nullset( g[ i ], i );
- od;
- maxset( );
- while max < n-2 and not change do
- while maxentry <= n and not change do
- if nullcount[ maxentry ] <> max then
- maxentry := maxentry + 1;
- else
- j := 1;
- while j < maxentry and not change do
- Search( j );
- j := j + 1;
- od;
- j := maxentry + 1;
- while j <= n and not change do
- Search( j );
- j := j + 1;
- od;
- if not change then
- maxentry := maxentry + 1;
- fi;
- fi;
- od;
- if not change then
- max := max + 1;
- maxentry := 1;
- fi;
- od;
-
- # 2 step-search in order to produce zeroes
- # 2_0_Box-Method
- change := false;
- i := 1;
- while i <= n and not change do
- while i <= n and nullcount[ i ] > n-3 do
- i := i + 1;
- od;
- if i <= n then
- j := 1;
- while j <= n and not change do
- while j <= n and g[ i ][ j ] <> 0 do
- j := j + 1;
- od;
- if j <= n then
- i1 := 1;
- while i1 <= n and not change do
- while i1 <= n
- and ( i1 = i or i1 = j or g[ i1 ][ j ] = 0 ) do
- i1 := i1 + 1;
- od;
- if i1 <= n then
- addtest := g[ i ] - g[ i ][ i1 ] * g[ i1 ];
- nullgenerate := 0;
- addable := true;
- for k in [ 1..n ] do
- if addtest[ k ] = 0 then
- nullgenerate := nullgenerate + 1;
- else
- if AbsInt( addtest[ k ] ) > 1 then
- addable := false;
- fi;
- fi;
- od;
- if addable then
- nullgenerate := nullgenerate - nullcount[ i ];
- for k in [ 1..n ] do
- if k <> i and k <> j then
- if addtest[ k ]
- = addtest[ j ] * g[ j ][ k ] then
- if g[ j ][ k ] <> 0 then
- nullgenerate := nullgenerate + 1;
- fi;
- else
- if addtest[ k ] <> 0 then
- if g[ j ][ k ] = 0 then
- nullgenerate := nullgenerate - 1;
- else
- addable := false;
- fi;
- fi;
- fi;
- fi;
- od;
- if nullgenerate > 0 and addable then
- Add( i, i1 );
- Add( j, i );
- change := true;
- fi;
- fi;
- i1 := i1 + 1;
- fi;
- od;
- j := j + 1;
- fi;
- od;
- i := i + 1;
- fi;
- od;
- od;
- i := 1;
- j := 0;
- next[ 1 ] := 1;
- while j < n do
- blockcount := blockcount + 1;
- blocks.begin[ blockcount ] := i;
- l := 0;
- used[ next [ i ] ] := true;
- j := j + 1;
- y2[ j ] := y[ next [ i ] ];
- while l >= 0 do
- for k in [ 1..n ] do
- if g[ next[ i ] ][ k ] <> 0 and not used[ k ] then
- l := l + 1;
- next[ i + l ] := k;
- j := j + 1;
- y2[ j ] := y[ k ];
- used[ k ] := true;
- fi;
- od;
- i := i + 1;
- l := l - 1;
- od;
- blocks.ende[ blockcount ] := i - 1;
- k := 1;
- while k <= n and used[ k ] do
- k := k + 1;
- od;
- if k <= n then
- next[i] := k;
- fi;
- od;
- perm := PermList( next )^-1;
- for i in [1..n] do
- g[i] := Permuted( g[i], perm );
- od;
- g := Permuted( g, perm );
- y := y2;
- y2 := [ ];
-
- # search for d4/d5 - lattice
- for i in [1..blockcount] do
- n := blocks.ende[ i ] - blocks.begin[ i ] + 1;
- solution := 0;
- if n >= 4 then
- gblock := [ ];
- j1 := 0;
- for j in [ blocks.begin[ i ]..blocks.ende[ i ] ] do
- j1 := j1 + 1;
- gblock[ j1 ] := [ ];
- k1 := 0;
- for k in [ blocks.begin[ i ]..blocks.ende[ i ] ] do
- k1 := k1 + 1;
- gblock[ j1 ][ k1 ] := g[ j ][ k ];
- od;
- od;
- root := [ ];
- rootcount := 0;
- for j in [1..n] do
- nullset( gblock[ j ], j );
- if nullcount[ j ] < n - 3 then
- rootcount := rootcount + 1;
- root[ rootcount ] := j;
- fi;
- od;
- j := 1;
- while solution = 0 and j <= rootcount do
- ligants := [ ];
- ligantscount := 0;
- for k in [1..n] do
- if k <> root[ j ] and gblock[ root[ j ] ][ k ] <> 0 then
- ligantscount := ligantscount + 1;
- ligants[ ligantscount ] := k;
- fi;
- od;
- begin := 1;
- depth := 0;
- choice := [ ];
- ende := false;
- DnSearch( begin, depth, choice );
- if solution > 0 then
- choice := sol;
- fi;
- j := j + 1;
- od;
- fi;
-
- # test of the found irreducibles
- if solution = 1 then
- # treatment of D4-lattice
- found := 0;
- preirred := Sublist( y, [ blocks.begin[i] .. blocks.ende[i] ] );
- z[1] := preirred[choice[1]] + preirred[choice[2]];
- if test(z[1]) then
- red := Reduced( tbl, preirred, [ z[1] ] );
- if ForAll( red.irreducibles, test ) then
- found := found + 1;
- foundpos := 1;
- fi;
- fi;
- z[2] := preirred[choice[1]] + preirred[choice[3]];
- if test(z[2]) then
- red := Reduced( tbl, preirred, [ z[2] ] );
- if ForAll( red.irreducibles, test ) then
- found := found + 1;
- foundpos := 2;
- fi;
- fi;
- z[3] := preirred[choice[2]] + preirred[choice[3]];
- if test(z[3]) then
- red := Reduced( tbl, preirred, [ z[3] ] );
- if ForAll( red.irreducibles, test ) then
- found := found + 1;
- foundpos := 3;
- fi;
- fi;
- if found = 1 then
- z := [z[foundpos]];
- callreduced();
- fi;
-
- else
- # treatment of D5-lattice
- if solution = 2 then
- if choice [ 1 ] <> choice [ 4 ] then
- z[ 1 ] := y[ blocks.begin[ i ] + choice[ 1 ] - 1 ];
- if choice [ 2 ] <> choice [ 4 ] then
- z[ 1 ]
- := z[ 1 ] + y[ blocks.begin[ i ] + choice[ 2 ] - 1 ];
- else
- z[ 1 ]
- := z[ 1 ] + y[ blocks.begin[ i ] + choice[ 3 ] - 1 ];
- fi;
- else
- z[ 1 ] := y[ blocks.begin[ i ] + choice[ 2 ] - 1 ]
- + y[ blocks.begin[ i ] + choice[ 3 ] - 1 ];
- fi;
- found := 0;
- if test(z[1]) then
- callreduced();
- fi;
- else
- Append( y2, Sublist( y, [ blocks.begin[i] .. blocks.ende[i] ] ) );
- fi;
- fi;
- od;
-
- if irredcount > 0 then
- g := MatScalarProducts( tbl, y2, y2 );
- fi;
- else
- # input was empty i.e. empty=true
- g := [];
- fi;
- return rec( gram:=g, remainders:=y2, irreducibles:=irred );
- end;
-
-
- #############################################################################
- ##
- #F DnLatticeIterative( <tbl>, <red> )
- ##
- DnLatticeIterative := function( tbl, red )
- local dnlat, red1, norms, i, reduc, irred, norm2, g;
-
- # check input parameters
- if not IsCharTable( tbl ) then
- Error( "first argument must be character-table\n",
- "usage: DnLatticeIterative( <tbl>, <record or list> )" );
- fi;
- if not IsRec( red ) and not IsList( red ) then
- Error( "second argument must be record or list\n",
- "usage: DnLatticeIterative( <tbl>, <record or list> )" );
- fi;
- if IsRec( red ) and not IsBound( red.remainders ) then
- Error( "second record must contain a field 'remainders'\n",
- "usage: DnLatticeIterative( <tbl>, <record or list> )" );
- fi;
- if not IsRec( red ) then
- red := rec( remainders:=red );
- fi;
- if not IsBound( red.norms ) then
- norms := List( red.remainders, x -> ScalarProduct( tbl, x, x ) );
- else
- norms := Copy( red.norms );
- fi;
- reduc := Copy( red.remainders );
- irred := [];
- repeat
- norm2 := [];
- for i in [1..Length( reduc )] do
- if norms[i] = 2 then
- Add( norm2, reduc[i] );
- fi;
- od;
- g := MatScalarProducts( tbl, norm2, norm2 );
- dnlat := DnLattice( tbl, g, norm2 );
- Append( irred, dnlat.irreducibles );
- red1:= Reduced( tbl, dnlat.irreducibles, reduc );
- reduc := red1.remainders;
- Append( irred, red1.irreducibles );
- norms:= List( reduc, x -> ScalarProduct( tbl, x, x ) );
- until dnlat.irreducibles=[] and red1.irreducibles=[];
- return rec( irreducibles:=irred, remainders:=reduc , norms := norms );
- end;
-
-