diff --git a/AeCodPruebas.lib b/AeCodPruebas.lib index 403103d..b556470 100644 --- a/AeCodPruebas.lib +++ b/AeCodPruebas.lib @@ -196,36 +196,9 @@ proc NormalOYModule(matrix GOX, matrix GOY, list #) } //print(V);// - T = T + freemodule(a*m) * V; - -/* Infierno infernal - - // "T";T;// - string RName=nameof(basering); - // "show basering"; execute("show("+RName+")");// - // "Raux 1"; Raux; // - print("ring rred = " + charstr(basering) + ",X(1.." + string(p) + "),ds");// - - execute("export("+ RName + ")"); - export(T); - - execute("ring rred = " + charstr(basering) + ",X(1.." + string(p) + "),ds"); - - print("def T = imap("+RName+",T)");// - "Raux 2"; execute(RName); - execute("def T = imap(" + RName + ",T)"); - "T=";T;// - */ - - module N = kbase(std(T)); - - /* - execute("setring("+ RName + ")"); - def N = imap(rred, N); - - print("N = "); print(N); // - */ + T = T + freemodule(a*m) * V; // This should be done by switching to a new ring with only X(1..p) + module N = kbase(std(T)); int CodimT = ncols(N); //print("vector N[1] ="); VectorToMatrix(N[1],a,m);// @@ -257,6 +230,9 @@ proc GenerateOYModule(matrix GOX, matrix GOY, list #) # is an optional ideal so that computations are made modulo this ideal. */ + + // Basic definitions + int i; int j; @@ -266,21 +242,37 @@ proc GenerateOYModule(matrix GOX, matrix GOY, list #) int nx = ncols(GOX); int a = nrows(GOY); - module M = 0; - matrix col[a][1] = 0; + + + module M = 0; // This will be module with the same generators but over O_n + + matrix col[a][1] = 0; // Auxiliar variable to store the particular vector to be transformed at each step + // This is needed because if a column ends in zeroes, SINGULAR cuts the last rows which + // are zero, and then after transforming to the Malgrange Normal Form they loose some components. + // This is also the reason to use matrices instead of vectors and modules. + + // Convert GOY to an O_n - module for (i=1; i<= ny; i++) { - col = submat(GOY,intvec(1..a),intvec(i)); - M = M + MatrixToVector(MalgrFormVect(col, #)); + col = submat(GOY,intvec(1..a),intvec(i)); // Pick the next generator in GOY + M = M + MatrixToVector(MalgrFormVect(col, #)); // Convert to GOX } + // Convert GOX to an O_n -module + + /* + For each generator v of GOX, we need to compute the Malgrange normal + form of v * g for each g in Gens. The result generates the same module in O_n. + */ + + for (i=1; i <= nx; i++) { - col = submat(GOX,intvec(1..a),intvec(i)); + col = submat(GOX,intvec(1..a),intvec(i)); // Pick the next generator in GOX for (j=1; j<= m; j++) { - M = M + MatrixToVector(MalgrFormVect(Gens[j]*col, #)); + M = M + MatrixToVector(MalgrFormVect(Gens[j]*col, #)); // Compute each product of col times an element of Gens } } @@ -297,24 +289,27 @@ proc MalgrRing(ideal J, int n, ideal f) */ // Definitions - int i; - int p = ncols(f); - string RName=nameof(basering); - ideal w = f[1..n]; + int i; + int p = ncols(f); // Total number of components of map + string RName=nameof(basering); // We need the name of the basering as string to later be able to extend it to a new ring with extra variables. + ideal w = f[1..n]; // Get a subset of components of f, which is expected to define a finite mapping. + // Compute generators of w_*O_X - ideal Gens = kbase(std(w+J)); + ideal Gens = kbase(std(w+J)); // This is the set of generators of O_X as O_n-module. int nGens = ncols(Gens); - - ring R0 = changeord(list(list("dp",nvars(basering)))); + // Create a ring with generators as variables and target variables. - string vaG ="G("; - def R1=extendring(nGens,vaG,"dp",1); + ring R0 = changeord(list(list("dp",nvars(basering)))); // Change ordering of basering to global. In local, computations fail since one of the generators of Gens is always a constant. + // ¿To Do: let user choose the local ordering? + + string vaG ="G("; + def R1=extendring(nGens,vaG,"dp",1); // Add G variables so that G(i) corresponds to the i-th generator of Gens. setring R1; string vaX="X("; - def R2=extendring(p, vaX,"lp",1); + def R2=extendring(p, vaX,"lp",1); // Add X variables so that X(j) corresponds to the j-th component of f. setring R2; // Bring necessary information from source ring @@ -330,15 +325,17 @@ proc MalgrRing(ideal J, int n, ideal f) for(i = 1; i<=nGens; i++) { - G = G + ideal(Gens[i]- G(i)); + G = G + ideal(Gens[i]- G(i)); // Make G(i) correspond to Gens[i] } for(i = 1; i<= n; i++) { - W = W + ideal(f[i]- X(i)); + W = W + ideal(f[i]- X(i)); // Make X(i) correspond to f[i], only for the finite mapping subset of components. } - ideal GF = std(W+G+J); + ideal GF = std(W+G+J); // If the orderings are properly chosen, reducing any monomial in O_X with respect to this ideal + // should return a normal form which is a polynomial in X(1..n), G(1..nGens) in which the G's only appear + // as linear terms times polynomials in the X's. This is what we call the Malgrange Normal Form. /* This is now moved to the MalgrFormPoly procedure for (i=n+1; i <= p; i++) @@ -347,7 +344,8 @@ proc MalgrRing(ideal J, int n, ideal f) } */ - export(GF); + // Save variables in ring so that they survive outside of the procedure + export(GF); export(Gens); export(J); @@ -377,32 +375,51 @@ proc MalgrFormPoly(poly h, list #) int i; - ideal K = GF; + // Prepare the ideal that reduces to the Malgrange Normal Form + + ideal K = GF; // Save the GF ideal to a new variable since we are going to possibly modify it. if (size(#)> 0) { - K = std(#[1]+GF); + K = std(#[1]+GF); // Work modulo an ideal, if requested. } for (i=dimX+1; i <= size(mappingf); i++) { - K = K + ideal(X(i) - reduce(mappingf[i], K)); + K = K + ideal(X(i) - reduce(mappingf[i], K)); // Assign the components of f which do not give the finite mapping to variables in the target, if p > n. } - poly hr = reduce(h,K); // Obtain Malgrange form as a sum + /* Caution: We do not compute again a standard basis of K since this would be equivalent to computing + the polynomial of the image when p > n and this is too computationally expensive. */ + + // Compute the Malgrange Normal Form of the requested polynomial + + poly hr = reduce(h,K); // Obtain Malgrange form as a sum. This should be a polynomial only in X's and G's, + // and the G's should only appear as linear variables times polys in X. poly c; int nGens = ncols(Gens); - matrix v[1][nGens] = 0; + + // Convert the Malgrange Normal Form of the polynomial to row matrix form. + + /* + Since the G's are only linear in hr, they determine a vector with + coefficients only in the X's (one coefficient for each G(i)). + We only need to extract these coefficients and add them to the corresponding component in v. + */ + + matrix v[1][nGens] = 0; for (i=1; i<= nGens-1; i++) { - c = hr - subst(hr,G(i),0); // Gens[i] term - hr = hr - c; - v[1,i] = c/G(i); + c = hr - subst(hr,G(i),0); // This is the coefficient of G(i) in hr + hr = hr - c; // Remove the G(i) and its coefficient from hr. + v[1,i] = c/G(i); // The i'th component of v is the coefficient of G(i) in hr. } - v[1,nGens] = hr; + v[1,nGens] = hr; // The variable G(nGens) corresponds to the generator 1 in Gens, + // hence it does not appear in the Malgrange Normal Form. + // Since its coefficient is the remaining part of the previous loop, we add it manually. return(v); } @@ -425,11 +442,13 @@ proc MalgrFormVect(matrix v, list #) int i; - def m = MalgrFormPoly(v[1,1], #); + def m = MalgrFormPoly(v[1,1], #); // We need to manually compute the first component outside of the loop + // so that the first row of the matrix already has the correct information + // (else, the first row would be made of all zeroes and later we would need to remove that row) for (i=2; i <= a; i++) { - m = transpose(concat(transpose(m),transpose(MalgrFormPoly(v[i,1], #)))); + m = transpose(concat(transpose(m),transpose(MalgrFormPoly(v[i,1], #)))); // compute the Malgrange Normal Form row of the next entry of v and add it to the matrix. } return(m); @@ -439,6 +458,11 @@ proc MalgrFormVect(matrix v, list #) proc MatrixToVector(matrix M) { + /* + This procedure converts an a x b matrix M into an (a*b) x 1 matrix v, where + the (i-1)*b + j entry in v with 1 <= j <= b, 1 <= i <= a corresponds to the (i, j) entry in M + */ + int a = nrows(M); int b = ncols(M); @@ -462,6 +486,11 @@ proc MatrixToVector(matrix M) proc VectorToMatrix(vector v, int a, int b) { + /* + Converts a vector of length a*b into an a*b matrix by chopping the adequate + number of components in v. + */ + int i; int j; @@ -482,6 +511,19 @@ proc VectorToMatrix(vector v, int a, int b) proc MalgrFormToOX(matrix M) { + /* + WARNING: + This procedure only works inside the ring generated by MalgrRing, containing + ideal J, ideal Gens, ideal GF, mappingf and the appropriate variables. + + Given a matrix with number of columns equal to nGens and entries in X(1..p), + returns the corresponding vector with entries in O_X + + TO DO: we should use the InvMalgrPoly procedure for this instead of repeating + everything again. + */ + + int i; int j; int p = ncols(mappingf); @@ -522,6 +564,15 @@ proc SplitMap(ideal f) proc InvMalgrPoly(matrix v, ideal Gens, ideal w) { + /* + WARNING: + This procedure only works inside the ring generated by MalgrRing, containing + ideal J, ideal Gens, ideal GF, and the appropriate variables. + + Converts a row matrix corresponding to a Malgrange Normal Form into its + original polynomial form in O_X + */ + int n=ncols(w); int i; poly h=0;