Skip to content

DirectSummands: v0.3 #3815

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 88 commits into
base: development
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
cbc7e87
added DirectSummands to =distributed-packages
mahrud Apr 21, 2025
f5bdef6
added package draft
mahrud Oct 5, 2023
9565f97
exported "findIdem" command, though we should rename it at some point
Devlin-Mallory Oct 18, 2023
85a830e
all checks are green
mahrud Oct 25, 2023
4b79a11
changed Hom of sheaves to use Hom in degree zero
mahrud Oct 25, 2023
e8ef502
moved tests and docs to aux directory
mahrud Oct 27, 2023
89df4f8
added directSummands(Matrix)
mahrud Oct 27, 2023
19193ec
added a main documentation page
mahrud Oct 27, 2023
01a89e6
removed trim from Hom for speedups
mahrud Dec 3, 2023
b02161e
improved summands for Gr(2,4)
mahrud Dec 4, 2023
8b21089
added frobeniusTwist, X5 / GF(4) works now
mahrud Dec 6, 2023
c0713a7
added Recursive option, several minor improvements
mahrud Jan 22, 2024
120dafd
updated package for M2 v1.23
mahrud Jan 22, 2024
9167ca2
added strategy for precomputing Homs
mahrud Jan 22, 2024
b635fac
cached frobeniusPushforward for sheaves and removed frobeniusPushforw…
mahrud Jan 23, 2024
5a5d946
improved changeBaseField
mahrud Feb 14, 2024
de74dbd
added test for modules with Schreyer order
mahrud Feb 16, 2024
685a1d2
added test for potentialExtension and changeBaseField
mahrud Feb 16, 2024
54e63c9
added support for larger powers
mahrud Feb 16, 2024
9d72700
wip: added tally' and unique'
mahrud Feb 16, 2024
b309a49
fixed a broken test
mahrud Mar 11, 2024
3cc9b81
fixed a bug in potentialExtension
mahrud Mar 11, 2024
a043740
added temporary fix for extending ground field of sheaves
mahrud Mar 11, 2024
2c664c3
changed needs to load
mahrud Apr 5, 2024
2e91781
added faster reducedScalar
mahrud May 11, 2024
c92f2f9
added faster reduceScalar
mahrud May 15, 2024
2ee7f5f
added changes for 1.24.05 release
mahrud May 15, 2024
0a067d5
fixed diagonalizing {{x,y},{-y,x}}
mahrud Aug 13, 2024
6beec57
switched to using isWeakIdempotent, added test
mahrud Aug 13, 2024
c602271
changes until Oct 31st (probably)
mahrud Nov 12, 2024
e3f314c
added large-tests.m2
mahrud Nov 15, 2024
edee7aa
changes from last discussion, in preparation for changing matrix powers
Devlin-Mallory Nov 25, 2024
fe1cd7a
changes from last discussion
Devlin-Mallory Nov 25, 2024
da5cca8
frobenius pushforward of sheaf map
Devlin-Mallory Nov 25, 2024
7c311b9
simplified matrix multiplication
Devlin-Mallory Nov 25, 2024
95b70be
fixed a bug I introduced in summands(L,M) when L is a free module
Dec 20, 2024
ba0ca2a
uncommitted changes
mahrud Dec 31, 2024
6da9eb5
added projection and inclusion maps
mahrud Feb 2, 2025
f4ba01b
split random into homogeneous and inhomogeneous version
mahrud Feb 14, 2025
8dd88b6
added tallySummands and isomorphismTally
mahrud Mar 28, 2025
142c0e3
added failing GF exmaple and fixed free summand check
mahrud Mar 30, 2025
c393100
fixed a bug in isIsomorphic for free modules
mahrud Apr 1, 2025
4072c49
added groundField instead of baseField and coefficientRing'
mahrud Apr 2, 2025
ffd5ba8
added eigenvalues'
mahrud Apr 2, 2025
c0ceb20
added summandsFromProjectives
mahrud Apr 2, 2025
b42bec7
updated tests
mahrud Apr 2, 2025
f690a41
fixed bug in isisomfree
mahrud Apr 2, 2025
2985ea7
added projection and injection maps for summandsFromProjectors
mahrud Apr 2, 2025
32fc75c
lowered the number of Tries
mahrud Apr 3, 2025
f47a51c
bumped the version of DirectSummands
mahrud Apr 3, 2025
a1ef191
updated summands(L, M) to be non-recursive
mahrud Apr 3, 2025
e2d87d3
added debug printing
mahrud Apr 3, 2025
00c97c9
moved part of summands code to summandsFromIdempotents
mahrud Apr 3, 2025
70cd68d
added gensEnd0 and moved generalEndomorphism
mahrud Apr 6, 2025
d8a9d65
added findBasicIdempotent, updated isIndecomposable
mahrud Apr 16, 2025
10a214b
implemented method to avoid recomputing Hom
mahrud Apr 17, 2025
3fafd52
made various improvements; all tests pass
mahrud Apr 19, 2025
1eabc57
removed ExtendGroundField option
mahrud Apr 19, 2025
635d2a8
made summandsFromIdempotents almost identical to summandsFromProjectors
mahrud Apr 20, 2025
e63c71f
fixed bug in generalEndomorphism for inhomogeneous case
mahrud Apr 20, 2025
0c4e34e
simplified findIdempotent
mahrud Apr 20, 2025
823d33f
added leftInverse and rightInverse
mahrud Apr 20, 2025
6c52cb2
skip zero summands
mahrud Apr 20, 2025
60767e7
implemented a version with a single Hom computation
mahrud Apr 21, 2025
54d5a62
added splitComponents, improved isomorphism
mahrud Apr 21, 2025
2cc7f74
fixed a missing ??=
mahrud Apr 21, 2025
8f100fa
added dumb eigenvalue hack over ZZ/p
mahrud Apr 21, 2025
ef34310
updated frobenius.m2
mahrud Apr 21, 2025
2e5c5c1
updated Grassmannian benchmark data
mahrud Apr 21, 2025
83618b5
fixed some comments
mahrud Apr 21, 2025
a528121
fixed bug in eigenvalues''
mahrud Apr 22, 2025
a0ea0e9
some changes in summands(L, M)
mahrud Apr 22, 2025
73d11c1
exported more methods
mahrud Apr 22, 2025
7de9002
fixed another bug in fieldElements
mahrud Apr 22, 2025
7d6392b
fixed many problems with summands(L, M)
mahrud Apr 23, 2025
582e786
added splitComponentsBasic, renamed findIdempotents
mahrud Apr 23, 2025
97abefa
added kludge for LocalRings
mahrud Apr 23, 2025
f25f521
added prune' for inhomogeneous examples
mahrud Apr 23, 2025
794d136
fixed the local and inhomogeneous tests
mahrud Apr 24, 2025
37a9fed
fixed isIndecomposable
mahrud Apr 24, 2025
9040240
moved a file to avoid case-insensitive conflicts
mahrud Apr 25, 2025
7c43258
fixed a bug in findProjectors
mahrud Apr 27, 2025
44a4d39
added test
mahrud Apr 27, 2025
d27b57a
added changeBaseField(Ring, Matrix)
mahrud May 1, 2025
ace561e
added pushForward(RingMap, CoherentSheaf)
mahrud May 1, 2025
e12aa09
extracted methods that moved to Isomorphism
mahrud May 14, 2025
c16365c
fixed decomposePushforwardPresentation for degree 1 maps
mahrud May 14, 2025
e00526a
updated package for new version of Isomorphism
mahrud May 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions M2/Macaulay2/packages/=distributed-packages
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ OnlineLookup
MergeTeX
Probability
Isomorphism
DirectSummands
CodingTheory
WhitneyStratifications
JSON
Expand Down
668 changes: 668 additions & 0 deletions M2/Macaulay2/packages/DirectSummands.m2

