reesIdeal(I, a) saturates in a tower ring, where most saturate strategies decline, so it cannot finish where flattening first takes ten seconds
Nobody has claimed this yet.
- Dominant language
- Macaulay2
- Stars
- 435
- Forks
- 297
- Avg merge
- 4d 20h
- Merged PRs (30d)
- 11
Description
This issue was triaged from bugs/mike/bench-1-rees.m2, one of the 857 files removed from the pre-GitHub bugs/ tree by d2c8d27826 and catalogued in #36. The commentary below was written by Claude (Claude Opus 5, via Claude Code), not by @d-torrance, whose account posted it -- please weigh it accordingly.
The original file, verbatim
-- Add these examples to the ReesAlgebra benchmark code
kk=ZZ/101
n=6
S=kk[vars(0..n)]
i=monomialCurveIdeal(S,{4,8,11,13,15})
time reesIdeal(i) -- 1.7 sec
--time reesIdeal(i,i_0) -- doesn't finish before I get impatient (10 min?)!
restart
loadPackage "ReesAlgebra2"
kk=ZZ/101
n=3
S=kk[vars(0..n)]
i=ideal random(S^1, S^{-3,-4,-5,-6})
time reesIdeal(i) --8.4 sec
time reesIdeal(i,i_0) --1.4sec
Where it stands today
reesIdeal(I, a) — the two-argument form, whose comment in the source reads "the following method, usually
faster" — does not finish on a 7-variable monomial curve where the one-argument form takes two seconds:
i1 : needsPackage "ReesAlgebra";
i2 : S = ZZ/101[vars(0..6)];
i3 : i = monomialCurveIdeal(S, {4,8,11,13,15});
o3 : Ideal of S
i4 : elapsedTime reesIdeal i; -- 24 generators
-- 1.93899s elapsed
i5 : elapsedTime reesIdeal(i, i_0); -- killed at 15 minutes
i_0 is e^2-d*f, a nonzero element of a domain, so it is a non-zerodivisor and the method's precondition
holds. The file this comes from records the same behaviour in 2013 — "doesn't finish before I get impatient
(10 min?)" — so this is not a regression.
Where the time goes
reesIdeal(Module, RingElement) := Ideal => o -> (I, I0) -> (
if o.Trim == true then I' := trim I else I' = I;
K' := if o.Jacobian == true then expectedReesIdeal I' else (
K' = symmetricAlgebraIdeal I';
R := ring K';
IR := substitute(I0, R);
trim saturate(K', IR) -- <-- unbounded
))
| step | cost |
|---|---|
trim i, then trim module |
0.0008 s, 0.0003 s |
symmetricAlgebraIdeal |
56.8 s |
saturate(K', IR) |
> 180 s, no result |
The saturation happens in a tower, which disables most of saturate
symmetricAlgebraIdeal returns an ideal in S[w_0..w_7] — a polynomial ring whose coefficient ring is
itself a polynomial ring:
i6 : R = ring symmetricAlgebraIdeal trim module trim i;
i7 : numgens R, coefficientRing R
o7 = (8, S)
saturate's strategies gate on isFlatPolynomialRing, defined at Saturation.m2:72 as
isFlatPolynomialRing = R -> isPolynomialRing R and (isField(kk := coefficientRing R) or kk === ZZ)
which is false here because coefficientRing R is S. It is checked at Saturation.m2:533, 555 and
579, so Linear, Bayer, GRevLex and Eliminate all decline the input — each returns in under a
millisecond — leaving only Iterate, which is the naive loop.
Flattening the ring first, and changing nothing else, makes the same saturation finish:
| ring | isFlatPolynomialRing |
saturate(K, i_0), default options |
|---|---|---|
S[w_0..w_7], 8 vars over S |
false | > 180 s, no result |
flattenRing of it: 15 vars over ZZ/101 |
true | 9.9 s, 24 generators |
The 24 generators agree with what reesIdeal i returns, so this is the same answer by a different route.
What I could not determine
In the flat ring, Strategy => Eliminate and Strategy => Iterate each also exceeded 300 s, yet the
default chain returned in 9.9 s. So the measurement above shows that flattening makes the step fast, but
not which strategy is responsible for that, and the mechanism I can name — the four strategies declining
the tower — does not by itself account for the flat-ring default being faster than any strategy I could
select by hand. Worth someone with more knowledge of the hook order looking at, since it may point at a
second, separate problem in how (saturate, Ideal, RingElement) dispatches.
One caveat about what fixing this would buy
Even with the saturation flattened, the two-argument form would total roughly 67 s on this example against
1.94 s for reesIdeal i, so the "usually faster" claim above the method still would not hold here. The
change is from does not finish to finishes, not from slow to fast. The file's second example runs the
other way — reesIdeal(i) 8.4 s against reesIdeal(i, i_0) 1.4 s on
ideal random(S^1, S^{-3,-4,-5,-6}) in four variables — so the method is genuinely worth having; it just
should not be able to hang on a seven-variable monomial curve.
Searches this rests on
Titles and bodies for reesIdeal, ReesAlgebra, symmetricKernel, symmetricAlgebraIdeal, saturate,
flattenRing, tower and isFlatPolynomialRing, and comments via gh search issues for reesIdeal.
Nothing mentions reesIdeal outside the package's own history.
#4308 is (saturate, Module, Ideal) being broken, a
different method; the open flattenRing issues
(#2133,
#3887,
#4578,
#4579) are about flattenRing itself rather than about
callers that fail to use it.
open · disposition issue · source of truth: bug-triage/catalog.tsv
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the monomial-curve example with the two-argument reesIdeal entry point, then inspect the saturation dispatch and the isFlatPolynomialRing checks at Saturation.m2:72, 533, 555, and 579. Compare the tower-ring and flattenRing timings and review the default strategy hook order. Done means the case finishes reliably without changing the computed 24 generators.
Written by the indexing model from the issue text.
Assessment
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100