1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334
|
--=========================================================================--
-*
Copyright 2010 Bart Snapp, Nathaniel Stapleton.
This file is in the public domain.
*-
newPackage(
"NoetherNormalization",
Version => "0.9.3",
Date => "Sept, 2010",
Authors => {
{Name => "Bart Snapp", Email => "snapp@math.ohio-state.edu", HomePage => "http://www.math.ohio-state.edu/~snapp/"},
{Name => "Nathaniel Stapleton", Email => "nstaple2@math.uiuc.edu"}
},
Headline => "place an ideal in Noether normal position",
Keywords => {"Commutative Algebra"},
DebuggingMode => false
)
-- The algorithm given here is based on A. Logar's algorithm as given
-- in:
-- A. Logar. A Computational Proof of the Noether Normalization
-- Lemma. In: Proceedings 6th AAEEC, Lecture Notes in Computer Science
-- 357, Springer, 1989, 259--273.
-- an additional algorithm was implemented from:
-- H. Kredel and V. Weispfenning. Computing Dimension and Independent
-- sets for Polynomial Ideals. J. Symbolic Computation (1988) 6,
-- 231--247.
--=========================================================================--
export{"noetherNormalization","LimitList","RandomRange"}
--=========================================================================--
-- initial comments: noetherNormalization takes an ideal I of a ring R
-- over a field k such that the dimension of I in R is d (fix these
-- symbols for all comments) and returns 1) a linear transformation
-- that puts the ideal in Noether position and 2) the independent
-- variables of R
-----------------------------------------------------------------------------
integralSet = G -> (
J := {};
M := gens G;
for i from 0 to numgens source M - 1 do ( -- check the gens of G to see if their leadMonomial is in a single variable
if # support leadMonomial (M)_(0,i) === 1 then J = J | {support leadMonomial (M)_(0,i)} --checks how many vars are in the lead
);
J = unique flatten J; --note that according to the algorithm J is a set of integers (in fact indices), we choose to return the variables
J);
-- comments: The procedure integralSet takes a Groebner basis G (ie a
-- list of polynomials) and returns the variables that already have an
-- integral relation. It does this by taking the lead monomial of each
-- polynomial and checking whether or not it consists of a power of a
-- single variable. We are assuming that the ring is over a field and
-- thus we don't check the lead coefficient.
-----------------------------------------------------------------------------
varPrep = (X,I) -> (
U := support (independentSets(I,Limit => 1))_0;
(U,X - set U)
);
-- comments: varPrep is the initial function we run on the Groebner
-- basis of the inputted ideal I. It returns sets U and V, with U
-- being algebraically independent and V being algebraically
-- dependent. For all prime ideals it returns a maximal algebraically
-- independent set of variables whose cardinality is equal to d.
-----------------------------------------------------------------------------
lastCheck = (X,G,d) -> (
M := gens G;
i := 0;
while i < numgens source M and not isSubset(support M_(0,i),toList(X_{0..d-1})) do (
i = i+1;
);
if i != numgens source M then return false
else(
if X_{d..#X-1} != integralSet(G) then return false
);
true
);
-- comments: We use lastCheck to check that our final Groebner basis
-- (the gb of the ideal after the change of variables) witnesses the
-- integrality of each variable that should be integral. It first
-- checks that there are no elements of the Groebner basis with
-- support in the independent variables and then that each variable
-- that should be integral after the linear transformation is
-- integral.
-----------------------------------------------------------------------------
inverseSequence = (U,X) -> (
N := {};
for i to #X - 1 do (
for j to #U - 1 do (
if X_i == U_j then (
N = {X_j}|N;
break;
);
);
);
return N;
);
-- comments: inverseSequence is used to give the inverse of a ring
-- map. A ring map is given by a list explaining where each of the
-- ring's variables should go. If the ring map is just a permutation
-- of the variables then it is obviously an isomorphism and
-- inverseSequence returns the sequence that gives the inverse
-- morphism.
-----------------------------------------------------------------------------
randomSum = (U,V,k,rr) -> (
for j to #V - 1 do (
if rr == 0 then
U = apply(U, i -> i + random(k)*V_j) else
U = apply(U, i -> i + random(-rr,rr)*V_j);
);
return U;
);
-- comments: randomSum is used to make the random linear
-- transformations which are candidates for putting I in
-- noetherPosition. It takes in two lists and adds the second to the
-- first with random coefficients.
-----------------------------------------------------------------------------
-- comments: noetherNormalization is the main method. An ideal I is
-- passed to it and its Groebner basis is immediately computed. Next
-- a random linear transformation is applied and we check to see if
-- the ideal is in Noether position. We then check to see if the the
-- ideal in Noether position by partially computing a Groebner basis
-- for the ideal. If the partially computed Groebner basis witnesses
-- the integrality of all of the dependent variables, we are done, if
-- not we try again. If the entire Groebner basis is computed and the
-- integrality is never witnessed then we apply another random linear
-- transformation and start the process again.
noetherNormalization = method(Options => {Verbose => false, LimitList => {5,20,40,60,80,infinity}, RandomRange => 0})
noetherNormalization(Ideal) := opts -> I -> (
A := ring I;
(flatA,fAtoFlatA) := flattenRing A;
fFlatAtoA := fAtoFlatA^-1;
-- (flatA,fAtoFlatA,fFlatAtoA) := flattenRing A;
if not isPolynomialRing A then error "expected an ideal over a polynomial ring";
k := coefficientRing flatA;
if not isField k then error "expected the ring to contain a field";
R := k (monoid [gens flatA,MonomialOrder => Lex]);
ff := map(R,flatA,gens R)*fAtoFlatA; --these maps merely change the order of the ring
ffinverse := fFlatAtoA*map(flatA, R, gens flatA); --these maps merely change the order of the ring
I = ff(I);
G := gb I;
d := dim I;
X := sort gens R;
(U,V) := varPrep(X,I);
counter := 1; --counts the number of times lastCheck is called
limitsequence := opts.LimitList; -- {5,20,40,60,80,infinity}; -- this is for the basiselementlimit setting for computing gb and is based on experience (and nothing else)
done := false;
indep := U;
f := map(R,R,inverseSequence(U|V,X));
finverse := map(R,R, reverse(U|V));
J := apply(integralSet G,i -> f i); -- may need to do a gb comp.
V = apply(V, i -> f(i)); --there might be a faster way to do this, perhaps V={x_(#U)..x_(#U+#V-1)}
U = apply(U, i -> f(i)); -- might be faster to do U = {x_0..x_(#U-1)}
Uold := U;
while not done do (
if opts.Verbose then << "--trying random transformation: " << counter << endl;
seqindex := 0;
stuff := Uold;
rr := opts.RandomRange;
if counter == 0 then U = randomSum(U,V-set J,k,rr);
if counter >= 1 then U = randomSum(U,V-set integralSet(G),k,rr);
stuff = stuff + (stuff - U);
g := map(R,R,reverse(U|V));
ginverse := map(R,R,reverse(stuff|V));
f = g*f;
finverse = finverse*ginverse;
while (not done and seqindex < #limitsequence) do (
if opts.Verbose then (<< "--trying with basis element limit: " << limitsequence_seqindex << endl;);
fI := f I;
G = gb(fI, BasisElementLimit => limitsequence_seqindex);
done = lastCheck(X,G,d);-- may want to define f I above, but this causes noetherNormalization to fail at the moment
seqindex = seqindex + 1;
);
if counter == 5 then << "--warning: no good linear transformation found by noetherNormalization" <<endl;
if done or counter == 5 then(
ffinal := ffinverse*f*ff;
ffinalInverse := ffinverse*finverse*ff;
ffinal.cache.inverse = ffinalInverse;
ffinalInverse.cache.inverse = ffinal;
X = apply(X, i -> ffinverse i);
-- return (ffinal, ffinverse f I,map(A, k[X_{0..d-1}], X_{0..d-1}));
return (ffinal, ffinverse f I,X_{0..d-1});
);
counter = counter + 1;
); -- f puts the ideal into Noether normal position. f inverse goes back to the original ring
);
-----------------------------------------------------------------------------
noetherNormalization(QuotientRing) := noetherNormalization(PolynomialRing) := opts -> R -> (
if not isPolynomialRing ring ideal R then error "expected a quotient of a polynomial ring";
noetherNormalization(ideal R, Verbose => opts.Verbose)
);
--=========================================================================--
beginDocumentation() -- the start of the documentation
-----------------------------------------------------------------------------
document {
Key => NoetherNormalization,
Headline => "routines related to Noether normalization",
EM "NoetherNormalization", " is a package for computing ring homomorphisms
which will place ideals in Noether normal position. The algorithms
used are based on algorithms found in A. Logar's paper: A
Computational Proof of the Noether Normalization Lemma. In:
Proceedings 6th AAEEC, Lecture Notes in Computer Science 357,
Springer, 1989, 259-273."
}
-----------------------------------------------------------------------------
document {
Key => {noetherNormalization,
(noetherNormalization,Ideal),
(noetherNormalization,QuotientRing),
(noetherNormalization,PolynomialRing),
LimitList,
RandomRange,
[noetherNormalization,LimitList],
[noetherNormalization,RandomRange],
[noetherNormalization,Verbose]
},
Headline => "data for Noether normalization",
Usage => "(f,J,X) = noetherNormalization C",
Inputs => {
"C" => null => {"which is either ", ofClass Ideal, " ", TT "I", ", or ", ofClass QuotientRing, " ", TT "R/I", " where ", TT "R", " is ", ofClass PolynomialRing },
LimitList => List => "gives the value which ", TO "BasisElementLimit", "will take",
RandomRange => ZZ => "if not 0, gives a integer bound for the random coefficients. If 0, then chooses random elements from the coefficient field."
},
Outputs => {
"f" => RingMap => {"an automorphism of ", TT "R"},
"J" => Ideal => { "the image of ", TT "I", " under ", TT "f"},
"X" => List => { "a list of variables which are algebraically independent in ", TT "R/J"},
},
"The computations performed in the routine ", TT "noetherNormalization", " use a random linear change of coordinates,
hence one should expect the output to change each time the routine is executed.",
EXAMPLE lines ///
R = QQ[x_1..x_4];
I = ideal(x_2^2+x_1*x_2+1, x_1*x_2*x_3*x_4+1);
(f,J,X) = noetherNormalization I
///,
"The next example shows how when we use the lexicographical ordering, we can see the integrality of ",
TT "R/ f I", " over the polynomial ring in ", TT "dim(R/I)", " variables:",
EXAMPLE lines ///
R = QQ[x_1..x_5, MonomialOrder => Lex];
I = ideal(x_2*x_1-x_5^3, x_5*x_1^3);
(f,J,X) = noetherNormalization I
transpose gens gb J
///,
"If ", TT "noetherNormalization", " is unable to place the ideal into the desired position after a few tries, the following warning is given:",
EXAMPLE lines ///
R = ZZ/2[a,b];
I = ideal(a^2*b+a*b^2+1);
(f,J,X) = noetherNormalization I
///,
"Here is an example with the option ", TT "Verbose => true", ":",
EXAMPLE lines ///
R = QQ[x_1..x_4];
I = ideal(x_2^2+x_1*x_2+1, x_1*x_2*x_3*x_4+1);
(f,J,X) = noetherNormalization(I,Verbose => true)
///,
"The first number in the output above gives the number of
linear transformations performed by the routine while attempting to
place ", TT "I", " into the desired position.
The second number tells which ", TO "BasisElementLimit", " was used when computing the (partial) Groebner basis.
By default, ", TT "noetherNormalization", " tries to use a partial
Groebner basis. It does this by sequentially computing a Groebner
basis with the option ", TO "BasisElementLimit", " set to
predetermined values. The default values come from the following list:", TT "{5,20,40,60,80,infinity}",
". To set the values manually, use the option ", TT "LimitList", ":",
EXAMPLE lines ///
R = QQ[x_1..x_4];
I = ideal(x_2^2+x_1*x_2+1, x_1*x_2*x_3*x_4+1);
(f,J,X) = noetherNormalization(I,Verbose => true,LimitList => {5,10})
///,
"To limit the randomness of the coefficients, use the option ", TT "RandomRange",
". Here is an example where the coefficients of the linear transformation are
random integers from ", TT "-2", " to ", TT "2", ":",
EXAMPLE lines ///
R = QQ[x_1..x_4];
I = ideal(x_2^2+x_1*x_2+1, x_1*x_2*x_3*x_4+1);
(f,J,X) = noetherNormalization(I,Verbose => true,RandomRange => 2)
///,
PARA {
"This symbol is provided by the package ", TO NoetherNormalization, "."
}
}
--=========================================================================--
--Assertions
TEST ///
--uninstallPackage "NoetherNormalization"
--installPackage "NoetherNormalization"
A = QQ[x_1..x_4]
I = ideal(x_1^2 + x_1*x_4+1,x_1*x_2*x_3*x_4+1)
assert((noetherNormalization(I))_2=={x_4,x_3})
///
TEST ///
--loadPackage "NoetherNormalization"
R = QQ[x,y]
I = ideal (y^2-x^2*(x+1))
(F,J,xs) = noetherNormalization I
assert(F === map(R,R,{x, y}))
assert(J == ideal(-x^3-x^2+y^2))
assert(xs == {y})
///
|