[8bb77b] | 1 | // Last change 10.12.2000 (TB) |
---|
[4e461ff] | 2 | /////////////////////////////////////////////////////////////////////////////// |
---|
[8bb77b] | 3 | version="$Id: rinvar.lib,v 1.5 2000-12-22 14:43:04 greuel Exp $"; |
---|
[fd3fb7] | 4 | category="Invariant theory"; |
---|
[4e461ff] | 5 | info=" |
---|
[8bb77b] | 6 | LIBRARY: rinvar.lib Invariant Rings of Reductive Groups |
---|
| 7 | AUTHOR: Thomas Bayer, tbayer@in.tum.de |
---|
| 8 | http://wwwmayr.informatik.tu-muenchen.de/personen/bayert/ |
---|
| 9 | Current Adress: Institut fuer Informatik, TU Muenchen |
---|
| 10 | OVERVIEW: |
---|
| 11 | Implementation based on Derksen's algorithm. Written in the frame of the |
---|
| 12 | diploma thesis (advisor: Prof. Gert-Martin Greuel) 'Computations of moduli |
---|
| 13 | spaces of semiquasihomogenous singularities and an implementation in Singular' |
---|
[4e461ff] | 14 | |
---|
| 15 | PROCEDURES: |
---|
[8bb77b] | 16 | HilbertSeries(I, w); Hilbert series of the ideal I w.r.t. weight w |
---|
| 17 | HilbertWeights(I, w); weighted degrees of the generators of I |
---|
| 18 | ImageVariety(I, F); ideal of the image variety F(variety(I)) |
---|
| 19 | ImageGroup(G, F); ideal of G w.r.t. the induced representation |
---|
| 20 | InvariantRing(G, Gaction); generators of the invariant ring of G |
---|
| 21 | InvariantQ(f, G, Gaction); decide if f is invariant w.r.t. G |
---|
| 22 | LinearizeAction(G, Gaction); linearization of the action 'Gaction' of G |
---|
| 23 | LinearActionQ(action,s,t); decide if action is linear in var(s..nvars) |
---|
| 24 | LinearCombinationQ(base, f); decide if f is in the linear hull of 'base' |
---|
| 25 | MinimalDecomposition(f,s,t); minimal decomposition of f (like coef) |
---|
| 26 | NullCone(G, act); ideal of the nullcone of the action 'act' of G |
---|
| 27 | ReynoldsImage(RO,f); image of f under the Reynolds operator 'RO' |
---|
| 28 | ReynoldsOperator(G, Gaction); Reynolds operator of the group G |
---|
| 29 | SimplifyIdeal(I[,m,s]); simplify the ideal I (try to reduce variables) |
---|
| 30 | TransferIdeal(R,name,nA); transfer the ideal 'name' from R to basering |
---|
| 31 | |
---|
| 32 | SEE ALSO: qhmoduli.lib, zeroset.lib |
---|
[4e461ff] | 33 | "; |
---|
| 34 | |
---|
| 35 | LIB "presolve.lib"; |
---|
| 36 | LIB "elim.lib"; |
---|
| 37 | LIB "zeroset.lib"; |
---|
| 38 | |
---|
| 39 | /////////////////////////////////////////////////////////////////////////////// |
---|
| 40 | |
---|
| 41 | proc EquationsOfEmbedding(ideal embedding, int nrs) |
---|
| 42 | "USAGE: EquationsOfEmbedding(embedding, s); ideal embedding; int s; |
---|
[8bb77b] | 43 | PUROPSE: compute the ideal of the variety parameterized by 'embedding' by |
---|
[4e461ff] | 44 | implicitation and change the variables to the old ones. |
---|
| 45 | RETURN: ideal |
---|
| 46 | ASSUME: nvars(basering) = n, size(embedding) = r and s = n - r. |
---|
| 47 | The polynomials of embedding contain only var(s + 1 .. n). |
---|
| 48 | NOTE: the result is the Zariski closure of the parameterized variety |
---|
| 49 | EXAMPLE: example EquationsOfEmbedding; shows an example |
---|
| 50 | " |
---|
| 51 | { |
---|
| 52 | ideal tvars; |
---|
| 53 | |
---|
| 54 | for(int i = nrs + 1; i <= nvars(basering); i++) { tvars[i - nrs] = var(i); } |
---|
| 55 | |
---|
| 56 | def RE1 = ImageVariety(ideal(0), embedding); // implicitation of the parameterization |
---|
| 57 | // map F = RE1, tvars; |
---|
| 58 | map F = RE1, maxideal(1); |
---|
| 59 | return(F(imageid)); |
---|
| 60 | } |
---|
| 61 | example |
---|
| 62 | {"EXAMPLE:"; echo = 2; |
---|
| 63 | ring R = 0,(s(1..5), t(1..4)),dp; |
---|
| 64 | ideal emb = t(1), t(2), t(3), t(3)^2; |
---|
| 65 | ideal I = EquationsOfEmbedding(emb, 5); |
---|
| 66 | I; |
---|
| 67 | } |
---|
| 68 | |
---|
| 69 | /////////////////////////////////////////////////////////////////////////////// |
---|
| 70 | |
---|
| 71 | proc ImageGroup(ideal Grp, ideal Gaction) |
---|
| 72 | "USAGE: ImageGroup(G, action); ideal G, action; |
---|
[8bb77b] | 73 | PUROPSE: compute the ideal of the image of G in GL(m,K) induced by the linear |
---|
[4e461ff] | 74 | action 'action', where G is an algebraic group and 'action' defines |
---|
| 75 | an action of G on K^m (size(action) = m). |
---|
| 76 | RETURN: ring, a polynomial ring over the same ground field as the basering, |
---|
| 77 | containing the ideals 'groupid' and 'actionid'. |
---|
| 78 | - 'groupid' is the ideal of the image of G (order <= order of G) |
---|
| 79 | - 'actionid' defines the linear action of 'groupid' on K^m. |
---|
| 80 | NOTE: 'action' and 'actionid' have the same orbits |
---|
| 81 | all variables which give only rise to 0's in the m x m matrices of G |
---|
| 82 | have been omitted. |
---|
| 83 | ASSUME: basering K[s(1..r),t(1..m)] has r + m variables, G is the ideal of an |
---|
| 84 | algebraic group and F is an action of G on K^m. G contains only the |
---|
| 85 | variables s(1)...s(r). The action 'action' is given by polynomials |
---|
| 86 | f_1,...,f_m in basering, s.t. on the ring level we have |
---|
[8bb77b] | 87 | K[t_1,...,t_m] --> K[s_1,...,s_r,t_1,...,t_m]/G |
---|
| 88 | t_i --> f_i(s_1,...,s_r,t_1,...,t_m) |
---|
[4e461ff] | 89 | EXAMPLE: example ImageGroup; shows an example |
---|
| 90 | " |
---|
| 91 | { |
---|
| 92 | int i, j, k, newVars, nrt, imageSize, dbPrt; |
---|
| 93 | ideal matrixEntries; |
---|
| 94 | matrix coMx; |
---|
| 95 | poly tVars, mPoly; |
---|
| 96 | string ringSTR1, ringSTR2, order; |
---|
| 97 | |
---|
| 98 | dbPrt = printlevel-voice+2; |
---|
| 99 | dbprint(dbPrt, "Image Group of " + string(Grp) + ", action = " + string(Gaction)); |
---|
| 100 | def RIGB = basering; |
---|
| 101 | mPoly = minpoly; |
---|
| 102 | tVars = 1; |
---|
| 103 | k = 0; |
---|
| 104 | |
---|
| 105 | // compute the representation of G induced by Gaction, i.e., a matrix |
---|
| 106 | // of size(Gaction) x size(Gaction) and polynomials in s(1),...,s(r) as entries |
---|
| 107 | // the matrix is represented as the list 'matrixEntries' where |
---|
| 108 | // the entries which are always 0 are omittet. |
---|
| 109 | |
---|
| 110 | for(i = 1; i <= ncols(Gaction); i++) { |
---|
| 111 | tVars = tVars * var(i + nvars(basering) - ncols(Gaction)); |
---|
| 112 | } |
---|
| 113 | for(i = 1; i <= ncols(Gaction); i++){ |
---|
| 114 | coMx = coef(Gaction[i], tVars); |
---|
| 115 | for(j = 1; j <= ncols(coMx); j++){ |
---|
| 116 | k++; |
---|
| 117 | matrixEntries[k] = coMx[2, j]; |
---|
| 118 | } |
---|
| 119 | } |
---|
| 120 | newVars = size(matrixEntries); |
---|
| 121 | nrt = ncols(Gaction); |
---|
| 122 | |
---|
| 123 | // this matrix defines an embedding of G into GL(m, K). |
---|
| 124 | // in the next step the ideal of this image is computed |
---|
| 125 | // note that we have omitted all variables which give give rise |
---|
| 126 | // only to 0's. Note that z(1..newVars) are slack variables |
---|
| 127 | |
---|
| 128 | order = "(dp(" + string(nvars(basering)) + "), dp);"; |
---|
| 129 | ringSTR1 = "ring RIGR = (" + charstr(basering) + "), (" + varstr(basering) + ", z(1.." + string(newVars) + "))," + order; |
---|
| 130 | execute(ringSTR1); |
---|
| 131 | minpoly = number(imap(RIGB, mPoly)); |
---|
| 132 | ideal I1, I2, Gn, G, F, mEntries, newGaction; |
---|
| 133 | G = imap(RIGB, Grp); |
---|
| 134 | F = imap(RIGB, Gaction); |
---|
| 135 | mEntries = imap(RIGB, matrixEntries); |
---|
| 136 | |
---|
| 137 | // prepare the ideals needed to compute the image |
---|
| 138 | // and compute the new action of the image on K^m |
---|
| 139 | |
---|
| 140 | for(i = 1; i <= size(mEntries); i++) { I1[i] = var(i + nvars(RIGB)) - mEntries[i]; } |
---|
| 141 | I1 = std(I1); |
---|
| 142 | |
---|
| 143 | for(i = 1; i <= ncols(F); i++) { newGaction[i] = reduce(F[i], I1); } |
---|
| 144 | I2 = G, I1; |
---|
| 145 | I2 = std(I2); |
---|
| 146 | Gn = nselect(I2, 1, nvars(RIGB)); |
---|
| 147 | imageSize = ncols(Gn); |
---|
| 148 | |
---|
| 149 | // create a new basering which might contain more variables |
---|
| 150 | // s(1..newVars) as the original basering and map the ideal |
---|
| 151 | // Gn (contians only z(1..newVars)) to this ring |
---|
| 152 | |
---|
| 153 | ringSTR2 = "ring RIGS = (" + charstr(basering) + "), (s(1.." + string(newVars) + "), t(1.." + string(nrt) + ")), lp;"; |
---|
| 154 | execute(ringSTR2); |
---|
| 155 | minpoly = number(imap(RIGB, mPoly)); |
---|
| 156 | ideal mapIdeal, groupid, actionid; |
---|
| 157 | int offset; |
---|
| 158 | |
---|
| 159 | // construct the map F : RIGB -> RIGS |
---|
| 160 | |
---|
| 161 | for(i = 1; i <= nvars(RIGB) - nrt; i++) { mapIdeal[i] = 0;} // s(i) -> 0 |
---|
| 162 | offset = nvars(RIGB) - nrt; |
---|
| 163 | for(i = 1; i <= nrt; i++) { mapIdeal[i + offset] = var(newVars + i);} // t(i) -> t(i) |
---|
| 164 | offset = offset + nrt; |
---|
| 165 | for(i = 1; i <= newVars; i++) { mapIdeal[i + offset] = var(i);} // z(i) -> s(i) |
---|
| 166 | |
---|
| 167 | // map Gn and newGaction to RIGS |
---|
| 168 | |
---|
| 169 | map F = RIGR, mapIdeal; |
---|
| 170 | groupid = F(Gn); |
---|
| 171 | actionid = F(newGaction); |
---|
| 172 | export(groupid); |
---|
| 173 | export(actionid); |
---|
| 174 | dbprint(dbPrt, " |
---|
| 175 | // 'ImageGroup' created a new ring. |
---|
| 176 | // To see the ring, type (if the name of the ring is R): |
---|
| 177 | show(R); |
---|
| 178 | // To access the ideal of the image-group Gn of the group G w.r.t. 'action' |
---|
| 179 | // and the new action of Gn, type |
---|
| 180 | def R = ImageGroup(G, action); setring R; groupid; actionid; |
---|
| 181 | // 'groupid' is the ideal defining the image of the group G w.r.t. 'action' |
---|
| 182 | // and 'actionid' is the new action of 'groupid'. |
---|
| 183 | "); |
---|
| 184 | return(RIGS); |
---|
| 185 | } |
---|
| 186 | example |
---|
| 187 | {"EXAMPLE:"; echo = 2; |
---|
| 188 | ring B = 0,(s(1..2), t(1..2)),dp; |
---|
| 189 | ideal G = s(1)^3-1, s(2)^10-1; |
---|
| 190 | ideal action = s(1)*s(2)^8*t(1), s(1)*s(2)^7*t(2); |
---|
| 191 | def R = ImageGroup(G, action); |
---|
| 192 | setring R; |
---|
| 193 | groupid; |
---|
| 194 | actionid; |
---|
| 195 | } |
---|
| 196 | |
---|
| 197 | /////////////////////////////////////////////////////////////////////////////// |
---|
| 198 | |
---|
| 199 | proc HilbertWeights(ideal I, wt) |
---|
| 200 | "USAGE: HilbertWeights(I, w); ideal I, intvec wt |
---|
[8bb77b] | 201 | PUROPSE: compute the weights of the "slack" varaibles needed for the |
---|
[4e461ff] | 202 | computation of the algebraic relations of the generators of 'I' s.t. |
---|
| 203 | the Hilbert driven 'std' can be used. |
---|
| 204 | RETURN: intvec |
---|
| 205 | ASSUME: basering = K[t_1,...,t_m,...], 'I' is quasihomogenous w.r.t. 'w' and |
---|
| 206 | contains only polynomials in t_1,...,t_m |
---|
| 207 | " |
---|
| 208 | { |
---|
| 209 | int offset = size(wt); |
---|
| 210 | intvec wtn = wt; |
---|
| 211 | |
---|
| 212 | for(int i = 1; i <= size(I); i++) { wtn[offset + i] = deg(I[i], wt); } |
---|
| 213 | return(wtn); |
---|
| 214 | } |
---|
| 215 | |
---|
| 216 | /////////////////////////////////////////////////////////////////////////////// |
---|
| 217 | |
---|
| 218 | proc HilbertSeries(ideal I, wt) |
---|
| 219 | "USAGE: HilbertSeries(I, w); ideal I, intvec wt |
---|
[8bb77b] | 220 | PUROPSE: compute the polynomial p of the Hilbert Series,represented by p/q, of |
---|
[4e461ff] | 221 | the ring K[t_1,...,t_m,y_1,...,y_r]/I1 where 'w' are the weights of |
---|
| 222 | the variables, computed, e.g., by 'HilbertWeights', 'I1' is of the |
---|
| 223 | form I[1] - y_1,...,I[r] - y_r and is quasihomogenous w.r.t. 'w' |
---|
| 224 | RETURN: intvec |
---|
| 225 | NOTE: the leading 0 of the result does not belong to p, but is needed in |
---|
| 226 | the hilbert-driven 'std'. |
---|
| 227 | " |
---|
| 228 | { |
---|
| 229 | int i; |
---|
| 230 | intvec hs1; |
---|
| 231 | matrix coMx; |
---|
| 232 | poly f = 1; |
---|
| 233 | |
---|
| 234 | for(i = 1; i <= ncols(I); i++) { f = f * (1 - var(1)^deg(I[i], wt));} |
---|
| 235 | coMx = coeffs(f, var(1)); |
---|
| 236 | for(i = 1; i <= deg(f) + 1; i++) { |
---|
| 237 | hs1[i] = int(coMx[i, 1]); |
---|
| 238 | } |
---|
| 239 | hs1[size(hs1) + 1] = 0; |
---|
| 240 | return(hs1); |
---|
| 241 | } |
---|
[8bb77b] | 242 | /////////////////////////////////////////////////////////////////////////////// |
---|
[4e461ff] | 243 | |
---|
| 244 | proc HilbertSeries1(wt) |
---|
| 245 | "USAGE: HilbertSeries1(wt); ideal I, intvec wt |
---|
[8bb77b] | 246 | PUROPSE: compute the polynomial p of the Hilbert Series represented by p/q of |
---|
[4e461ff] | 247 | the ring K[t_1,...,t_m,y_1,...,y_r]/I where I is a complete inter- |
---|
| 248 | section and the generator I[i] has degree wt[i] |
---|
| 249 | RETURN: poly |
---|
| 250 | " |
---|
| 251 | { |
---|
| 252 | int i, j; |
---|
| 253 | intvec hs1; |
---|
| 254 | matrix ma; |
---|
| 255 | poly f = 1; |
---|
| 256 | |
---|
| 257 | for(i = 1; i <= size(wt); i++) { f = f * (1 - var(1)^wt[i]);} |
---|
| 258 | ma = coef(f, var(1)); |
---|
| 259 | j = ncols(ma); |
---|
| 260 | for(i = 0; i <= deg(f); i++) { |
---|
| 261 | if(var(1)^i == ma[1, j]) { |
---|
| 262 | hs1[i + 1] = int(ma[2, j]); |
---|
| 263 | j--; |
---|
| 264 | } |
---|
| 265 | else { hs1[i + 1] = 0; } |
---|
| 266 | } |
---|
| 267 | hs1[size(hs1) + 1] = 0; |
---|
| 268 | return(hs1); |
---|
| 269 | } |
---|
| 270 | |
---|
| 271 | /////////////////////////////////////////////////////////////////////////////// |
---|
| 272 | |
---|
| 273 | proc ImageVariety(ideal I, F, list #) |
---|
| 274 | "USAGE: ImageVariety(ideal I, F [, w]);ideal I; F is a list/ideal, intvec w. |
---|
[8bb77b] | 275 | PUROPSE: compute the Zariski closure of the image of the variety of I under |
---|
[4e461ff] | 276 | the morphism F. |
---|
| 277 | NOTE: if 'I' and 'F' are quasihomogenous w.r.t. 'w' then the Hilbert-driven |
---|
| 278 | 'std' is used. |
---|
| 279 | RETURN: polynomial ring over the same groundfield, containing the ideal |
---|
| 280 | 'imageid'. The variables are Y(1),...,Y(k) where k = size(F) |
---|
| 281 | - 'imageid' is the ideal of the Zariski closure of F(X) where |
---|
| 282 | X is the variety of I. |
---|
| 283 | EXAMPLE: example ImageVariety; shows an example |
---|
| 284 | " |
---|
| 285 | { |
---|
| 286 | int i, dbPrt, nrNewVars; |
---|
| 287 | intvec wt, wth, hs1; |
---|
| 288 | string ringSTR1, ringSTR2, order; |
---|
| 289 | |
---|
| 290 | def RARB = basering; |
---|
| 291 | nrNewVars = size(F); |
---|
| 292 | |
---|
| 293 | dbPrt = printlevel-voice+2; |
---|
| 294 | dbprint(dbPrt, "ImageVariety of " + string(I) + " under the map " + string(F)); |
---|
| 295 | |
---|
| 296 | if(size(#) > 0) { wt = #[1]; } |
---|
| 297 | |
---|
| 298 | // create new ring for elimination, Y(1),...,Y(m) are slack variables. |
---|
| 299 | |
---|
| 300 | poly mPoly = minpoly; |
---|
| 301 | order = "(dp(" + string(nvars(basering)) + "), dp);"; |
---|
| 302 | ringSTR1 = "ring RAR1 = (" + charstr(basering) + "), (" + varstr(basering) + ", Y(1.." + string(nrNewVars) + ")), " + order; |
---|
| 303 | ringSTR2 = "ring RAR2 = (" + charstr(basering) + "), Y(1.." + string(nrNewVars) + "), dp;"; |
---|
| 304 | execute(ringSTR1); |
---|
| 305 | minpoly = number(imap(RARB, mPoly)); |
---|
| 306 | |
---|
| 307 | ideal I, J1, J2, Fm; |
---|
| 308 | |
---|
| 309 | I = imap(RARB, I); |
---|
| 310 | Fm = imap(RARB, F); |
---|
| 311 | |
---|
| 312 | if(size(wt) > 1) { |
---|
| 313 | wth = HilbertWeights(Fm, wt); |
---|
| 314 | hs1 = HilbertSeries(Fm, wt); |
---|
| 315 | } |
---|
| 316 | |
---|
| 317 | // get the ideal of the graph of F : X -> Y and compute a standard basis |
---|
| 318 | |
---|
| 319 | for(i = 1; i <= nrNewVars; i++) { J1[i] = var(i + nvars(RARB)) - Fm[i];} |
---|
| 320 | J1 = J1, I; |
---|
| 321 | if(size(wt) > 1) { |
---|
| 322 | J1 = std(J1, hs1, wth); // Hilbert-driven algorithm |
---|
| 323 | } |
---|
| 324 | else { |
---|
| 325 | J1 = std(J1); |
---|
| 326 | } |
---|
| 327 | |
---|
| 328 | // forget all elements which contain other than the slack variables |
---|
| 329 | |
---|
| 330 | J2 = nselect(J1, 1, nvars(RARB)); |
---|
| 331 | |
---|
| 332 | execute(ringSTR2); |
---|
| 333 | minpoly = number(imap(RARB, mPoly)); |
---|
| 334 | ideal imageid = imap(RAR1, J2); |
---|
| 335 | export(imageid); |
---|
| 336 | dbprint(dbPrt, " |
---|
| 337 | // 'ImageVariety' created a new ring. |
---|
| 338 | // To see the ring, type (if the name of the ring is R): |
---|
| 339 | show(R); |
---|
| 340 | // To access the ideal of the image F(X), where F is a map and X is a variety |
---|
| 341 | // with ideal I,type |
---|
| 342 | def R = ImageVariety(I, F); setring R; imageid; |
---|
| 343 | // 'imageid' is the ideal of the Zariski closure of F(X). |
---|
| 344 | "); |
---|
| 345 | return(RAR2); |
---|
| 346 | } |
---|
| 347 | example |
---|
| 348 | {"EXAMPLE:"; echo = 2; |
---|
| 349 | ring B = 0,(x,y),dp; |
---|
| 350 | ideal I = x4 - y4; |
---|
| 351 | ideal F = x2, y2, x*y; |
---|
| 352 | def R = ImageVariety(I, F); |
---|
| 353 | setring R; |
---|
| 354 | imageid; |
---|
| 355 | } |
---|
| 356 | |
---|
| 357 | /////////////////////////////////////////////////////////////////////////////// |
---|
| 358 | |
---|
| 359 | proc LinearizeAction(ideal Grp, Gaction, int nrs) |
---|
| 360 | "USAGE: LinearizeAction(G,action,r); ideal G, action; int r |
---|
[8bb77b] | 361 | PUROPSE: linearize the group action 'action' and find an equivariant embedding |
---|
| 362 | of K^m where m = size(action). |
---|
[4e461ff] | 363 | ASSUME: G contains only variables var(1..r) (r = nrs) |
---|
| 364 | basering = K[s(1..r),t(1..m)], K = Q or K = Q(a) and minpoly != 0. |
---|
[8bb77b] | 365 | RETURN: polynomial ring contianing the ideals 'actionid', 'embedid', 'groupid' |
---|
[4e461ff] | 366 | - 'actionid' is the ideal defining the linearized action of G |
---|
[8bb77b] | 367 | - 'embedid' is a parameterization of an equivariant embedding (closed) |
---|
[4e461ff] | 368 | - 'groupid' is the ideal of G in the new ring |
---|
| 369 | NOTE: set printlevel > 0 to see a trace |
---|
| 370 | EXAMPLE: example LinearizeAction; shows an example |
---|
| 371 | " |
---|
| 372 | { |
---|
| 373 | int i, j, k, ok, loop, nrt, sizeOfDecomp, dbPrt; |
---|
| 374 | intvec wt; |
---|
| 375 | ideal action, basis, G, reduceIdeal; |
---|
| 376 | matrix decompMx; |
---|
| 377 | poly actCoeff; |
---|
| 378 | string str, order, mPoly; |
---|
| 379 | |
---|
| 380 | dbPrt = printlevel-voice+2; |
---|
| 381 | dbprint(dbPrt, "LinearizeAction " + string(Gaction)); |
---|
| 382 | def RLAR = basering; |
---|
| 383 | mPoly = "minpoly = " + string(minpoly) + ";"; |
---|
| 384 | order = ordstr(basering); |
---|
| 385 | nrt = ncols(Gaction); |
---|
| 386 | for(i = 1; i <= nrs; i++) { wt[i] = 0;} |
---|
| 387 | for(i = nrs + 1; i <= nrs + nrt; i++) { basis[i - nrs] = var(i); wt[i] = 1;} |
---|
| 388 | dbprint(dbPrt, " basis = " + string(basis)); |
---|
| 389 | if(attrib(Grp, "isSB")) { G = Grp; } |
---|
| 390 | else { G = std(Grp); } |
---|
| 391 | reduceIdeal = G; |
---|
| 392 | action = Gaction; |
---|
| 393 | loop = 1; |
---|
| 394 | i = 1; |
---|
| 395 | |
---|
| 396 | // check if each component of 'action' is linear in t(1),...,t(nrt). |
---|
| 397 | |
---|
| 398 | while(loop){ |
---|
| 399 | if(deg(action[i], wt) <= 1) { |
---|
| 400 | sizeOfDecomp = 0; |
---|
| 401 | dbprint(dbPrt, " " + string(action[i]) + " is linear"); |
---|
| 402 | } |
---|
| 403 | else { // action[i] is not linear |
---|
| 404 | |
---|
| 405 | // compute the minimal decomposition of action[i] |
---|
| 406 | // action[i] = decompMx[1,1]*decompMx[2,1] + ... + decompMx[1,k]*decompMx[2,k] |
---|
| 407 | // decompMx[1,j] contains variables var(1)...var(nrs) |
---|
| 408 | // decompMx[2,j] contains variables var(nrs + 1)...var(nvars(basering)) |
---|
| 409 | |
---|
| 410 | dbprint(dbPrt, " " + string(action[i]) + " is not linear, a minimal decomposition is :"); |
---|
| 411 | decompMx = MinimalDecomposition(action[i], nrs, nrt); |
---|
| 412 | sizeOfDecomp = ncols(decompMx); |
---|
| 413 | dbprint(dbPrt, decompMx); |
---|
| 414 | |
---|
| 415 | for(j = 1; j <= sizeOfDecomp; j++) { // check if decompMx[2,j] is a linear combination of basis elements |
---|
| 416 | actCoeff = decompMx[2, j]; |
---|
| 417 | ok = LinearCombinationQ(basis, actCoeff, nrt + nrs); |
---|
| 418 | if(ok == 0) { |
---|
| 419 | |
---|
| 420 | // nonlinear element, compute new component of the action |
---|
| 421 | |
---|
| 422 | dbprint(dbPrt, " the polynomial " + string(actCoeff) + " is not a linear combination of the elements of basis"); |
---|
| 423 | nrt++; |
---|
| 424 | str = charstr(basering) + ", (" + varstr(basering) + ",t(" + string(nrt) + ")),"; |
---|
| 425 | if(defined(RLAB)) { kill(RLAB);} |
---|
| 426 | def RLAB = basering; |
---|
| 427 | if(defined(RLAR)) { kill(RLAR);} |
---|
| 428 | execute("ring RLAR = " + str + "(" + order + ");"); |
---|
| 429 | execute(mPoly); |
---|
| 430 | |
---|
| 431 | ideal basis, action, G, reduceIdeal; |
---|
| 432 | matrix decompMx; |
---|
| 433 | map F; |
---|
| 434 | poly actCoeff; |
---|
| 435 | |
---|
| 436 | wt[nrs + nrt] = 1; |
---|
| 437 | basis = imap(RLAB, basis), imap(RLAB, actCoeff); |
---|
| 438 | action = imap(RLAB, action); |
---|
| 439 | decompMx = imap(RLAB, decompMx); |
---|
| 440 | actCoeff = imap(RLAB, actCoeff); |
---|
| 441 | G = imap(RLAB, G); |
---|
| 442 | attrib(G, "isSB", 1); |
---|
| 443 | reduceIdeal = imap(RLAB, reduceIdeal), actCoeff - var(nrs + nrt); |
---|
| 444 | |
---|
| 445 | // compute action on the new basis element |
---|
| 446 | |
---|
| 447 | for(k = 1; k <= nrs; k++) { F[k] = 0;} |
---|
| 448 | for(k = nrs + 1; k < nrs + nrt; k++) { F[k] = action[k - nrs];} |
---|
| 449 | actCoeff = reduce(F(actCoeff), G); |
---|
| 450 | action[ncols(action) + 1] = actCoeff; |
---|
| 451 | dbprint(dbPrt, " extend basering by " + string(var(nrs + nrt))); |
---|
| 452 | dbprint(dbPrt, " new basis = " + string(basis)); |
---|
| 453 | dbprint(dbPrt, " action of G on new basis element = " + string(actCoeff)); |
---|
| 454 | dbprint(dbPrt, " decomp : " + string(decompMx[2, j]) + " -> " + string(var(nrs + nrt))); |
---|
| 455 | } // end if |
---|
| 456 | else { |
---|
| 457 | dbprint(dbPrt, " the polynomial " + string(actCoeff) + " is a linear combination of the elements of basis"); |
---|
| 458 | } |
---|
| 459 | } // end for |
---|
| 460 | reduceIdeal = std(reduceIdeal); |
---|
| 461 | action[i] = reduce(action[i], reduceIdeal); |
---|
| 462 | } // end else |
---|
| 463 | if(i < ncols(action)) { i++;} |
---|
| 464 | else {loop = 0;} |
---|
| 465 | } // end while |
---|
| 466 | if(defined(actionid)) { kill(actionid); } |
---|
| 467 | ideal actionid, embedid, groupid; |
---|
| 468 | actionid = action; |
---|
| 469 | embedid = basis; |
---|
| 470 | groupid = G; |
---|
| 471 | export(actionid); |
---|
| 472 | export(embedid); |
---|
| 473 | export(groupid); |
---|
| 474 | dbprint(dbPrt, " |
---|
| 475 | // 'LinearizeAction' created a new ring. |
---|
| 476 | // To see the ring, type (if the name of the ring is R): |
---|
| 477 | show(R); |
---|
| 478 | // To access the new action and the equivariant embedding, where G and 'action' |
---|
| 479 | // are the original group and group-action contained in K[s(1..ns)] and |
---|
| 480 | // K[s(1..ns),t(1..nt)] respectively, type |
---|
| 481 | def R = LinearizeAction(G, action, ns, nt); setring R; actionid; embedid; groupid |
---|
| 482 | // 'actionid' is the ideal of the linearized action, 'embedid' is the ideal |
---|
| 483 | // defining the equivariant embedding and 'grouid' is the ideal G. |
---|
| 484 | "); |
---|
| 485 | return(RLAR); |
---|
| 486 | } |
---|
| 487 | example |
---|
| 488 | {"EXAMPLE:"; echo = 2; |
---|
| 489 | ring B = 0,(s(1..5), t(1..3)),dp; |
---|
| 490 | ideal G = s(3)-s(4), s(2)-s(5), s(4)*s(5), s(1)^2*s(4)+s(1)^2*s(5)-1, s(1)^2*s(5)^2-s(5), s(4)^4-s(5)^4+s(1)^2, s(1)^4+s(4)^3-s(5)^3, s(5)^5-s(1)^2*s(5); |
---|
| 491 | ideal action = -s(4)*t(1)+s(5)*t(1), -s(4)^2*t(2)+2*s(4)^2*t(3)^2+s(5)^2*t(2), s(4)*t(3)+s(5)*t(3); |
---|
| 492 | LinearActionQ(action, 5); |
---|
| 493 | def R = LinearizeAction(G, action, 5); |
---|
| 494 | setring R; |
---|
| 495 | R; |
---|
| 496 | actionid; |
---|
| 497 | embedid; |
---|
| 498 | groupid; |
---|
| 499 | LinearActionQ(actionid, 5); |
---|
| 500 | } |
---|
| 501 | |
---|
| 502 | /////////////////////////////////////////////////////////////////////////////// |
---|
| 503 | |
---|
| 504 | proc LinearActionQ(Gaction, int nrs) |
---|
| 505 | "USAGE: LinearActionQ(action,nrs,nrt); ideal action, int nrs |
---|
[8bb77b] | 506 | PUROPSE: check if the action defined by 'action' is linear w.r.t. the variables |
---|
[4e461ff] | 507 | var(nrs + 1...nvars(basering)). |
---|
| 508 | RETURN: 0 action not linear |
---|
| 509 | 1 action is linear |
---|
| 510 | EXAMPLE: example LinearActionQ; shows an example |
---|
| 511 | " |
---|
| 512 | { |
---|
| 513 | int i, nrt, loop; |
---|
| 514 | intvec wt; |
---|
| 515 | |
---|
| 516 | nrt = ncols(Gaction); |
---|
| 517 | for(i = 1; i <= nrs; i++) { wt[i] = 0;} |
---|
| 518 | for(i = nrs + 1; i <= nrs + nrt; i++) { wt[i] = 1;} |
---|
| 519 | loop = 1; |
---|
| 520 | i = 1; |
---|
[8bb77b] | 521 | while(loop) |
---|
| 522 | { |
---|
[4e461ff] | 523 | if(deg(Gaction[i], wt) > 1) { loop = 0; } |
---|
[8bb77b] | 524 | else |
---|
| 525 | { |
---|
[4e461ff] | 526 | i++; |
---|
| 527 | if(i > ncols(Gaction)) { loop = 0;} |
---|
| 528 | } |
---|
| 529 | } |
---|
| 530 | return(i > ncols(Gaction)); |
---|
| 531 | } |
---|
| 532 | example |
---|
| 533 | {"EXAMPLE:"; echo = 2; |
---|
| 534 | ring R = 0,(s(1..5), t(1..3)),dp; |
---|
| 535 | ideal G = s(3)-s(4), s(2)-s(5), s(4)*s(5), s(1)^2*s(4)+s(1)^2*s(5)-1, s(1)^2*s(5)^2-s(5), s(4)^4-s(5)^4+s(1)^2, s(1)^4+s(4)^3-s(5)^3, s(5)^5-s(1)^2*s(5); |
---|
| 536 | ideal Gaction = -s(4)*t(1)+s(5)*t(1), -s(4)^2*t(2)+2*s(4)^2*t(3)^2+s(5)^2*t(2), s(4)*t(3)+s(5)*t(3); |
---|
| 537 | LinearActionQ(Gaction, 5, 3); |
---|
| 538 | } |
---|
| 539 | |
---|
| 540 | /////////////////////////////////////////////////////////////////////////////// |
---|
| 541 | |
---|
| 542 | proc LinearCombinationQ(ideal I, poly f) |
---|
| 543 | "USAGE: LinearCombination(I, f); ideal I, poly f |
---|
[8bb77b] | 544 | PUROPSE: test if f can be written as a linear combination of the generators of I. |
---|
| 545 | RETURN: 0 f is not a linear combination |
---|
| 546 | 1 f is a linear combination |
---|
[4e461ff] | 547 | " |
---|
| 548 | { |
---|
| 549 | int i, loop, sizeJ; |
---|
| 550 | ideal J; |
---|
| 551 | |
---|
| 552 | J = I, f; |
---|
| 553 | sizeJ = size(J); |
---|
| 554 | |
---|
| 555 | def RLC = ImageVariety(ideal(0), J); // compute algebraic relations |
---|
| 556 | setring RLC; |
---|
| 557 | matrix coMx; |
---|
| 558 | poly relation = 0; |
---|
| 559 | |
---|
| 560 | loop = 1; |
---|
| 561 | i = 1; |
---|
[8bb77b] | 562 | while(loop) |
---|
| 563 | { // look for a linear relation containing Y(nr) |
---|
| 564 | if(deg(imageid[i]) == 1) |
---|
| 565 | { |
---|
[4e461ff] | 566 | coMx = coef(imageid[i], var(sizeJ)); |
---|
[8bb77b] | 567 | if(coMx[1,1] == var(sizeJ)) |
---|
| 568 | { |
---|
[4e461ff] | 569 | relation = imageid[i]; |
---|
| 570 | loop = 0; |
---|
| 571 | } |
---|
| 572 | } |
---|
[8bb77b] | 573 | else |
---|
| 574 | { |
---|
[4e461ff] | 575 | i++; |
---|
| 576 | if(i > ncols(imageid)) { loop = 0;} |
---|
| 577 | } |
---|
| 578 | } |
---|
| 579 | return(i <= ncols(imageid)); |
---|
| 580 | } |
---|
| 581 | |
---|
| 582 | /////////////////////////////////////////////////////////////////////////////// |
---|
| 583 | |
---|
| 584 | proc InvariantRing(ideal G, ideal action, list #) |
---|
| 585 | "USAGE: InvariantRing(G, Gact [, opt]); ideal G, Gact; int opt |
---|
[8bb77b] | 586 | PUROPSE: compute generators of the invariant ring of G w.r.t. the action 'Gact' |
---|
[4e461ff] | 587 | ASSUME: G is a finite group and 'Gact' is a linear action. |
---|
| 588 | RETURN: polynomial ring over a simple extension of the groundfield of the |
---|
| 589 | basering (the extension might be trivial), containing the ideals |
---|
| 590 | 'invars' and 'groupid' and the poly 'newA' |
---|
| 591 | - 'invars' contains the algebra-generators of the invariant ring |
---|
| 592 | - 'groupid' is the ideal of G in the new ring |
---|
[8bb77b] | 593 | - 'newA' if the minpoly changes this is the new representation of the |
---|
| 594 | algebraic number, otherwise it is set to 'a'. |
---|
[4e461ff] | 595 | NOTE: the delivered ring might have a different minimal polynomial |
---|
| 596 | EXAMPLE: example InvariantRing; shows an example |
---|
| 597 | " |
---|
| 598 | { |
---|
| 599 | int i, ok, dbPrt, noReynolds, primaryDec; |
---|
| 600 | ideal invarsGens, groupid; |
---|
| 601 | |
---|
| 602 | dbPrt = printlevel-voice+2; |
---|
| 603 | |
---|
| 604 | if(size(#) > 0) { primaryDec = #[1]; } |
---|
| 605 | else { primaryDec = 0; } |
---|
| 606 | |
---|
| 607 | dbprint(dbPrt, "InvariantRing of " + string(G)); |
---|
| 608 | dbprint(dbPrt, " action = " + string(action)); |
---|
| 609 | |
---|
| 610 | if(!attrib(G, "isSB")) { groupid = std(G);} |
---|
| 611 | else { groupid = G; } |
---|
| 612 | |
---|
| 613 | // compute the nullcone of G by means of Derksen's algorithm |
---|
| 614 | |
---|
| 615 | invarsGens = NullCone(groupid, action); // compute the nullcone of the linear action |
---|
| 616 | dbprint(dbPrt, " generators of zero-fibre ideal are " + string(invarsGens)); |
---|
| 617 | |
---|
| 618 | // make all generators of the nullcone invariant |
---|
| 619 | // if necessary, compute the Reynolds Operator, i.e., find all elements |
---|
| 620 | // of the variety defined by G. It might be necessary to extend the groundfield. |
---|
| 621 | |
---|
| 622 | def IRB = basering; |
---|
| 623 | if(defined(RIRR)) { kill(RIRR);} |
---|
| 624 | def RIRR = basering; |
---|
| 625 | setring RIRR; |
---|
| 626 | export(RIRR); |
---|
| 627 | export(invarsGens); |
---|
| 628 | noReynolds = 1; |
---|
| 629 | dbprint(dbPrt, " nullcone is generated by " + string(size(invarsGens))); |
---|
| 630 | dbprint(dbPrt, " degrees = " + string(maxdeg(invarsGens))); |
---|
| 631 | for(i = 1; i <= ncols(invarsGens); i++){ |
---|
| 632 | ok = InvariantQ(invarsGens[i], groupid, action); |
---|
| 633 | if(ok) { dbprint(dbPrt, string(i) + ": poly " + string(invarsGens[i]) + " is invariant");} |
---|
| 634 | else { |
---|
| 635 | if(noReynolds) { |
---|
| 636 | |
---|
| 637 | // compute the Reynolds operator and change the ring ! |
---|
| 638 | |
---|
| 639 | def RORN = ReynoldsOperator(groupid, action, primaryDec); |
---|
| 640 | noReynolds = 0; |
---|
| 641 | setring RORN; |
---|
| 642 | export(RORN); |
---|
| 643 | ideal groupid = std(id); |
---|
| 644 | attrib(groupid, "isSB", 1); |
---|
| 645 | ideal action = actionid; |
---|
| 646 | ideal invarsGens = TransferIdeal(RIRR, "invarsGens", newA); |
---|
| 647 | export(invarsGens); |
---|
| 648 | kill(RIRR); |
---|
| 649 | |
---|
| 650 | } |
---|
| 651 | dbprint(dbPrt, string(i) + ": poly " + string(invarsGens[i]) + " is NOT invariant"); |
---|
| 652 | invarsGens[i] = ReynoldsImage(ROelements, invarsGens[i]); |
---|
| 653 | dbprint(dbPrt, " --> " + string(invarsGens[i])); |
---|
| 654 | } |
---|
| 655 | } |
---|
| 656 | for(i = 1; i <= ncols(invarsGens); i++){ |
---|
| 657 | ok = InvariantQ(invarsGens[i], groupid, action); |
---|
| 658 | if(ok) { dbprint(dbPrt, string(i) + ": poly " + string(invarsGens[i]) + " is invariant"); } |
---|
| 659 | else { print(string(i) + ": Fatal Error with Reynolds ");} |
---|
| 660 | } |
---|
| 661 | kill(IRB); |
---|
| 662 | if(noReynolds == 0) { |
---|
| 663 | def RIRS = RORN; |
---|
| 664 | setring(RIRS); |
---|
| 665 | kill(RORN);export(groupid); |
---|
| 666 | } |
---|
| 667 | else { |
---|
| 668 | def RIRS = RIRR; |
---|
| 669 | kill(RIRR); |
---|
| 670 | setring(RIRS); |
---|
| 671 | export(groupid); |
---|
| 672 | } |
---|
| 673 | ideal invars = invarsGens; |
---|
| 674 | kill(invarsGens); |
---|
| 675 | export(invars); |
---|
| 676 | // export(groupid); |
---|
| 677 | dbprint(dbPrt, " |
---|
| 678 | // 'InvariantRing' created a new ring. |
---|
| 679 | // To see the ring, type (if the name of the ring is R): |
---|
| 680 | show(R); |
---|
| 681 | // To access the generators of the invariant ring of G w.r.t. the linear |
---|
| 682 | // group-action 'action' of G, where G is contained in K[s(1..ns)] and |
---|
| 683 | // 'action' in K[s(1..ns),t(1..nt)], type |
---|
| 684 | def R = InvariantRing(G, action); setring R; invars; |
---|
| 685 | // 'invars' contains generator of the invariant ring. |
---|
| 686 | // Note that G is containd in R as the ideal 'groupid', to see it, type |
---|
| 687 | groupid; |
---|
| 688 | // Note that 'InvariantRing' might change the minimal polynomial |
---|
| 689 | // The representation of the algebraic number is given by 'newA' |
---|
| 690 | "); |
---|
| 691 | return(RIRS); |
---|
| 692 | } |
---|
| 693 | example |
---|
| 694 | {"EXAMPLE:"; echo = 2; |
---|
| 695 | ring B = 0, (s(1..2), t(1..2)), dp; |
---|
| 696 | ideal G = -s(1)+s(2)^3, s(1)^4-1; |
---|
| 697 | ideal action = s(1)*t(1), s(2)*t(2); |
---|
| 698 | |
---|
| 699 | def R = InvariantRing(std(G), action); |
---|
| 700 | setring R; |
---|
| 701 | invars; |
---|
| 702 | } |
---|
| 703 | |
---|
| 704 | /////////////////////////////////////////////////////////////////////////////// |
---|
| 705 | |
---|
| 706 | proc InvariantQ(poly f, ideal G, action) |
---|
| 707 | "USAGE: InvariantQ(f, G, action); poly f; ideal G, action |
---|
[8bb77b] | 708 | PUROPSE: check if the polynomial f is invariant w.r.t. G where G acts via |
---|
[4e461ff] | 709 | 'action' on K^m. |
---|
| 710 | ASSUME: basering = K[s_1,...,s_m,t_1,...,t_m] where K = Q of K = Q(a) and |
---|
| 711 | minpoly != 0, f contains only t_1,...,t_m, G is the ideal of an |
---|
| 712 | algebraic group and a standardbasis. |
---|
| 713 | RETURN: int; |
---|
| 714 | 0 if f is not invariant, |
---|
| 715 | 1 if f is invariant |
---|
| 716 | NOTE: G need not be finite |
---|
| 717 | EXAMPLE: example InvariantQ; shows an example |
---|
| 718 | " |
---|
| 719 | { |
---|
| 720 | map F; |
---|
| 721 | |
---|
| 722 | if(deg(f) == 0) { return(1); } |
---|
| 723 | for(int i = 1; i <= size(action); i++) { |
---|
| 724 | F[nvars(basering) - size(action) + i] = action[i]; |
---|
| 725 | } |
---|
| 726 | return(reduce(f - F(f), G) == 0); |
---|
| 727 | } |
---|
| 728 | |
---|
| 729 | /////////////////////////////////////////////////////////////////////////////// |
---|
| 730 | |
---|
| 731 | proc MinimalDecomposition(poly f, int nrs, int nrt) |
---|
| 732 | "USAGE: MinimalDecomposition(f,a,b); poly f; int a, b. |
---|
[8bb77b] | 733 | PUROPSE: decompose f as a sum M[1,1]*M[2,1] + ... + M[1,r]*M[2,r] where M[1,i] |
---|
| 734 | contains only s(1..a), M[2,i] contains only t(1...b) s.t. r is minimal |
---|
| 735 | ASSUME: f polynomial in K[s(1..a),t(1..b)], K = Q or K = Q(a) and minpoly != 0 |
---|
[4e461ff] | 736 | RETURN: 2 x r matrix M s.t. f = M[1,1]*M[2,1] + ... + M[1,r]*M[2,r] |
---|
| 737 | EXAMPLE: example MinimalDecomposition; |
---|
| 738 | " |
---|
| 739 | { |
---|
| 740 | int i, sizeOfMx, changed, loop; |
---|
| 741 | list initialTerms; |
---|
| 742 | matrix coM1, coM2, coM, decompMx, auxM; |
---|
| 743 | matrix m[2][2] = 0,1,1,0; |
---|
| 744 | poly vars1, vars2; |
---|
| 745 | |
---|
| 746 | if(f == 0) { return(decompMx); } |
---|
| 747 | |
---|
| 748 | // first decompose f w.r.t. t(1..nrt) |
---|
| 749 | // then decompose f w.r.t. s(1..nrs) |
---|
| 750 | |
---|
| 751 | vars1 = RingVarProduct(nrs+1..nrt+nrs); |
---|
| 752 | vars2 = RingVarProduct(1..nrs); |
---|
| 753 | coM1 = SimplifyCoefficientMatrix(m*coef(f, vars1)); // exchange rows of decomposition |
---|
| 754 | coM2 = SimplifyCoefficientMatrix(coef(f, vars2)); |
---|
| 755 | if(ncols(coM2) < ncols(coM1)) { |
---|
| 756 | auxM = coM1; |
---|
| 757 | coM1 = coM2; |
---|
| 758 | coM2 = auxM; |
---|
| 759 | } |
---|
| 760 | decompMx = coM1; // decompMx is the smaller decomposition |
---|
| 761 | if(ncols(decompMx) == 1) { return(decompMx);} // n = 1 is minimal |
---|
| 762 | changed = 0; |
---|
| 763 | loop = 1; |
---|
| 764 | i = 1; |
---|
| 765 | |
---|
| 766 | // first loop, try coM1 |
---|
| 767 | |
---|
| 768 | while(loop) { |
---|
| 769 | coM = MinimalDecomposition(f - coM1[1, i]*coM1[2, i], nrs, nrt); |
---|
| 770 | if(size(coM) == 1) { sizeOfMx = 0; } // coM = 0 |
---|
| 771 | else {sizeOfMx = ncols(coM); } // number of columns |
---|
| 772 | if(sizeOfMx + 1 < ncols(decompMx)) { // shorter decomposition |
---|
| 773 | changed = 1; |
---|
| 774 | decompMx = coM; |
---|
| 775 | initialTerms[1] = coM1[1, i]; |
---|
| 776 | initialTerms[2] = coM1[2, i]; |
---|
| 777 | } |
---|
| 778 | if(sizeOfMx == 1) { loop = 0;} // n = 2 is minimal |
---|
| 779 | if(i < ncols(coM1)) {i++;} |
---|
| 780 | else {loop = 0;} |
---|
| 781 | } |
---|
| 782 | if(sizeOfMx > 1) { // n > 2 |
---|
| 783 | loop = 1; // coM2 might yield |
---|
| 784 | i = 1; // a smaller decomposition |
---|
| 785 | } |
---|
| 786 | |
---|
| 787 | // first loop, try coM2 |
---|
| 788 | |
---|
| 789 | while(loop) { |
---|
| 790 | coM = MinimalDecomposition(f - coM2[1, i]*coM2[2, i], nrs, nrt); |
---|
| 791 | if(size(coM) == 1) { sizeOfMx = 0; } |
---|
| 792 | else {sizeOfMx = ncols(coM); } |
---|
| 793 | if(sizeOfMx + 1 < ncols(decompMx)) { |
---|
| 794 | changed = 1; |
---|
| 795 | decompMx = coM; |
---|
| 796 | initialTerms[1] = coM2[1, i]; |
---|
| 797 | initialTerms[2] = coM2[2, i]; |
---|
| 798 | } |
---|
| 799 | if(sizeOfMx == 1) { loop = 0;} |
---|
| 800 | if(i < ncols(coM2)) {i++;} |
---|
| 801 | else {loop = 0;} |
---|
| 802 | } |
---|
| 803 | if(!changed) { return(decompMx); } |
---|
| 804 | if(size(decompMx) == 1) { matrix decompositionM[2][1];} |
---|
| 805 | else { matrix decompositionM[2][ncols(decompMx) + 1];} |
---|
| 806 | decompositionM[1, 1] = initialTerms[1]; |
---|
| 807 | decompositionM[2, 1] = initialTerms[2]; |
---|
| 808 | if(size(decompMx) > 1) { |
---|
| 809 | for(i = 1; i <= ncols(decompMx); i++) { |
---|
| 810 | decompositionM[1, i + 1] = decompMx[1, i]; |
---|
| 811 | decompositionM[2, i + 1] = decompMx[2, i]; |
---|
| 812 | } |
---|
| 813 | } |
---|
| 814 | return(decompositionM); |
---|
| 815 | } |
---|
| 816 | example |
---|
| 817 | {"EXAMPLE:"; echo = 2; |
---|
| 818 | ring R = 0, (s(1..2), t(1..2)), dp; |
---|
| 819 | poly h = s(1)*(t(1) + t(1)^2) + (t(2) + t(2)^2)*(s(1)^2 + s(2)); |
---|
| 820 | matrix M = MinimalDecomposition(h, 2, 2); |
---|
| 821 | M; |
---|
| 822 | M[1,1]*M[2,1] + M[1,2]*M[2,2] - h; |
---|
| 823 | } |
---|
| 824 | |
---|
| 825 | /////////////////////////////////////////////////////////////////////////////// |
---|
| 826 | |
---|
| 827 | proc NullCone(ideal G, action) |
---|
| 828 | "USAGE: NullCone(G, action); ideal G, action |
---|
[8bb77b] | 829 | PUROPSE: compute the ideal of the nullcone of the linear action of G on K^n, |
---|
[4e461ff] | 830 | given by 'action', by means of Deksen's algorithm |
---|
| 831 | ASSUME: basering = K[s(1..r),t(1..n)], K = Q or K = Q(a) and minpoly != 0, |
---|
| 832 | G is an ideal of a reductive algebraic group in K[s(1..r)], |
---|
| 833 | 'action' is a linear group action of G on K^n (n = ncols(action)) |
---|
| 834 | RETURN: ideal of the nullcone of G. |
---|
[8bb77b] | 835 | NOTE: the generators of the nullcone are homogenous, but i.g. not invariant |
---|
[4e461ff] | 836 | EXAMPLE: example NullCone; shows an example |
---|
| 837 | " |
---|
| 838 | { |
---|
| 839 | int i, nt, dbPrt, offset, groupVars; |
---|
| 840 | poly minPoly; |
---|
| 841 | string ringSTR, vars, order; |
---|
| 842 | def RNCB = basering; |
---|
| 843 | |
---|
| 844 | // prepare the ring needed for the computation |
---|
| 845 | // s(1...) variables of the group |
---|
| 846 | // t(1...) variables of the affine space |
---|
| 847 | // y(1...) additional 'slack' variables |
---|
| 848 | |
---|
| 849 | nt = size(action); |
---|
| 850 | order = "(dp(" + string(nvars(basering) - nt) + "), dp);"; |
---|
| 851 | vars = "(s(1.." + string(nvars(basering) - nt); |
---|
| 852 | vars = vars + "), t(1.." + string(nt) + "), Y(1.." + string(nt) + "))," + order; |
---|
| 853 | ringSTR = "ring RNCR = (" + charstr(basering) + ")," + vars; // ring for the computation |
---|
| 854 | |
---|
| 855 | minPoly = minpoly; |
---|
| 856 | offset = size(G) + nt; |
---|
| 857 | execute(ringSTR); |
---|
| 858 | minpoly = number(imap(RNCB, minPoly)); |
---|
| 859 | ideal action, G, I, J, N, generators; |
---|
| 860 | map F; |
---|
| 861 | poly f; |
---|
| 862 | |
---|
| 863 | // built the ideal of the graph of GxV -> V, (s,v) -> s(v), i.e. |
---|
| 864 | // of the image of the map GxV -> GxVxV, (s,v) -> (s,v,s(v)) |
---|
| 865 | |
---|
| 866 | G = fetch(RNCB, G); |
---|
| 867 | action = fetch(RNCB, action); |
---|
| 868 | groupVars = nvars(basering) - 2*nt; |
---|
| 869 | offset = groupVars + nt; |
---|
| 870 | I = G; |
---|
| 871 | for(i = 1; i <= nt; i = i + 1) { |
---|
| 872 | I = I, var(offset + i) - action[i]; |
---|
| 873 | } |
---|
| 874 | |
---|
| 875 | J = std(I); // takes long, try to improve |
---|
| 876 | |
---|
| 877 | // eliminate |
---|
| 878 | |
---|
| 879 | N = nselect(J, 1, groupVars); |
---|
| 880 | |
---|
| 881 | // substitute |
---|
| 882 | |
---|
| 883 | for(i = 1; i <= nvars(basering); i = i + 1) { F[i] = 0; } |
---|
| 884 | for(i = groupVars + 1; i <= offset; i = i + 1) { F[i] = var(i); } |
---|
| 885 | |
---|
| 886 | generators = mstd(F(N))[2]; |
---|
| 887 | setring(RNCB); |
---|
| 888 | return(fetch(RNCR, generators)); |
---|
| 889 | } |
---|
| 890 | example |
---|
| 891 | {"EXAMPLE:"; echo = 2; |
---|
| 892 | ring R = 0, (s(1..2), x, y), dp; |
---|
| 893 | ideal G = -s(1)+s(2)^3, s(1)^4-1; |
---|
| 894 | ideal action = s(1)*x, s(2)*y; |
---|
| 895 | |
---|
| 896 | ideal inv = NullCone(G, action); |
---|
| 897 | inv; |
---|
| 898 | } |
---|
| 899 | |
---|
| 900 | /////////////////////////////////////////////////////////////////////////////// |
---|
| 901 | |
---|
| 902 | proc ReynoldsOperator(ideal Grp, ideal Gaction, list #) |
---|
| 903 | "USAGE: ReynoldsOperator(G, action [, opt); ideal G, action; int opt |
---|
[8bb77b] | 904 | PUROPSE: compute the Reynolds operator of the group G which act via 'action' |
---|
[4e461ff] | 905 | RETURN: polynomial ring R over a simple extension of the groundfield of the |
---|
| 906 | basering (the extension might be trivial), containing a list |
---|
| 907 | 'ROelements', the ideals 'id', 'actionid' and the polynomial 'newA'. |
---|
| 908 | R = K(a)[s(1..r),t(1..n)]. |
---|
| 909 | - 'ROelements' is a list of ideal, each ideal represents a |
---|
| 910 | substitution map F : R -> R according to the zero-set of G |
---|
| 911 | - 'id' is the ideal of G in the new ring |
---|
| 912 | - 'newA' is the new representation of a' in terms of a. If the |
---|
| 913 | basering does not contain a parameter then 'newA' = 'a'. |
---|
| 914 | ASSUME: basering = K[s(1..r),t(1..n)], K = Q or K = Q(a') and minpoly != 0, |
---|
[8bb77b] | 915 | G is the ideal of a finite group in K[s(1..r)], 'action' is a linear |
---|
[4e461ff] | 916 | group action of G |
---|
| 917 | EXAMPLE: example ReynoldsOperator; shows an example |
---|
| 918 | " |
---|
| 919 | { |
---|
| 920 | int i, j, n, ns, primaryDec; |
---|
| 921 | ideal G1 = Grp; |
---|
| 922 | list solution, saction; |
---|
| 923 | string str; |
---|
| 924 | |
---|
| 925 | if(size(#) > 0) { primaryDec = #[1]; } |
---|
| 926 | else { primaryDec = 0; } |
---|
| 927 | |
---|
| 928 | n = nvars(basering); |
---|
| 929 | ns = n - size(Gaction); |
---|
| 930 | for(i = ns + 1; i <= n; i++) { G1 = G1, var(i);} |
---|
| 931 | |
---|
| 932 | def ROBR = basering; |
---|
| 933 | export(Grp); |
---|
| 934 | export(Gaction); |
---|
| 935 | def RORN = ZeroSet(G1, primaryDec); |
---|
| 936 | setring RORN; |
---|
| 937 | id = TransferIdeal(ROBR, "Grp", newA); // defined in ZeroSet ... |
---|
| 938 | ideal actionid = TransferIdeal(ROBR, "Gaction", newA); |
---|
| 939 | list ROelements; |
---|
| 940 | ideal Rf; |
---|
| 941 | map groupElem; |
---|
| 942 | poly h1, h2; |
---|
| 943 | |
---|
| 944 | for(i = 1; i <= size(zeroset); i++) { |
---|
| 945 | groupElem = zeroset[i]; // element of G |
---|
| 946 | for(j = ns + 1; j <= n; j++) { groupElem[j] = var(j); } // do not change t's |
---|
| 947 | for(j = 1; j <= n - ns; j++) { |
---|
| 948 | h1 = actionid[j]; |
---|
| 949 | h2 = groupElem(h1); |
---|
| 950 | Rf[ns + j] = h2; |
---|
| 951 | } |
---|
| 952 | ROelements[i] = Rf; |
---|
| 953 | } |
---|
| 954 | export(actionid); |
---|
| 955 | export(ROelements); |
---|
| 956 | return(RORN); |
---|
| 957 | } |
---|
| 958 | |
---|
| 959 | /////////////////////////////////////////////////////////////////////////////// |
---|
| 960 | |
---|
| 961 | proc ReynoldsImage(list reynoldsOp, poly f) |
---|
| 962 | "USAGE: ReynoldsImage(RO, f); list RO, poly f |
---|
[8bb77b] | 963 | PUROPSE: compute the Reynolds image of the polynomial f where RO represents |
---|
[4e461ff] | 964 | the Reynolds operator |
---|
| 965 | RETURN: poly |
---|
| 966 | " |
---|
| 967 | { |
---|
| 968 | map F; |
---|
| 969 | poly h = 0; |
---|
| 970 | |
---|
| 971 | for(int i = 1; i <= size(reynoldsOp); i++) { |
---|
| 972 | F = basering, reynoldsOp[i]; |
---|
| 973 | h = h + F(f); |
---|
| 974 | } |
---|
| 975 | return(h/size(reynoldsOp)); |
---|
| 976 | } |
---|
| 977 | |
---|
| 978 | /////////////////////////////////////////////////////////////////////////////// |
---|
| 979 | |
---|
| 980 | static proc SimplifyCoefficientMatrix(matrix coefMatrix) |
---|
| 981 | "USAGE: SimplifyCoefficientMatrix(M); M matrix coming from coef(...) |
---|
[8bb77b] | 982 | PUROPSE: simplify the matrix, i.e. find linear dependencies among the columns |
---|
[4e461ff] | 983 | RETURN: matrix M, f = M[1,1]*M[2,1] + ... + M[1,n]*M[2,n] |
---|
| 984 | " |
---|
| 985 | { |
---|
| 986 | int i, j , loop; |
---|
| 987 | intvec columnList; |
---|
| 988 | matrix decompMx = coefMatrix; |
---|
| 989 | |
---|
| 990 | loop = 1; |
---|
| 991 | i = 1; |
---|
| 992 | while(loop) { |
---|
| 993 | columnList = 1..i; // current column |
---|
| 994 | for(j = i + 1; j <= ncols(decompMx); j++) { |
---|
| 995 | // test if decompMx[2, j] equals const * decompMx[2, i] |
---|
| 996 | if(LinearCombinationQ(ideal(decompMx[2, i]), decompMx[2, j])) { // column not needed |
---|
| 997 | decompMx[1, i] = decompMx[1, i] + decompMx[2, j] / decompMx[2, i] * decompMx[1, j]; |
---|
| 998 | } |
---|
| 999 | else { columnList[size(columnList) + 1] = j; } |
---|
| 1000 | } |
---|
| 1001 | if(defined(auxM)) { kill(auxM);} |
---|
| 1002 | matrix auxM[2][size(columnList)]; // built new matrix and omit |
---|
| 1003 | for(j = 1; j <= size(columnList); j++) { // the linear dependent colums |
---|
| 1004 | auxM[1, j] = decompMx[1, columnList[j]]; // found above |
---|
| 1005 | auxM[2, j] = decompMx[2, columnList[j]]; |
---|
| 1006 | } |
---|
| 1007 | decompMx = auxM; |
---|
| 1008 | if(i < ncols(decompMx) - 1) { i++;} |
---|
| 1009 | else { loop = 0;} |
---|
| 1010 | } |
---|
| 1011 | return(decompMx); |
---|
| 1012 | } |
---|
| 1013 | |
---|
| 1014 | /////////////////////////////////////////////////////////////////////////////// |
---|
| 1015 | |
---|
| 1016 | proc SimplifyIdeal(ideal I, list #) |
---|
[8bb77b] | 1017 | "USAGE: SimplifyIdeal(I [,m, name]); ideal I; int m, string name" |
---|
[4e461ff] | 1018 | PURPOSE: simplify ideal I to the ideal I', do not change the names of the |
---|
| 1019 | first m variables, new ideal I' might contain less variables. |
---|
| 1020 | I' contains variables var(1..m) |
---|
| 1021 | RETURN: list |
---|
| 1022 | _[1] ideal I' |
---|
[8bb77b] | 1023 | _[2] ideal representing a map phi to a ring with probably less vars. s.t. |
---|
| 1024 | phi(I) = I' |
---|
[4e461ff] | 1025 | _[3] list of variables |
---|
| 1026 | _[4] list from 'elimpart' |
---|
| 1027 | " |
---|
| 1028 | { |
---|
| 1029 | int i, k, m; |
---|
| 1030 | string nameCMD; |
---|
| 1031 | ideal mId, In, mapId; // ideal for the map |
---|
| 1032 | list sList, result; |
---|
| 1033 | |
---|
| 1034 | sList = elimpart(I); |
---|
| 1035 | In = sList[1]; |
---|
| 1036 | mapId = sList[5]; |
---|
| 1037 | |
---|
[8bb77b] | 1038 | if(size(#) > 0) |
---|
| 1039 | { |
---|
[4e461ff] | 1040 | m = #[1]; |
---|
| 1041 | nameCMD = #[2]; |
---|
| 1042 | } |
---|
| 1043 | else { m = 0;} // nvars(basering); |
---|
| 1044 | k = 0; |
---|
[8bb77b] | 1045 | for(i = 1; i <= nvars(basering); i++) |
---|
| 1046 | { |
---|
| 1047 | if(sList[4][i] != 0) |
---|
| 1048 | { |
---|
[4e461ff] | 1049 | k++; |
---|
| 1050 | if(k <= m) { mId[i] = sList[4][i]; } |
---|
| 1051 | else { execute("mId["+string(i) +"] = "+nameCMD+"("+string(k-m)+");");} |
---|
| 1052 | } |
---|
| 1053 | else { mId[i] = 0;} |
---|
| 1054 | } |
---|
| 1055 | map phi = basering, mId; |
---|
| 1056 | result[1] = phi(In); |
---|
| 1057 | result[2] = phi(mapId); |
---|
| 1058 | result[3] = simplify(sList[4], 2); |
---|
| 1059 | result[4] = sList; |
---|
| 1060 | return(result); |
---|
| 1061 | } |
---|
| 1062 | |
---|
[8bb77b] | 1063 | /////////////////////////////////////////////////////////////////////////////// |
---|
[4e461ff] | 1064 | |
---|
| 1065 | static proc TransferIdeal(R, string name, poly newA) |
---|
| 1066 | " USAGE: TransferIdeal(R, name, newA); ring R, string name, poly newA |
---|
[8bb77b] | 1067 | PUROPSE: Maps an ideal with name 'name' in R to the basering, s.t. all |
---|
[4e461ff] | 1068 | variables are fixed but par(1) is replaced by 'newA'. |
---|
| 1069 | RETURN: ideal |
---|
[8bb77b] | 1070 | NOTE: this is used to transfor an ideal if the minimal polynomial has changed |
---|
[4e461ff] | 1071 | " |
---|
| 1072 | { |
---|
| 1073 | def RAB = basering; |
---|
| 1074 | def RA1 = TransferRing(R); |
---|
| 1075 | |
---|
| 1076 | setring RA1; |
---|
| 1077 | execute("ideal I = imap(R, " + name + ");"); |
---|
| 1078 | setring RAB; |
---|
| 1079 | map F = RA1, maxideal(1); |
---|
| 1080 | F[nvars(RAB) + 1] = newA; |
---|
| 1081 | return(F(I)); |
---|
| 1082 | } |
---|
| 1083 | |
---|
| 1084 | /////////////////////////////////////////////////////////////////////////////// |
---|
| 1085 | |
---|
| 1086 | static proc RingVarProduct(index) |
---|
| 1087 | // list of indices |
---|
| 1088 | { |
---|
| 1089 | poly f = 1; |
---|
[8bb77b] | 1090 | for(int i = 1; i <= size(index); i++) |
---|
| 1091 | { |
---|
[4e461ff] | 1092 | f = f * var(index[i]); |
---|
| 1093 | } |
---|
| 1094 | return(f); |
---|
| 1095 | } |
---|
| 1096 | /////////////////////////////////////////////////////////////////////////////// |
---|