The documented way to erase a cached Gröbner basis is a silent no-op, and there is no supported replacement
- Dominant language
- Macaulay2
- Stars
- 435
- Forks
- 297
- Avg merge
- 4d 20h
- Merged PRs (30d)
- 11
Description
This issue was triaged from [`bugs/dan/1-caching-idea`](https://github.com/Macaulay2/M2/blob/388c1ff0ce30d83751dea7bc7eac77fdc1305dd7/bugs/dan/1-caching-idea), 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 (105 lines)
```text
In-Reply-To: <200605231814.k4NIElV19287@u00.math.uiuc.edu>
From: Michael Stillman
Subject: Re: Re:
Date: Tue, 23 May 2006 16:37:26 -0400
To: dan@math.uiuc.edu
I like the idea of having perhaps two features:
(1) a new option to gb, res, and anything else which generally
stashes its results. It could be
UseCache (or simply Cache)
If false, it either doesn't use the cache, or removes the cached value.
(2) clearCache
which basically does what you mention below. The main problem here
is: how far away does an object have to be from your object for its
cache to not be cleared?
On May 23, 2006, at 2:14 PM, Dan Grayson wrote:
>
> You could also empty all the caches of all the values of I.
>
> i35 : I.gens.cache
>
> o35 = CacheTable{...3...}
>
> o35 : CacheTable
>
> i36 : scan(values I, x -> if x.?cache then scan(keys x.cache,
> remove_(x.cache)))
>
> i37 : I.gens.cache
>
> o37 = CacheTable{}
>
> o37 : CacheTable
>
> Should do that to I.cache, too.
>
>>
>> Well, you could just get the keys of the cache and remove each of
>> them from the cache.
>>
>>
>> i21 : peek I.gens.cache
>>
>> o21 = CacheTable{image => image | x y
>> |
>> }
>> isHomogeneous => true
>> OptionTable{HardDegreeLimit => } => GroebnerBasis[status:
>> done; S-pairs encountered up to degree 0]
>> Syzygies => false
>> SyzygyRows => 0
>>
>> i23 : scan(keys I.gens.cache, key -> remove(I.gens.cache,key))
>>
>> i24 : I.gens.cache
>>
>> o24 = CacheTable{}
>>
>>
>>> From: Michael Stillman
>>> Subject: Re: Re:
>>> Date: Tue, 23 May 2006 14:07:15 -0400
>>> To: dan@math.uiuc.edu
>>>
>>> How do we clean the cache associated with an object now?
>>>
>>> On May 23, 2006, at 2:02 PM, Dan Grayson wrote:
>>>
>>>>
>>>> Why not just add an option to gb so that, instead of computing, it
>>>> discards any
>>>> cached computation it might have left behind when called with the
>>>> same optional
>>>> arguments previously?
>>>>
>>>> gb(I, DegreeLimit=>4, CleanCache => true)
>>>>
>>>> But first tell me why you wanted to remove the cached gb. If you
>>>> just wanted
>>>> to save space, perhaps we need a function that removes all cached
>>>> large
>>>> computations associated with objects of various types.
>>>>
>>>>> To: Dan Grayson
>>>>> From: Michael Stillman
>>>>> Subject:
>>>>> Date: Tue, 23 May 2006 13:52:32 -0400
>>>>>
>>>>> Our description of how to remove a cached GB is no longer correct.
>>>>>
>>>>> We used to do something like this:
>>>>> remove((generators I).cache, {false,0})
>>>>> but now the cached location is different, harder to get at.
>>>>>
>>>>> Perhaps something like: getGroebnerKey(I, DegreeLimit=>4, ...)
>>>>> could return the key that one would use to get at the GB.
>>>>>
>>>>> Then it would be easier to remove.
>>>>>
>>>
>>
```
### Where it stands today
Two live asks, and the first is a verified documentation defect.
### The manual documents a no-op
The thread opens with Mike reporting that *"our description of how to remove a cached GB is no longer
correct"*. That description is still in the manual. `ov_groebner_bases.m2:439` is an `EXAMPLE` block
which says "we must erase the memory of the Groebner basis computed above", runs
```m2
remove(f.cache, {false,0})
```
then says "compute the Groebner basis anew" and times it. The cache key is a `GroebnerBasisOptions` hash
today, not `{false,0}`, so that `remove` is a **silent no-op** — verified: `keys (generators I).cache` is
unchanged across it and the basis is still cached.
Which means the timing the manual displays for the Hilbert-hint computation is a **cache hit**, not a
fresh run. The two `gbRemove` copies at `ov_rings.m2:1535-1536` carry the same stale key but sit inside
`-* *-` blocks, so they are dead rather than misleading.
### The design half is unadopted and still undecided
Mike proposes a `UseCache` (or `Cache`) option on `gb`, `res` and anything else that stashes results, plus
a way to ask for the key. Today `gb` and `res` have no `UseCache`, `Cache` or `CleanCache` option,
`clearCache` exists nowhere in Core (only as a `BasicDivisor` method in `WeilDivisors`), and Mike's
`getGroebnerKey` never appeared — though the key is at least inspectable now, via
`keys (generators I).cache`.
The two halves are filed together because the documentation cannot be corrected without deciding what the
supported way to clear a cache *is*.
`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
Research direction
Start with ov_groebner_bases.m2:439 and inspect the current cache key using keys (generators I).cache; ov_rings.m2:1535-1536 contains related dead examples. Resolve the supported cache-clearing behavior for gb/res, then make the manual example perform a fresh computation and document the replacement; done means the example no longer silently reuses the cached basis.
Written by the indexing model from the issue text.
Assessment
- Domain
- documentation
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100