One Hat Cyber Team
Your IP :
216.73.216.14
Server IP :
194.44.31.54
Server :
Linux zen.imath.kiev.ua 4.18.0-553.77.1.el8_10.x86_64 #1 SMP Fri Oct 3 14:30:23 UTC 2025 x86_64
Server Software :
Apache/2.4.37 (Rocky Linux) OpenSSL/1.1.1k
PHP Version :
5.6.40
Buat File
|
Buat Folder
Eksekusi
Dir :
~
/
usr
/
share
/
doc
/
Macaulay2
/
Core
/
tests
/
Edit File:
totaro.m2
-- From: Burt Totaro <B.J.Totaro@dpmms.cam.ac.uk> -- Date: Wed, 15 Jan 2003 19:02:53 +0000 -- Here is a more detailed description of Grobner bases for commutative -- Z/p^r-algebras R, in particular how to find a Grobner basis. -- This note ends with some programs I wrote, for reducing modulo -- such a Grobner basis (with various restrictions). -- I hope that you and Mike Stillman may want to implement -- some of this. I wrote about Grobner bases before when R is assumed to be flat -- over Z/p^r, but here I won't assume that. -- Briefly, everything works as it does for Grobner bases over fields, -- except that one treats "p" as an extra variable. For the algorithms -- I describe, the basic example of a monomial ordering is reverse lexicographic -- based on the order of "variables" x_1,...,x_n,p: that is, we always -- try to reduce any expression to one divisible by a high power of p, -- if possible. -- Here are some more detailed definitions. Fix a monomial ordering -- on x_1,...,x_n. Given a nonzero homogeneous polynomial f over Z/p^r -- (or over Z localized at p), define the "leading monomial" of f -- to be the element p^i.m, with m a monomial in x_1,...,x_n, -- such that i is the least number with f=0 (mod p^i) and -- m is the leading monomial of the Z/p-polynomial (f/p^i) (mod p). -- For any homogeneous ideal I in Z/p^r[x_1,...,x_n], define the "initial ideal" -- in(I) to be the ideal generated by the leading monomials of all -- nonzero elements of I. (It's convenient to think of in(I) as an ideal -- in Z[x_1,...x_n] which contains the element p^r.) -- The initial ideal in(I) has a unique minimal -- set of generators of the form p^i.m with m a monomial in x_1,...,x_n; -- call these elements p^i.m the "basic non-reduced monomials" of I. -- As usual, by the Hilbert basis theorem, there are only finitely many -- basic non-reduced monomials, p^(i_j).m_j for 1<=j<=N. -- We say that a Z/p^r-polynomial in x_1,...,x_n is "reduced" with respect to I -- if the coefficient c of each monomial m in x_1,...,x_n satisfies 0 <= c < p^i, -- where i is the least number such that p^i.m is a multiple of some -- basic non-reduced monomial. Clearly i<=r for all monomials m. -- It is standard to check that every element of R = Z/p^r[x_1,...,x_n]/I -- is represented by a unique -- reduced polynomial in x_1,...,x_n. -- One could define a "Grobner basis" of I to be any set of elements of -- I < Z/p^r[x_1,...,x_n] whose leading monomials generate -- in(I) < Z/p^r[x_1,...,x_n]. Or one could make a stronger definition, -- which makes the Grobner basis of I uniquely defined (given the -- ordering of monomials in x_1,...,x_n): the Grobner basis of I -- is the set of Z/p^r-polynomials g_j, 1<=j<=N (one for each basic -- non-reduced monomial p^(i_j).m_j), such that g_j is in I, -- g_j has leading monomial p^(i_j).m_j, and the polynomial p^(i_j)m_j - g_j -- is reduced. Using either definition, once we have found a Grobner basis -- for I, there is a simple algorithm to compute the reduced polynomial -- representing any given element f(x_1,...,x_n) of R: one first makes -- f reduced mod p, then mod p^2, and so on up to p^r. (It may save -- time in this process to compute as much as possible over Z/p and -- then "lift" the results; this is what I do in my program "red" to reduce -- modulo a given Grobner basis, as discussed below.) -- It remains to say how to compute a Grobner basis for the ideal -- I in Z/p^r[x_1,...,x_n] generated by a given set of polynomials -- f_1,...,f_s. Briefly, Buchberger's algorithm works, using the above -- notion of "leading monomial". That is, one looks at the leading monomials -- of f_1,...,f_s, for example p.xy, p^4.yz, and so on, and then one -- has to consider "overlaps" such as p^4.xyz which can be reduced in -- two different ways, leading to a new element of I with a possibly -- interesting leading monomial. As usual, this process stops -- after finitely many steps. -- To save time, both in finding a Grobner basis and in reducing a polynomial -- modulo a known Grobner basis, each step of the calculation should be done -- modulo Z/p^i for i as small as possible. For example, once we find -- the Grobner basis over Z/p^r, it is probably a good idea to reduce the Grobner -- basis modulo Z/p^{r-1},..., and Z/p, and to store all this information, -- for use in the reduction algorithm. -- --------------- -- For an application I had in mind, I wrote programs to reduce a given -- polynomial modulo a Grobner basis for a commutative flat Z/2^B-algebra R. -- This is less general than what is suggested above in several ways: -- I take p=2, I don't implement Buchberger's algorithm for finding -- a Grobner basis, and I assume that R is flat over Z/2^B, which implies that the -- basic non-reduced monomials are simply monomials in x_1,...,x_n -- (rather than a power of p times such a monomial). -- Still, I send these programs in case you want to take a look, -- at the end of this note. -- These programs include a particular Grobner basis over Z/2^B, where I -- take B=7, for the ring H^*(SO(2l+1)/U(l),Z/2^B) -- with l=5. The generators of this ring are called e_1,...,e_5, -- in degrees 1,...,5, and e_1...e_5 is a basis for the ring in the top -- dimension, which is 15. -- So for example, one can compute the degree modulo 2^7 of the "spinor variety" -- SO(11)/U(5) in its basic projective embedding (corresponding -- to the ample divisor class e_1), by typing -- load "filename" (the file below) -- red(e_1^15,B) -- The answer is: 30e_1...e_5, which is correct. Indeed, integrally -- one has e_1^15 = 286 e_1...e_5: that is, this spinor variety has degree 286; -- and 286 (mod 2^7) is indeed 30. -- Here are some aspects of these programs that might be worth noting -- if you write similar things. First, it would be handy to have -- Z/p^B available as a basic ring, with multiplication and division by -- units in this ring. I just implemented these things ad hoc, by thinking -- of polynomials over Z/2^B as integral polynomials with coefficients -- in 0,...,2^B-1. Other useful operations one would want in dealing with -- Z/p^B or over Z are "ord" (the p-adic valuation) and "ordpol" (minimum "ord" -- of the coefficients of a polynomial); again, I just implemented these -- by hand. Finally, it might be nice to have special routines for arithmetic -- and polynomial rings over Z/p^B when p=2; computers should be able to work -- much faster in that case. -- It would be tempting to think of Z/p[x_1,...,x_n] as a quotient ring -- of Z[x_1,...,x_n], but I'm not sure if that's allowed by Macaulay 2. -- So in these programs, I used different variable names in the two rings, -- Z[e_1,...e_5] and Z/2[E_1,...,E_5]. This is only a minor complication, -- but it led to something interesting: I defined "redmap" (below) as the obvious -- ring map from the Z-algebra to the Z/2-algebra, and "liftmap" as -- the map back. Of course, there is actually no ring map back, but -- fortunately Macaulay 2 did not give me an error message: "liftmap" gives -- the unique lift of any Z/2-polynomial to the corresponding Z-polynomial -- with coefficients 0 or 1. This is a very convenient operation, so -- you might want to describe it "officially" in the documentation. -- Likewise, if you implement polynomial rings over Z/p^B, there -- should be a built-in way to reduce them to Z/p-polynomials, or to lift them -- to Z-polynomials with coefficients in 0,...,p^B-1. -- The main program below is red(f,B), which reduces a polynomial f -- modulo the given Grobner basis (which is stored in several global variables, -- grob0,grob1,Gmat,gmat) and modulo 2^B. After several improvements, -- described in the comments below, this program is fairly fast. It -- relies heavily on Macaulay 2's ability to reduce modulo a Grobner basis -- over Z/2, and does as little arithmetic over Z/2^B as possible. -- Finally, in my applications, I often found myself multiplying -- two elements of R which are divisible by high powers of 2 and then -- reducing the result. Clearly, one can save a lot of work by -- being aware of these powers of 2 when doing the multiplication. -- As a result, I introduced an alternate notation for elements of R, -- namely as a pair z = (j,f), representing (2^j)f, where the polynomial f -- only needs to be stored modulo 2^(B-j). The last two programs below -- are red2(z,B), which reduces an expression z of this type modulo -- the given Grobner basis, and mult(x,y,B), which multiplies two -- expressions x and y of this type and reduces the result. -- These programs are slightly more specialized, so I'm not -- sure whether programs like these should be included -- in a general-purpose set of Grobner basis routines over Z/p^B. -- Maybe so, since they should speed things up for a user who knows -- that he will be have to multiply elements of R which are divisible -- by high powers of p. -- Burt -- To: Dan Grayson <dan@math.uiuc.edu> -- These programs work modulo 2^B, where B is a global variables. B=7; -- We define a sequence two, with two#i = 2^i for i=0,...,B. two=(); i=0; while (i<=B) do (two=append(two,2^i); i=i+1); -- recip(x,C) computes 1/x mod 2^C, where C is at most the global -- variable B. If x is even, -- we stop with an error. recip = (x,C) -> (if (x%2==0) then ( error ("Tried to compute 1/",x," mod 2^",C)) else (C=two#C; y:=(1-x)%C; tot:=1; pow:=y; -- Then 1/x = 1/(1-y) = 1+y+y^2+.... while (pow != 0) do (tot=tot+pow; pow=(pow*y)%C); tot%C)); -- ord(i) computes the 2-adic order of an integer i. The program -- gives ord(0) = infty. ord = i -> (tot:=0; if i==0 then (tot=infty) else (while (i%2==0) do (tot=tot+1; i=i//2)); tot) -- ordpol(f) computes the 2-adic order of a polynomial over the integers. ordpol = f -> (tot:=0; coeff:=coefficients f; sizef:= size f; i:=0; if (f==0) then (tot=infty) else ( tot=ord(lift(coeff#1_(0,0),ZZ)); i=1; while (i<sizef) do ( tot=min(tot,ord(lift(coeff#1_(0,i),ZZ))); i=i+1)); tot); R0=ZZ[e_1..e_5,Degrees=>{1..5}]; -- Here grob1 is a Grobner basis for H^*(SO(11)/U(5),Z/2^B), and grob0 -- is the corresponding list of basic non-reduced monomials. -- This is based on the reverse lexicographic monomial ordering, as usual. -- It happens that the usual relations (see for example Mimura and Toda's book -- The Topology of Lie Groups) form a Grobner basis over Z/2^C for any C: -- H^*(SO(2l+1)/U(l),Z) = --Z[e_1,...,e_l]/(e_i^2-2e_(i-1)e_(i+1)+2e_(i-2)e_(i+2)-...+(-1)^i e_(2i) = 0), -- where e_i=0 for i>l. -- grob0=(e_1^2,e_2^2,e_3^2,e_4^2,e_5^2); grob1=(e_1^2-e_2, e_2^2-2*e_1*e_3+e_4, e_3^2-2*e_2*e_4+2*e_1*e_5, e_4^2-2*e_3*e_5, e_5^2); R1=ZZ/2[E_1..E_5,Degrees=>{1..5}]; redmap=map(R1,R0,{E_1,E_2,E_3,E_4,E_5}); liftmap=map(R0,R1,{e_1,e_2,e_3,e_4,e_5}); -- In defining "liftmap", I am using "map" in an undocumented way, -- but it seems to work. -- There is no ring homomorphism from the Z/2-algebra R1 to the Z-algebra R0, -- but "liftmap" seems to provide the natural lift from Z/2-polynomials to -- Z-polynomials with coefficients 0 or 1. -- We define a global variable Gmat. It is a sequence such that -- Gmat#i is a row matrix containing our Grobner basis grob1 over 2^B -- reduced modulo 2^i, for 1<=i<=B. Here Gmat#0 should not be used, -- so we make it an empty sequence () rather than a matrix. Having this -- sequence Gmat saves time in our reduction procedures. Gmat=(); i=B; prev=grob1; len=#grob1; nxt=(); j=0; while i>=1 do ( nxt=(); j=0; while j<len do (nxt=append(nxt,(prev#j)%(two#i)); j=j+1); prev=nxt; Gmat=prepend(matrix {toList prev},Gmat); i=i-1); Gmat=prepend((),Gmat); gmat=redmap(Gmat#1); -- It may not be necessary to ask Macaulay 2 to compute a Grobner basis -- for the image of the row matrix "gmat" of Z/2-polynomials, since -- Macaulay 2 will do so automatically, whenever it first needs to. Still, -- it seems natural to get it done now. -- It should be fast, since the matrix "gmat" really forms -- a Grobner basis already, if all is well. gb gmat; -- red(f,C) uses a mod-2^C Grobner basis, where C is at most the -- global variable B, to reduce f to a reduced polynomial -- over Z/2^r. Here f must be an element of a polynomial ring over Z, -- the same as the ring containing grob0 and grob1; in this exposition, -- I call it R0, but any name would do. -- -- There is a lot of choice about what order to do things in; the wrong -- choice may involve a lot of extra work. -- For red, I try to save time by using Macaulay 2 to do Grobner -- basis calculations over Z/2. We begin by reducing f mod 2 -- using the Grobner basis (g_j) = (G_j mod 2). That is, we find -- Z/2-polynomials e_j such that -- f mod 2 = r + sum_j g_j e_j -- where r is a reduced Z/2-polynomial. Let E_j be any lifts -- of the polynomials e_j to Z/2^C. (It might seem preferable to make -- a more intelligent choice of lift, but I don't see a simple way -- to do that. The program actually takes the lifts E_j to be the unique -- lifts to Z/2^r-polynomials whose coefficients are 0 or 1. This turns -- out to work very well, in that the following multiplication becomes very -- fast.) Then we replace f by -- f - sum_j G_j E_j, -- which is reduced mod 2. -- -- To repeat the process, we need to subtract off some reduced -- Z/2^C-polynomial to make f zero mod 2. Let us just do this in -- a crude way: let R_0 be the lift of r to Z/2^C which has coefficients -- 0 or 1. (We could instead subtract all monomials in f that occur in r -- with their precise coefficient in f, but this crude way seems -- only marginally slower.) We remember R_0, -- and replace f by (f-R)/2 and C by C-1. When we're done, we have to -- add up R_0 + 2R_1+...+2^(C-1)R_(C-1). -- -- The Grobner basis must be in global variables grob0 and Gmat, -- the latter being computed earlier from grob1. -- Here grob0 is the sequence of basic non-reduced monomials, as elements -- of the integral ring R0, in any order. -- And grob1 is the corresponding sequence of Grobner relations. -- They are polynomials over Z/2^B, represented as integer polynomials, in R0, -- with coefficients in 0,...,2^B-1, such that the coefficient -- of the corresponding monomial in grob0 is 1. Finally, Gmat#i, -- for 1<=i<=B, is the sequence grob1 reduced modulo 2^i and viewed -- as a row matrix, and gmat is the row matrix Gmat#1 viewed as a -- row matrix over the Z/2-polynomial ring R1. -- We also use the ring maps redmap and liftmap, defined above. -- -- The program "red", to reduce modulo a given Grobner basis over Z/2^i, -- is significantly faster than several earlier versions. In one test, -- I tried a big calculation using an earlier version of "red", -- which does this reduction "by hand", without using Macaulay 2's -- Grobner basis routines over Z/2, but otherwise using some natural tricks -- to save calculation, such as storing the given Grobner basis modulo -- 2^B, ..., and 2^1, where I had B=7. -- This took 196 seconds. Then I did the same -- calculation using another version of "red", which used Macaulay 2's -- Grobner basis routines over Z/2, but without bothering to store -- the given Grobner basis over different powers of 2 (in effect, -- it used just Gmat#B instead of Gmat#(B-j), in "red", below). -- This took 80 seconds. Finally, I did the same calculation using -- the version of red below, which uses both tricks: it uses Macaulay 2's -- Grobner basis routines over Z/2 and also stores the given Grobner basis over -- 2^B,...,and 2^1, where I had B=7. This took 51 seconds, -- a convincing success. -- red= (f,C) -> (j:=0; h:=f; tot:=0_(ring f); hred:=0; Emat:=0; R:=0; -- We will be looking at a polynomial h (which changes) modulo 2^(C-j). -- At the end, the answer will be tot. while (j<C) do ( h=h%(two#(C-j)); hred=redmap(h); R=liftmap(hred%gmat); Emat=liftmap(hred//gmat); h=h-(((Gmat#(C-j))*Emat)_(0,0))-R; -- At this point, h is zero modulo 2. h=h//2; tot=tot+(two#j)*R; j=j+1); -- Here I will use that liftmap yields integer polynomials with coefficients -- 0 or 1. It follows that tot = R_0 + 2R_1 + ... +2^(C-1)R_(C-1), -- in the above notation, has coefficients in the range 0,...,2^C-1, -- and so I don't need to reduce it mod 2^C. tot); -- red2(z,C) uses a Grobner basis modulo 2^C (maybe at first defined -- modulo a higher power of 2) to reduce z to a reduced polynomial over Z/2^C. -- Here z is a sequence (i,f) where 0<=i<=C-1 and f is an element -- of a polynomial ring over Z, the same as the ring containing grob0 -- and grob1; in exposition, I call it R0, but any name would do. -- Here z means (2^i)f mod 2^C, so in particular f is only meaningful -- mod 2^(C-i). Also, we allow the possibility z=(infty, 0_R0), -- representing 0. The output of red2(z,C) is the same kind of pair. -- red2 = (z,C) -> (tot:=(); tot0:=0; tot1:=0; if (#z != 2) then (error("First input to red2 should be a pair")) else ( if (z#0===infty) then (tot=(infty,0_(ring z#1))) else ( if (z#0>=C) then (tot=(infty,0_(ring z#1))) else ( tot1=red(z#1,C-z#0); if (tot1 == 0) then (tot=(infty,0_(ring z#1))) else ( tot0=ordpol(tot1); tot=(z#0+tot0,tot1//(two#tot0))))); tot)); -- mult(x,y,C) computes x*y (mod 2^C) in reduced form. Here x and y -- are pairs of the form (i,f), meaning (2^i)f (mod 2^C), and -- the output of mult is in the same form. Zero is denoted by -- (infty, 0_R0). -- mult = (x,y,C) -> (tot:=(); tot0:=0; tot1:=0; ex:=0; if ((x#0===infty) or (y#0===infty)) then (tot=(infty, 0_(ring x#1))) else ( if (x#0+y#0 >= C) then (tot=(infty, 0_(ring x#1))) else ( ex=C-x#0-y#0; tot1=((x#1)%(two#ex)) * ((y#1)%(two#ex)); tot=red2((x#0+y#0,tot1),C))); tot); -- a quick test! assert( red(e_1^15,B) == 30*e_1*e_2*e_3*e_4*e_5 )
Simpan