Large diffs are not rendered by default.

59 changes: 59 additions & 0 deletions M2/Macaulay2/packages/DirectSummands/bench.m2
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
restart
debug needsPackage "DirectSummands"
debugLevel = 1
errorDepth = 2

kk = ZZ/5
R = quotient Grassmannian(1,3, CoefficientRing => kk)
X = Proj R
elapsedTime M = module frobeniusPushforward(1, OO_X); -- <1s in char 2 & 3
rank M
elapsedTime L = summands(M, Verbose => true);
tally apply(summands M, N -> (rank N, degrees N))

N = last M.cache#"FreeSummands";
elapsedTime projs = findProjectors N;
elapsedTime L0 = flatten(summands \ prune \ coker \ projs);
elapsedTime L = summands(keys tallySummands L0, N, Verbose => true);
M.cache.summands = drop(M.cache#"FreeSummands", -1) | L;

-* Timing results:
-----------------------------------
q | F_* | Tot | End | misc
-----------------------------------
2 | <1s | <1s | <1s | noether
4 | ~6s | 33m | 8m | Fields
3 | <1s | 10s | <1s | noether
5 | 43s | ~3h | ~3h | noether (once End is computed, pretty fast with some manual work)
7 | | | |
9 | | | |
-----------------------------------
field q rk free summands non-free summands
-----------------------------------
ZZ/2 2^1 16 1:0 14:1 1:2
ZZ/2 2^2 256 1:0 99:1 99:2 1:3 28:rk 2 bundles
ZZ/3 3^1 81 1:0 44:1 20:2 8: rk 2 bundles
ZZ/3 3^2
ZZ/5 5^1 625 1:0 190:1 300:2 6:3 64:rk 2 bundles
ZZ/7 7^1
*-


kk = ZZ/2
R = quotient Grassmannian(2,5, CoefficientRing => kk)
X = Proj R
elapsedTime M = module frobeniusPushforward(1, OO_X); -- ~20min in char 2
rank M
elapsedTime L = summands(M, Verbose => true);
tally apply(L, N -> (rank N, degrees N))

-* Timing results:
-----------------------------------
q | F_* | Tot | End | misc
-----------------------------------
2 | 20m | | | Fields
-----------------------------------
field q rk free summands non-free summands
-----------------------------------
ZZ/2 2^1 512 (312) (200)
*-
93 changes: 93 additions & 0 deletions M2/Macaulay2/packages/DirectSummands/docs.m2
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
-- TODO:
-- [x] example that is indecomposable
-- [ ] example that decomposes after field extension
-- [ ] example over ZZ, ZZ[i]/(i^2+1), QQ, QQ[i]/(i^2+1), GF, RR, CC?
-- [ ] graded example
-- [ ] local example
-- [ ] example of passing hints of summands
-- [ ] example of isIndecomposable

doc ///
Node
Key
DirectSummands
Headline
decompositions of graded modules and coherent sheaves
Description
Text
As an example, we prove the indecomposability of the @wikipedia "Horrocks–Mumford bundle"@ on $\PP^4$.
Example
needsPackage "BGG"
S = ZZ/32003[x_0..x_4];
E = ZZ/32003[e_0..e_4, SkewCommutative => true];
alphad = map(E^5, E^{-2,-2}, transpose matrix{
{ e_1*e_4, -e_0*e_2, -e_1*e_3, -e_2*e_4, e_0*e_3},
{-e_2*e_3, -e_3*e_4, e_0*e_4, -e_0*e_1, -e_1*e_2}});
alpha = syz alphad;
alphad = beilinson(alphad, S);
alpha = beilinson(alpha, S);
FHM = prune homology(alphad, alpha)
assert(2 == rank FHM)
-- initially ~30s for End(FHM), ~110s for basis; ~35s in ZZ/2; now down to ~1s total!
assert({FHM} == summands FHM)
assert FHM.cache.isIndecomposable
Acknowledgement
The authors thank the organizers of the @HREF{"https://aimath.org/pastworkshops/macaulay2efie.html",
"Macaulay2 workshop at AIM"}@, where significant progress on this package was made.
Subnodes
directSummands

Node
Key
directSummands
(directSummands, Module)
(directSummands, CoherentSheaf)
Headline
computes the direct summands of a graded module or coherent sheaf
Usage
summands M
Inputs
M:{Module,CoherentSheaf}
Outputs
:List
containing modules or coherent sheaves which are direct summands of $M$
Description
Text
This function attempts to find the indecomposable summands of a module or coherent sheaf $M$.
Example
S = QQ[x,y]
M = coker matrix{{x,y},{x,x}}
L = summands M
assert isIsomorphic(M, directSum L)
SeeAlso
findIdempotents
///

-- Template:
///
Node
Key
Headline
Usage
Inputs
Outputs
Consequences
Item
Description
Text
Example
CannedExample
Code
Pre
ExampleFiles
Contributors
References
Caveat
SeeAlso
-- Tree
-- CannedExample
-- Contributors
-- References
-- Caveat
-- SeeAlso
///
213 changes: 213 additions & 0 deletions M2/Macaulay2/packages/DirectSummands/frobenius.m2
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
--needsPackage "PushForward"
--needsPackage "Polyhedra" -- for lattice points
--needsPackage "Complexes"

myPushForward = (f, M) -> (
directSum apply(cachedSummands M,
N -> pushFwd(f, N))
-- doesn't work for matrices:
-- pushForward(f, M)
-- pushForward(f, M, UseHilbertFunction => false)
)

-----------------------------------------------------------------------------
-* Frobenius pushforwards *-
-----------------------------------------------------------------------------

protect FrobeniusRing
protect FrobeniusFormation
frobeniusRing = method(TypicalValue => Ring)
frobeniusRing(ZZ, Ring) := (e, R) -> (
if not R.?cache then R.cache = new CacheTable;
(Rp0, e0) := if R.cache.?FrobeniusFormation then R.cache.FrobeniusFormation else (R, 0);
if Rp0.cache#?(symbol FrobeniusRing, e0 + e) then Rp0.cache#(symbol FrobeniusRing, e0 + e)
else Rp0.cache#(symbol FrobeniusRing, e0 + e) = (
Rpe := newRing(Rp0, Degrees => (char Rp0)^(e0 + e) * degrees Rp0);
Rpe.cache = new CacheTable;
Rpe.cache.FrobeniusFormation = (Rp0, e0 + e);
Rpe)
)

