integralClosure of an ideal can be intractable where the same closure via integralClosure(I, d) is instant
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/1-integralClosureIdeal.m2`](https://github.com/Macaulay2/M2/blob/388c1ff0ce30d83751dea7bc7eac77fdc1305dd7/bugs/mike/1-integralClosureIdeal.m2), one of the 857 files removed from the pre-GitHub `bugs/` tree by [`d2c8d27826`](https://github.com/Macaulay2/M2/commit/d2c8d27826) and catalogued in [#36](https://github.com/Macaulay2/M2/issues/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 (151 lines)
```m2
-- Some possibly good test examples for integralClosure of ideals.
-- MES: Also: some bugs/unpleasant-isms DE found while playing with this
end
restart
load "integralClosureIdeal.m2"
kk=ZZ/101
S=kk[a,b]
integralClosure(ideal(a^3,b^7),2)
i=ideal"a4,a3b,ab3,b4"
integralClosure i
integralClosure (i^2) == i^2 -- i^2 is already integrally closed
-- this line above doesn't seem to finish in small time
-- the timings here refer to some older version of integral closure.
S=kk[a,b,c]
integralClosure ideal(a^2,b^3,c^3) -- OLD: 4th rad takes 45 sec. Then done.
time integralClosure ideal(a^3,b^3,c^3)
-- OLD 4th rad takes 70 sec, 5th rad much longer.
-- NEW 4th rad takes 1 sec, 5th rad 23 sec
time integralClosure(ideal(a^3,b^4,c^5),1)
-- OLD: third (?) rad comp 60 sec. 4th much longer.
-- NEW: fourth rad comp 1 sec. 5th takes 439 sec.
---------------
--Huneke's question (related to "evolutions"):
--If f has isolated singularity, is
--f \in mm*integralClosureIdeal(J(f))
--where mm is the maximal ideal and J(f) is the
--ideal generated by the partial derivatives of f?
--This is known to be true in 2 variables, and
--it's also known if f is quasi-homogeneous.
--Further, it's known that
--f \in integralClosureIdeal(mm*J(f))
restart
kk=ZZ/32003
S=kk[a,b,c]
mm=ideal vars S
--S=QQ[x,y]
f=ideal(matrix{{a^3}}+random(S^1, S^{-4})) -- smallest non-qhom ex we could find in 3 vars.
toString f
ideal(-2136*a^4+9349*a^3*b-5609*a^2*b^2-15802*a*b^3-11250*b^4+8735*a^3*c-9489*a^2*b*c-371*a*b^2*c-14212*b
^3*c+13529*a^2*c^2-545*a*b*c^2-1270*b^2*c^2-2519*a*c^3-1415*b*c^3+626*c^4+a^3)
f= ideal (y^4-2*x^3*y^2-4*x^5*y+x^6-x^7)
f = trim ideal( random(S^1, S^{-3})+random(S^1, S^{-5}))
f = ideal (a^2+a^3+b^2+c^2) -- this is an example
f = ideal (a^2+a^3+b^2+a*b*c+c^2) -- this is an example
J = ideal jacobian f
substitute(J:f, kk) -- check local quasi-homogeneity!
ReesJ=(flattenRing reesAlgebra(J))_0
P=ideal oo
betti res P
Q=trim(P+ minors (2,jacobian P))
codim Q
betti Q
Q1=trim(P+ideal randomMinors(1,2,jacobian P))
betti Q1
time decompose Q1
--radical Q1
vasconcelos (ideal(a,b,c),a)
R1=ringFromFractions(oo, Variable=>z)
R1ring = target (R1_0)
P1=trim ideal R1ring
codim P1
Q2=trim(P1+ideal randomMinors(1,3,jacobian P1))
codim Q2
betti Q1
time decompose Q2
--radical Q1
vasconcelos (ideal(a,b,c),a)
R1=ringFromFractions(oo, Variable=>z)
R1ring = target (R1_0)
P1=trim ideal R1ring
JJ = J -- in the integral closed case
--gens f%J -- f is not in J, so not quasi-homogeneous THIS IS WRONG -- NEED TO LOOK AT IT LOCALLY
JJ=integralClosureOfIdeal J
Slocal = (coefficientRing S){gens S}
fl=substitute(f,Slocal)
JJl=substitute(JJ,Slocal)
mml=substitute(mm,Slocal)
Jl=substitute(J,Slocal)
(gens fl) % (mml*JJl)
(gens fl) % JJl
J:f;
--integralClosureOfIdeal(mm*J)--can't compute this -- just finding the minors the first time is
--very slow (9 variables, codim 5, the 5 x 5's of a 9 x ?? matrix...)
betti res (mm*J)
R4 = kk[a..d]
F = ((super basis(5,ideal(a,b,c))) * random(R4^55, R4^1))_(0,0)
R = kk[a,b,c]
f = sub(F,{d=>1})
f = sub(f,R)
f = ideal f
-------------
restart
--Some bugs:
viewHelp random -- documentation for "random" is peculiar
--truncate(3,Rbar^1)
--viewHelp truncate
--DOCUMENTATION OF "TRUNCATE" CLAIMS THERE'S A BUG
--BASIS problems:
restart
kk=ZZ/101
S=kk[a,b]
R=kk[c,d]
f=map(R,S,{c,d^2})
P=R^1/(ideal vars R)^3
--M=map(P,S^1,{{1_R}}) -- gives error
--M.RingMap=f
B=basis(P)
B=basis(P,SourceRing => S)
keys B -- "RingMap" is a key
B.RingMap => f --returns f, does NOT set the key
B.RingMap -- thinks the map of rings is 0.
kernel B
matrix"c,d3"
keys oo
source B
coimage B
--N=coker matrix{{a*b}}
--map(P,N,{{1_R}}) -- gives error
```
### Where it stands today
`integralClosure I` can be intractable where `integralClosure(J, d)` returning the same ideal is instant,
because the one-argument form always passes the ideal it is handed straight to the Rees algebra.
Over `ZZ/101[a,b]`, with `i = ideal(a^4, a^3*b, a*b^3, b^4)`:
```m2
i2 = i^2; -- 9 monomial generators, a^8 .. b^8
integralClosure i2 -- no result after 240 seconds
integralClosure(i, 2) -- 0.26 seconds
```
Both compute the same ideal. The second argument of `integralClosure(Ideal, ZZ)` is the power, so
`integralClosure(i, 2)` *is* the integral closure of `i^2`, and it comes back with
```
ideal(b^8, a*b^7, a^2*b^6, a^3*b^5, a^4*b^4, a^5*b^3, a^6*b^2, a^7*b, a^8)
```
which is `i^2` itself — so the answer to the whole question is that `i^2` is already integrally closed,
reached instantly by one entry point and not at all by the other.
For a check on what the second argument means, independent of this example, the closure of
`ideal(a^3, b^7)^2 = ideal(a^6, a^3*b^7, b^14)` is the monomials `a^i*b^j` with `i/6 + j/14 >= 1`, and that is
exactly what `integralClosure(ideal(a^3,b^7), 2)` returns:
```m2
i1 : integralClosure(ideal(a^3,b^7), 2)
o1 = ideal (a^6, a^5*b^3, a^4*b^5, a^3*b^7, a^2*b^10, a*b^12, b^14)
```
### Where the difference comes from
The one-argument and two-argument forms are both thin wrappers on the same three-argument method:
https://github.com/Macaulay2/M2/blob/development/M2/Macaulay2/packages/IntegralClosure.m2#L873-L875
So `integralClosure i2` runs `integralClosure(i2, (i2)_0, 1)` while `integralClosure(i, 2)` runs
`integralClosure(i, i_0, 2)`. That method trims its input and hands it to `integralClosureOfIdeal`, which
builds `reesAlgebra(I, a)` and takes the integral closure of *that* ring. The two calls therefore differ in
the size of the ring being normalized: a Rees algebra on `i2`'s 9 generators with denominator `a^8`, against
one on `i`'s 4 generators with denominator `a^4`. Reading the source, that is where the cost goes — this is
not a profile, and the slow call was never allowed to finish, so it is possible the expense lies elsewhere
inside the normalization.
Two smaller observations from the same runs:
* `integralClosure(i2, 1)` also fails to finish in 240 s, which is consistent with the above: it is the same
call as `integralClosure i2`.
* `integralClosure i` itself is instant (0.25 s), returning `ideal(b^4, a*b^3, a^2*b^2, a^3*b, a^4)`. The
difficulty appears with the squared generating set, not with the ring or the field.
### Why this is worth an issue rather than a note about expected cost
`i` is a monomial ideal in two variables whose closure is itself. Nothing about the input suggests it is
hard, a user has no way to tell an intractable call from a hung one, and the cheap route is only reachable if
you happen to know the ideal is a power *and* know that the `ZZ` argument means the exponent. A caller
holding `i2` and not its square root has no way in at all.
### Where this came from
Cataloguing the `bugs/` directory removed in d2c8d27826 (#36). `bugs/mike/1-integralClosureIdeal.m2` is a
scratch file of `integralClosure` examples; the line
```m2
integralClosure (i^2) == i^2 -- i^2 is already integrally closed
-- this line above doesn't seem to finish in small time
```
records the same observation, undated but from a file whose surrounding timings are annotated
"the timings here refer to some older version of integral closure".
`open` · disposition `issue` · source of truth: [`bug-triage/catalog.tsv`](https://github.com/d-torrance/M2/blob/bug-triage/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
Start with the three-argument method in M2/Macaulay2/packages/IntegralClosure.m2 around lines 873-875, then reproduce the timings for i, i^2, integralClosure(i^2), and integralClosure(i, 2) over ZZ/101[a,b]. Trace where the Rees algebra is built and determine whether the divergent cost can be addressed. Done should include a documented or tested resolution for equivalent calls.
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
- 35/100