@@ -70,164 +70,46 @@ local f, d1, d2, e, z, g1, g2, r, b, n, a, gp, i, j, k;
7070end );
7171
7272
73- # the following code is essentially due to Michael Smith
73+ BindGlobal(" SMTX_AddEqns" , function (eqns, newmat )
74+ local newrow;
7475
75- # These routines are designed to accumulate a system of linear equations
76- #
77- # M_1 X = V_1, M_2 X = V_2 ... M_t X = V_t
78- #
79- # Where each M_i is an m_i*n matrix, X is the unknown length n vector, and
80- # each V is an length m_i vector. The equations can be added as each batch
81- # is calculated. Here is some pseudo-code to demonstrate:
82- #
83- # eqns := newEqns (n, field);
84- # i := 1;
85- # repeat
86- # <calculate M_i and V_i>
87- # addEqns(M_i, V_i)
88- # increment i;
89- # until i > t or eqns.failed;
90- # if not eqns.failed then
91- # S := solveEqns(eqns);
92- # fi;
93- #
94- # As demonstrated by the example, an early notification of failure is
95- # available by checking ".failed". All new equations are sifted with respect
96- # to the current set, and only added if they are independent of the current
97- # set. If a new equation reduces to the zero row and a nonzero vector
98- # entry, then there is no solution and this is immediately returned by
99- # setting eqns.failed to true. The function solveEqns has an already
100- # triangulised system of equations, so it simply reduces above the pivots
101- # and returns the solution vector.
102-
103-
104- BindGlobal(" SMTX_AddEqns" ,function ( eqns, newmat, newvec )
105- local n, weights, mat, vec, ReduceRow, t,
106- newweight, newrow, newrhs, i, l, k;
107-
108- # Add a bunch of equations to the system of equations in <eqns>. Each
109- # row of <newmat> is the left-hand side of a new equation, and the
110- # corresponding row of <newvec> the right-hand side. Each equation in
111- # filtered against the current echelonised system stored in <eqns> and
112- # then added if it is independent of the system. As soon as a
113- # left-hand side reduces to 0 with a non-zero right-hand side, the flag
114- # <eqns.failed> is set.
115-
116- Info (InfoMtxHom,6 ," addEqns: entering" );
117-
118- n := eqns.dim;
119- weights := eqns.weights;
120- mat := eqns.mat;
121- vec := eqns.vec;
122-
123- # reduce the (lhs,rhs) against the semi-echelonised current matrix,
124- # and return either: (1) the reduced rhs if the lhs reduces to zero,
125- # or (2) a list containing the new echelon weight, the new row and
126- # the new rhs for the system, and the row number that this
127- # equation should placed.
128- ReduceRow := function (lhs, rhs )
129- local lead, i, z;
130- lead := PositionNonZero(lhs);
131- Assert (0 , n = Length(lhs));
132- if lead > n then
133- return rhs;
134- fi ;
135- lhs := ShallowCopy(lhs);
136- for i in [ 1 .. Length(weights)] do
137- if weights[ i] = lead then
138- z := lhs[ lead] ;
139- AddVector(lhs, mat[ i] , - z); # lhs is a vector
140- rhs := rhs - z * vec[ i] ; # rhs is a scalar
141- lead := PositionNonZero(lhs, lead);
142- if lead > n then
143- return rhs;
144- fi ;
145- elif weights[ i] > lead then
146- return [ lead, lhs, rhs, i] ;
147- fi ;
148- od ;
149- return [ lead, lhs, rhs, Length(weights)+ 1 ] ;
150- end ;
151-
152- for k in [ 1 .. Length(newmat)] do
153- t := ReduceRow(newmat[ k] , newvec[ k] );
154-
155- if IsList(t) then
156- # new equation
157- newweight := t[ 1 ] ;
158- newrow := t[ 2 ] ;
159- newrhs := t[ 3 ] ;
160- i := t[ 4 ] ; # position for new row
161-
162- # normalise so that leading entry is 1
163- newrhs := newrhs / newrow[ newweight] ;
164- newrow := newrow / newrow[ newweight] ; # NB: in this order
165-
166- if i = Length(mat)+ 1 then
167- # add new equation to end of list
168- Add(mat, newrow);
169- Add(vec, newrhs);
170- Add(weights, newweight);
171- else
172- l := Length(mat);
173- # move down other rows to make space for this new one...
174- mat{[ i+ 1 .. l+ 1 ]} := mat{[ i.. l]} ;
175- vec{[ i+ 1 .. l+ 1 ]} := vec{[ i.. l]} ;
176- # and then slot it in
177- mat[ i] := newrow;
178- vec[ i] := newrhs;
179- weights{[ i+ 1 .. l+ 1 ]} := weights{[ i.. l]} ;
180- weights[ i] := newweight;
181- fi ;
76+ Info (InfoMtxHom,6 ," addEqns: entering (n = " , eqns.dim, " , rank = " , NrBasisVectors(eqns.mb), " )" );
18277
183- else
184- # no new equation, check whether inconsistent due to
185- # nonzero rhs reduction
186-
187- if not IsZero(t) then
188- Info (InfoMtxHom,6 ," addEqns: FAIL!" );
189- eqns.failed := true ;
190- return eqns; # return immediately
191- fi ;
192- fi ;
78+ # reduce each row of newmat against the semi-echelonised current matrix;
79+ # if we find any new pivots, insert them
80+ for newrow in newmat do
81+ CloseMutableBasis(eqns.mb, newrow);
19382 od ;
19483end );
19584
19685BindGlobal(" SMTX_NewEqns" ,function (dim, field )
19786 return rec (
19887 dim := dim, # number of variables
19988 field := field, # field over which the equation hold
200- mat := [] , # left-hand sides of system
201- weights := [] , # echelon weights for lhs matrix
202- vec := [] , # right-hand sides of system
203- failed := false , # flag to indicate inconsistent system
204- index := [] , # index for row ordering
89+ mb := MutableBasis(field, [] , ZeroVector(field, dim)),
20590 );
20691end );
20792
20893BindGlobal(" SMTX_KillAbovePivotsEqns" ,function (eqns )
20994# Eliminate entries above pivots. Note that the pivot entries are
21095# all 1 courtesy of SMTX_AddEqns.
21196
212- local m, n, zero, i, c, j, factor;
97+ local m, i, c, j, factor;
21398
21499 Info (InfoMtxHom,6 ," killAbovePivotsEqns: entering" );
100+
215101 m := Length(eqns.mat);
216- n := eqns.dim;
217- if m > 0 then
218- zero := Zero(eqns.field);
219- for i in [ 1 .. m] do
220- c := eqns.weights[ i] ;
221- for j in [ 1 .. i- 1 ] do
222- factor := eqns.mat[ j,c] ;
223- if factor <> zero then
224- Info (InfoMtxHom,6 ," solveEqns: kill mat[" ,j," ," ,c," ]" );
225- AddVector(eqns.mat[ j] , eqns.mat[ i] , - factor);
226- eqns.vec[ j] := eqns.vec[ j] - factor* eqns.vec[ i] ;
227- fi ;
228- od ;
102+ for i in [ 1 .. m] do
103+ c := eqns.pivots[ i] ;
104+ Assert (0 , IsOne(eqns.mat[ i,c] ));
105+ for j in [ 1 .. i- 1 ] do
106+ factor := eqns.mat[ j,c] ;
107+ if not IsZero(factor) then
108+ Info (InfoMtxHom,6 ," solveEqns: kill mat[" ,j," ," ,c," ]" );
109+ AddVector(eqns.mat[ j] , eqns.mat[ i] , - factor);
110+ fi ;
229111 od ;
230- fi ;
112+ od ;
231113 Info (InfoMtxHom,6 ," killAbovePivotsEqns: leaving" );
232114end );
233115
@@ -243,6 +125,11 @@ BindGlobal("SMTX_NullspaceEqns",function(e)
243125
244126local mat, n, one, zerovec, i, k, nullspace, row;
245127
128+ # HACK: convert MutableBasis into the "old" format expected by this code
129+ e.mat := ShallowCopy(e.mb!. basisVectors);
130+ e.pivots := List(e.mat, PositionNonZero);
131+ SortParallel(e.pivots, e.mat);
132+
246133 SMTX_KillAbovePivotsEqns(e);
247134 mat := e.mat;
248135
@@ -624,10 +511,11 @@ end);
624511BindGlobal(" SpinHom" ,function (V, W )
625512local nv, nw, F, zero, minusone, zeroW, gV, gW, k, U, echu, r, homs, s, work, ans, v0,
626513 M, x, pos, z, echm, t, v, echv, a, u, e, start, oldlen, ag, m, uu, ret,
627- c, s1, X, mat, uuc, uic, newhoms, hom, Uhom, imv0, imv0c, image, i, j, l;
514+ c, s1, X, mat, uuc, uic, newhoms, hom, Uhom, imv0, imv0c, image, i, j, l,
515+ nullspace, nullspace_row;
628516
629517# Compute Hom(V,W) for G-modules <V> and <W>. The algorithm starts with
630- # the trivial submodule <U> of <V> for which Hom(U,V ) is trivial. It
518+ # the trivial submodule <U> of <V> for which Hom(U,W ) is trivial. It
631519# then computes Hom(U',W) for U' a submodule generated by <U> and a
632520# single element <v0> in <V>. This U' becomes the next <U> as the process
633521# is iterated, ending when <U'> = <V>. The element <v0> is chosen in a
@@ -820,7 +708,7 @@ local nv, nw, F, zero, minusone, zeroW, gV, gW, k, U, echu, r, homs, s, work, an
820708 od ;
821709 Append(mat, X);
822710 ConvertToMatrixRep(mat);
823- SMTX_AddEqns(e, TransposedMat(mat), zeroW );
711+ SMTX_AddEqns(e, TransposedMat(mat));
824712 fi ;
825713 od ;
826714 od ;
@@ -833,15 +721,14 @@ local nv, nw, F, zero, minusone, zeroW, gV, gW, k, U, echu, r, homs, s, work, an
833721 until oldlen = Length(v);
834722
835723 # we have the system of equations, so find its solution space
836-
837- ans:= SMTX_NullspaceEqns(e);
724+ nullspace:= SMTX_NullspaceEqns(e);
838725
839726 # Now build the homomorphisms
840727
841728 newhoms:= [] ;
842- for i in [ 1 .. Length(ans) ] do
729+ for nullspace_row in nullspace do
843730
844- # Each row of ans is of the form:
731+ # Each row of nullspace is of the form:
845732 #
846733 # [ b_1, b_2, ..., b_s, c_1, c_2, ..., c_t ]
847734 #
@@ -853,8 +740,8 @@ local nv, nw, F, zero, minusone, zeroW, gV, gW, k, U, echu, r, homs, s, work, an
853740 Uhom:= NullMat(r, nw, F);
854741 ConvertToMatrixRep(Uhom, F);
855742 for l in [ 1 .. s] do
856- if ans [ i ] [ l] <> zero then
857- AddMatrix(Uhom, homs[ l] , ans [ i ] [ l] );
743+ if nullspace_row [ l] <> zero then
744+ AddMatrix(Uhom, homs[ l] , nullspace_row [ l] );
858745 fi ;
859746 od ;
860747 for l in [ 1 .. r] do
@@ -864,8 +751,8 @@ local nv, nw, F, zero, minusone, zeroW, gV, gW, k, U, echu, r, homs, s, work, an
864751
865752 imv0:= ZeroMutable(zeroW);
866753 for l in [ 1 .. t] do
867- if ans [ i ] [ s+ l] <> zero then
868- AddVector(imv0, M[ l] , ans [ i ] [ s+ l] );
754+ if nullspace_row [ s+ l] <> zero then
755+ AddVector(imv0, M[ l] , nullspace_row [ s+ l] );
869756 fi ;
870757 od ;
871758 imv0c:= EchResidueCoeffs(M, echm, imv0,1 );
0 commit comments