-- FIXMEEE:
quotient Ideal := QuotientRing => opts -> (cacheValue symbol quotient) (I -> (ring I) / I)
--ideal Ring := (cacheValue symbol ideal) (R -> ideal map(R^1, R^0, 0))

-- FIXME: this might forget some information
RingMap ** Module := Module => (f, M) -> directSum apply(cachedSummands M, N -> tensor(f, N))

-- TODO: should also work if S is a finite field
-- defined as a QuotientRing rather than GaloisField
frobeniusTwistMap = (e, S) -> (
k := coefficientRing S;
if char S == 0 or k_0 == 1 then return map(S, S);
a := k_0;
p := char k;
map(S, S, gens S | {a^(p^e)}))

/// -- TODO: add as test:
R = QQ[x,y] -- or ZZ/p
assert(R === frobeniusTwist(1, R))
///

protect FrobeniusTwist
frobeniusTwist = method()
frobeniusTwist(ZZ, Ring) := Ring => (e, S) -> (
k := coefficientRing S;
if char S == 0 or k_0 == 1 then return S;
if not S.?cache then S.cache = new CacheTable;
-- FIMXE: towers of pushforwards
S.cache#(symbol FrobeniusTwist, e) ??= (
F := frobeniusTwistMap(e, ring ideal S);
quotient F ideal S))
frobeniusTwist(ZZ, Ideal) := Ideal => (e, I) -> frobeniusTwist(e, module I)
frobeniusTwist(ZZ, Module) := Module => (e, M) -> (
S := ring M;
R := frobeniusTwist(e, S);
F := frobeniusTwistMap(e, S);
-- TODO: is this correct?
F ** M ** R)
frobeniusTwist(ZZ, Matrix) := Matrix => (e, f) -> (
map(frobeniusTwist(e, target f), frobeniusTwist(e, source f),
frobeniusTwistMap(e, ring f) ** f))

--TODO: maybe export "frobeniusMap"
frobeniusMap = method(TypicalValue => RingMap)
frobeniusMap(Ring, ZZ) := (R, e) -> frobeniusMap(e, R)
frobeniusMap(ZZ, Ring) := (e, R) -> (
map(Re := frobeniusTwist(e, R), frobeniusRing(e, R),
apply(gens Re, g -> g^((char R)^e))))

decomposeFrobeniusPresentation = (e, f) -> decomposePushforwardPresentation((char ring f)^e, f)

protect FrobeniusPushforward
frobeniusPushforward = method()
--frobeniusPushforward(Thing, ZZ) := (T, e) -> frobeniusPushforward(e, T)
frobeniusPushforward(ZZ, Ring) := (e, R) -> frobeniusPushforward(e, module R)
frobeniusPushforward(ZZ, Ideal) := (e, I) -> frobeniusPushforward(e, quotient I)
-- TODO: cache in a way that the second pushforward is the same as applying pushforward twice
frobeniusPushforward(ZZ, Module) := (e, M) -> M.cache#(FrobeniusPushforward, e) ??= (
f := presentation myPushForward(
frobeniusMap(e, ring M),
frobeniusTwist(e, M));
if not isHomogeneous f then coker f
else directSum apply(decomposeFrobeniusPresentation(e, f), coker))

frobeniusPushforward(ZZ, Matrix) := (e, f) -> f.cache#(FrobeniusPushforward, e) ??= (
g := myPushForward(
frobeniusMap(e, ring f),
frobeniusTwist(e, f));
if not isHomogeneous g then g
else directSum decomposeFrobeniusPresentation(e, g))

frobeniusPushforward(ZZ, SheafMap) := (e, f) -> f.cache#(FrobeniusPushforward, e) ??= (
--if not(isFreeModule module source f and isFreeModule module target f) then error "expected a map between free modules";
g := myPushForward(
frobeniusMap(e, ring matrix f),
frobeniusTwist(e, matrix f));
if not isHomogeneous g then g
else Fg := first decomposeFrobeniusPresentation(e, g);
R := ring matrix f;
p := char R;
targetPres := presentation target Fg;
(tPrestardegs, tPressrcdegs) := toSequence(-degrees targetPres // p^e);
Fgtarget := sheaf coker map(R^tPrestardegs, R^tPressrcdegs, sub(targetPres, R));
sourcePres := presentation source Fg;
(sPrestardegs, sPressrcdegs) := toSequence(-degrees sourcePres // p^e);
Fgsource := sheaf coker map(R^sPrestardegs, R^sPressrcdegs, sub(sourcePres, R));
sheaf map(module Fgtarget, module Fgsource, sub(cover Fg, R)))

--frobeniusPushforward(ZZ, Complex) := (e, C) -> () -- TODO

frobeniusPushforward(ZZ, SheafOfRings) := (e, O) -> (
X := variety O;
X.cache.FrobeniusPushforward ??= new MutableHashTable;
X.cache.FrobeniusPushforward#e ??= frobeniusPushforward(e, O^1))
frobeniusPushforward(ZZ, CoherentSheaf) := (e, N) -> N.cache#(FrobeniusPushforward, e) ??= if e == 1 then (
R := ring variety N;
p := char R;
FN := first components frobeniusPushforward(e, module N);
-- slow alternative:
-- FN = myPushForward(frobeniusMap(e, R), module N);
-- prune sheaf image basis(p^e * (max degrees FN // p^e), FN)
Fmatrix := sub(presentation FN, R);
(tardegs, srcdegs) := toSequence(-degrees Fmatrix // p^e);
-- TODO: how long does this take? is it worth caching?
sheaf prune coker map(R^tardegs, R^srcdegs, Fmatrix)) else (
frobeniusPushforward(1, frobeniusPushforward(e-1, N)))

protect FrobeniusPullback
frobeniusPullback = method()
--frobeniusPullback(Thing, ZZ) := (T, e) -> frobeniusPullback(e, T)
frobeniusPullback(ZZ, Module) := (e, M) -> M.cache#(FrobeniusPullback, e) ??= (
R := ring M;
p := char R;
F := frobeniusMap(R, e);
R0 := source F;
A := presentation M;
A0 := sub(A, R0);
coker(F ** map(R0^(-(p^e) * degrees target A0), , A0)))
frobeniusPullback(ZZ, CoherentSheaf) := (e, F) -> sheaf frobeniusPullback(e, module F)

end--
restart
needsPackage "DirectSummands"
needsPackage "NormalToricVarieties"

-- Two cubics on P^2_(ZZ/2)
X = toricProjectiveSpace(2, CoefficientRing => ZZ/2)
S = ring X
I = ideal(x_0^3+x_1^3+x_2^3)
J = ideal(x_0^3+x_0^2*x_1+x_1^3+x_0*x_1*x_2+x_2^3)

R = quotient I
assert(rank \ summands frobeniusPushforward(1, OO_(Proj R)) == {2})
assert(rank \ summands frobeniusPushforward(1, R) == {2,2})
--M = coker frobeniusPushforward(char S, I) -- TODO: consolidate with toric version

R = quotient J
assert(rank \ summands frobeniusPushforward(1, OO_(Proj R)) == {1,1})
assert(rank \ summands frobeniusPushforward(1, R) == {1, 1, 2}) -- FIXME: this is not correct
--M = coker frobeniusPushforward(char S, J) -- TODO: consolidate with toric version

--
R = quotient I
M = frobeniusPushforward(1, R);
N1 = frobeniusPushforward(2, R)
N2 = frobeniusPushforward(1, M)
assert(N1 == N2) -- FIXME: why is this different?
N2' = prune coker frobeniusPushforward(1, presentation M)
assert(N2 == N2')


--
S=(ZZ/2)[x_0..x_2,y_0..y_2,Degrees=>{{1,0},{1,0},{1,0},{0,1},{0,1},{0,1}}];
J=ideal(x_0*y_0+x_1*y_1+x_2*y_2);
B=S/J;
Y=Proj B;
frobeniusPushforward(B,1)
--why is this giving 0? (if the degrees are standard it doesn't)
--this is now fixed with the new code for decomposeFrobeniusPresentation -DM


---
restart
needs "frobenius.m2"
debug PushForward
S=(ZZ/2)[x_0,x_1,x_2,y_0,y_1,y_2,Degrees=>{{1,0},{1,0},{1,0},{0,1},{0,1},{0,1}}]
S0=(ZZ/2)[x_0,x_1,x_2]**(ZZ/2)[y_0,y_1,y_2];
S0=tensor((ZZ/2)[x_0,x_1,x_2], (ZZ/2)[y_0,y_1,y_2], DegreeMap => null)
e=1
errorDepth=1
target presentation myPushForward(frobeniusMap(e, ring S^1), frobeniusTwist(e, S^1))
target presentation myPushForward(frobeniusMap(e, ring S0^1), frobeniusTwist(e, S0^1))

g' = g
peek g

degrees (pushAuxHgs g')_0
degrees (pushAuxHgs g'')_0
--why are the degrees right for S but not S0?

RB = RA = S0
tensor(RB, RA, Join => false)
tensor(RB, RA, Join => true)
Loading
Loading