From bb83418229f1cad5af0ea835c81eef3fdb5c5f50 Mon Sep 17 00:00:00 2001 From: Mahrud Sayrafi Date: Tue, 8 Jul 2025 12:28:23 -0500 Subject: [PATCH 1/8] updated helpers in SpectralSequences --- M2/Macaulay2/packages/SpectralSequences.m2 | 154 ++------------------- 1 file changed, 15 insertions(+), 139 deletions(-) diff --git a/M2/Macaulay2/packages/SpectralSequences.m2 b/M2/Macaulay2/packages/SpectralSequences.m2 index 5da4de6ece1..b539843b338 100644 --- a/M2/Macaulay2/packages/SpectralSequences.m2 +++ b/M2/Macaulay2/packages/SpectralSequences.m2 @@ -47,8 +47,7 @@ newPackage( HomePage => "http://math.berkeley.edu/~thanh"}}, Headline => "spectral sequences", Keywords => {"Homological Algebra"}, - PackageImports => {"Truncations"}, - PackageExports => {"SimplicialComplexes", "ChainComplexExtras", "PushForward"} + PackageExports => {"SimplicialComplexes", "Complexes", "PushForward"} ) export { @@ -91,148 +90,25 @@ ReverseDictionary = value Core#"private dictionary"#"ReverseDictionary" -------------------------------------------------------------------------------- -- CODE -------------------------------------------------------------------------------- ------------------------------------------------------------------------------------- --- ChainComplexExtraExtras -- Several people have worked on this portion of the code --------------------------------------------------------------------------------------- +-- TODO: move these to Complexes --- since things are mutable we don't want to cache spots spots = method() +spots Complex := List => C -> sort keys C.module -spots ChainComplex := List => ( - C -> sort select(keys complete C,i -> class i === ZZ)) - -max ChainComplex := K -> max spots K -min ChainComplex := K -> min spots K - -support ChainComplex := List => ( - C -> sort select (spots C, i -> C_i != 0)) - - --- Computes the graded pieces of the total complex of a Hom double complex --- (just as a graded module, so no maps!) -Hom (GradedModule, GradedModule) := GradedModule => opts -> (C, D) -> ( - R := C.ring; if R =!= D.ring then error "expected graded modules over the same ring"; - (c,d) := (spots C, spots D); - pairs := new MutableHashTable; - scan(c, i -> scan(d, j -> ( - k := j-i; - p := if not pairs#?k then pairs#k = new MutableHashTable else pairs#k; - p#(i,j) = 1;))); - scan(keys pairs, k -> pairs#k = sort keys pairs#k); - E := new GradedModule; - E.ring = R; - scan(keys pairs, k-> ( - p := pairs#k; - E#k = directSum(apply(p, v -> v => Hom(C_(v#0), D_(v#1), opts)));)); - E) - - - -isWellDefined ChainComplexMap := Boolean => f -> ( - (F,G):= (source f, target f); - all(drop(spots F,1), i -> G.dd_i * f#i == f#(i-1) * F.dd_i)) - --- Computes the total complex of the Hom double complex of two chain complexes --- This code is different from that in ChainComplexExtras. We need this version --- so that the indices are cached. -Hom (ChainComplex, ChainComplex) := ChainComplex => opts -> (C, D) -> ( - if C.ring =!= D.ring then error "expected chain complexes over the same ring"; - hom := lookup(Hom, GradedModule, GradedModule); - E := chainComplex (hom opts)(C, D); - scan(spots E, i -> if E#?i and E#?(i-1) then E.dd#i = - map(E#(i-1), E#i, - matrix table( - E#(i-1).cache.indices, E#i.cache.indices, - (j,k) -> map(E#(i-1).cache.components#(E#(i-1).cache.indexComponents#j), - (E#i).cache.components#((E#i).cache.indexComponents#k), - if j#0 === k#0 and j#1 === k#1-1 then (-1)^(k#0)*Hom(C_(k#0), D.dd_(k#1), opts) - else if j#0 === k#0 + 1 and j#1 === k#1 then Hom(C.dd_(j#0), D_(k#1), opts) - else 0)))); - E -) - -Hom (ChainComplex, ChainComplexMap) := ChainComplexMap => opts -> (C, f) -> ( - (F, G) := (Hom(C, source f, opts), Hom(C, target f, opts)); - map(G,F, i -> map(G_i,F_i, matrix table( G_i.cache.indices,F_i.cache.indices, - (j,k) -> map(G#i.cache.components#(G#i.cache.indexComponents#j), - F#i.cache.components#(F#i.cache.indexComponents#k), - if j === k then Hom(C_(j#0), f_(j#1), opts) - else 0))))) - -Hom (ChainComplexMap, ChainComplex) := ChainComplexMap => opts -> (f, C) -> ( - (F, G) := (Hom(target f, C, opts), Hom(source f, C, opts)); - map(G,F, i -> map (G_i,F_i, matrix table(G_i.cache.indices,F_i.cache.indices, - (j,k) -> map(G#i.cache.components#(G#i.cache.indexComponents#j), - F#i.cache.components#(F#i.cache.indexComponents#k), - if j === k then Hom(f_(j#0), C_(j#1), opts) - else 0))))) - -ChainComplexMap ** ChainComplex := ChainComplexMap => (f,C) -> ( - (F,G) := ((source f) ** C, (target f) ** C); - map(G,F, i -> map (G_i,F_i, matrix table(G_i.cache.indices,F_i.cache.indices, - (j,k) -> map(G#i.cache.components#(G#i.cache.indexComponents#j), - F#i.cache.components#(F#i.cache.indexComponents#k), - if j === k then f_(j#0) ** C_(j#1) - else 0))))) - -ChainComplex ** ChainComplexMap := ChainComplexMap => (C,f) -> ( - (F,G) := (C ** source f, C ** target f); - map(G,F, i -> map (G_i,F_i, matrix table(G_i.cache.indices,F_i.cache.indices, - (j,k) -> map(G#i.cache.components#(G#i.cache.indexComponents#j), - F#i.cache.components#(F#i.cache.indexComponents#k), - if j === k then C_(j#0) ** f_(j#1) - else 0))))) - --- truncate a chain complex at a given homological degree -truncate(ChainComplex,ZZ):= {} >> o -> (C,q) ->( - if q == 0 then return C - else ( - m := min support C; - n := max support C; - l := length C; - if q < -l or q > l then return image(0*id_C) - else K:=new ChainComplex; - K.ring=C.ring; - if q < 0 then for i from min C + 1 to max C do ( - if i <= n + q then K.dd_i = C.dd_i - else if i-1 > n + q then K.dd_i = inducedMap(0*C_(i-1),0*C_i,C.dd_i) - else K.dd_i = inducedMap(C_(i-1), 0*C_i, C.dd_i) ) - else for i from min C+1 to max C do ( - if i-1 >= q + m then K.dd_i = C.dd_i - else if i < q + m then K.dd_i = inducedMap(0*C_(i-1),0*C_i,C.dd_i) - else K.dd_i = map(0*C_(i-1), C_i, 0*C.dd_i) )); - K) - +support Complex := List => C -> select(spots C, i -> C_i != 0) -- the following relies on the pushFwd method from the package "PushForward.m2" - -pushFwd(RingMap,ChainComplex):=o->(f,C) -> -( pushFwdC := chainComplex(source f); - maps := apply(spots C, i-> (i,pushFwd(f,C.dd_i))); - for i from min C to max C do ( - pushFwdC.dd_(maps#i_0) = maps#i_1 - ); - pushFwdC - ) - - --- New method for tensor that returns the tensor product of a complex via a ring map -tensor(RingMap, ChainComplex) := ChainComplex => {} >> opts -> (f,C) -> ( - k := min C; - D := chainComplex( - if even(k) then apply( - drop(select(keys complete C, - i -> instance(i,ZZ)),1), - j -> f ** C.dd_j) - else apply( - drop(select(keys complete C, - i -> instance(i,ZZ)),1), - j -> (-1) * (f ** C.dd_j))); - D[-k] - ) - - ----------------------------------------------------------------------------------- +pushFwd(RingMap, Complex) := o -> (f, C) -> ( + (lo, hi) := concentration C; + if lo == hi + then complex(pushFwd(f, C_lo, o), Base => lo) + else complex applyValues(C.dd.map, + m -> pushFwd(f, m, o))) + +naiveTruncation(Complex, ZZ) := Complex => (C, n) -> ( + (lo, hi) := concentration C; + if n > 0 then naiveTruncation(C, (lo + n, infinity)) else + if n < 0 then naiveTruncation(C, (-infinity, hi + n)) else C) ------------------------------------------------------------------------------------- -- filtered complexes From ca32aa4bd7c823c2bb4334b8a6c00b693c7f0cb0 Mon Sep 17 00:00:00 2001 From: Mahrud Sayrafi Date: Tue, 8 Jul 2025 12:30:02 -0500 Subject: [PATCH 2/8] updated methods in SpectralSequences --- M2/Macaulay2/packages/SpectralSequences.m2 | 183 ++++++++++----------- 1 file changed, 85 insertions(+), 98 deletions(-) diff --git a/M2/Macaulay2/packages/SpectralSequences.m2 b/M2/Macaulay2/packages/SpectralSequences.m2 index b539843b338..1cc1136e57d 100644 --- a/M2/Macaulay2/packages/SpectralSequences.m2 +++ b/M2/Macaulay2/packages/SpectralSequences.m2 @@ -127,19 +127,19 @@ support FilteredComplex := List => ( FilteredComplex _ InfiniteNumber := -FilteredComplex _ ZZ := ChainComplex => (K,p) -> ( +FilteredComplex _ ZZ := Complex => (K,p) -> ( if K#?p then K#p else if p < min K then K#(min K) else if p > max K then K#(max K) ) FilteredComplex ^ InfiniteNumber := -FilteredComplex ^ ZZ := ChainComplex => (K,p) -> K_(-p) +FilteredComplex ^ ZZ := Complex => (K,p) -> K_(-p) -chainComplex FilteredComplex := ChainComplex => K -> K_infinity +complex FilteredComplex := Complex => {} >> o -> K -> K_infinity -- Returns the inclusion map from the pth subcomplex to the top -inducedMap (FilteredComplex, ZZ) := ChainComplexMap => opts -> (K,p) -> ( +inducedMap (FilteredComplex, ZZ) := ComplexMap => opts -> (K,p) -> ( if not K.cache#?inducedMaps then K.cache.inducedMaps = new MutableHashTable; if not K.cache.inducedMaps#?p then K.cache.inducedMaps#p = inducedMap(K_infinity, K_p); K.cache.inducedMaps#p) @@ -172,21 +172,21 @@ filteredComplex(List) := FilteredComplex => opts -> L -> ( if all(#L, p -> class L#p === SimplicialComplex) then ( kk := coefficientRing L#0; if opts.ReducedHomology == true then ( - C = chainComplex complex L#0; -- By default the ambient simplicial complex is the first element of the list - maps = apply(#L-1, p -> map(C, chainComplex complex L#(p+1), + C = complex L#0; -- By default the ambient simplicial complex is the first element of the list + maps = apply(#L-1, p -> map(C, complex L#(p+1), i -> sub(contract(transpose matrix{faces(i,L#0)}, matrix{faces(i,L#(p+1))}), kk)))) - else (C = truncate(chainComplex complex L#0,1); -- By default the ambient simplicial complex is the first element of the list - maps = apply(#L-1, p -> map(C, truncate(chainComplex complex L#(p+1),1), + else (C = naiveTruncation(complex L#0,1); -- By default the ambient simplicial complex is the first element of the list + maps = apply(#L-1, p -> map(C, naiveTruncation(complex L#(p+1),1), i -> sub(contract(transpose matrix{faces(i,L#0)}, matrix{faces(i,L#(p+1))}), kk)))) ) else ( maps = L; - if any(#maps, p -> class maps#p =!= ChainComplexMap) then ( + if any(#maps, p -> class maps#p =!= ComplexMap) then ( error "expected sequence of chain complexes"); C = target maps#0;-- By default the ambient chain complex is target of first map. if any(#maps, p -> target maps#p != C) then ( error "expected all map to have the same target")); - Z := image map(C, C, i -> 0*id_(C#i)); -- make zero subcomplex as a subcomplex of ambient complex + Z := image map(C, C, i -> 0*id_(C_i)); -- make zero subcomplex as a subcomplex of ambient complex P := {}; myList := {}; for p from 0 to #maps - 1 do ( @@ -205,33 +205,30 @@ filteredComplex(List) := FilteredComplex => opts -> L -> ( -- make the filtered complex associated to the "naive truncation of a chain complex" -filteredComplex ChainComplex := FilteredComplex => opts-> C->( complete C; - n := max support C; - m := min support C; +filteredComplex Complex := FilteredComplex => opts-> C->( + (n, m) := concentration C; p := length C; if p > 0 then ( - H := for i from 1 to p list inducedMap(C,truncate(C,-i)); + H := for i from 1 to p list inducedMap(C, naiveTruncation(C, -i)); filteredComplex( H, Shift => - m) ) else filteredComplex {map(C, image(0 * id_C), id_C)}--{map(C, id_C} -- now the constructor supports the zero chain complex ) - --produce the "x-filtration" of the tensor product complex. -FilteredComplex ** ChainComplex := FilteredComplex => (K,C) -> ( - xTensormodules := (p,q,T)->(apply( (T#q).cache.indices, - i-> if (i#0) <=p then - image (id_(((T#q).cache.components)#(((T#q).cache.indexComponents)#i))) - else image(0* id_(((T#q).cache.components)#(((T#q).cache.indexComponents)#i)))) ); - xTensorComplex := (T,p) ->(K := new ChainComplex; - K.ring = T.ring; - for i from min T to max T do ( - if T#?(i-1) then - K.dd_i = inducedMap( - directSum(xTensormodules(p,i-1,T) - ), - directSum(xTensormodules(p,i,T)),T.dd_i)); - K - ); +xTensormodules := (p,q,T) -> ( + apply(indices T_q, components T_q, + (ind, M) -> if ind#0 <= p + then image id_M + else image(0 * id_M))) + +xTensorComplex := (T,p) ->( + (lo, hi) := concentration T; + if lo == hi + then complex(directSum xTensormodules(p, lo, T), Base => lo) + else complex applyPairs(T.dd.map, + (i,f) -> i => inducedMap(directSum(xTensormodules(p, i-1, T)), directSum(xTensormodules(p, i, T)), f))) + +FilteredComplex ** Complex := FilteredComplex => (K,C) -> ( supp := support K_infinity; -- try to handle the boundary cases -- if supp != {} and #supp > 1 then ( @@ -254,18 +251,20 @@ filteredComplex(reverse for i from P to (N-1) list ) --produce the "y-filtration" of the tensor product complex. -ChainComplex ** FilteredComplex := FilteredComplex => (C,K) -> ( - yTensorModules := (p,q,T)->(apply( (T#q).cache.indices, - i-> if (i#1) <=p then image (id_(((T#q).cache.components)#(((T#q).cache.indexComponents)#i))) - else image(0* id_(((T#q).cache.components)#(((T#q).cache.indexComponents)#i)))) ); - yTensorComplex := (T,p) -> (K := new ChainComplex; - K.ring = T.ring; - for i from min T to max T do ( - if T#?(i-1) then - K.dd_i = inducedMap(directSum(yTensorModules(p,i-1,T)), - directSum(yTensorModules(p,i,T)),T.dd_i)); - K - ); +yTensorModules := (p,q,T)->( + apply(indices T_q, components T_q, + (ind, M) -> if ind#1 <= p + then image id_M + else image(0 * id_M))) + +yTensorComplex := (T,p) -> ( + (lo, hi) := concentration T; + if lo == hi + then complex(directSum(yTensorModules(p, lo, T), Base => lo)) + else complex applyPairs(T.dd.map, + (i,f) -> i => inducedMap(directSum(yTensorModules(p, i-1, T)), directSum(yTensorModules(p, i, T)), f))) + +Complex ** FilteredComplex := FilteredComplex => (C,K) -> ( supp := support K_infinity; -- try to handle the boundary cases -- if supp != {} and #supp > 1 then ( @@ -288,40 +287,36 @@ filteredComplex(reverse for i from P to (N-1) list ) -- produce the "x-filtration" of the Hom complex. -xmodules := (n, d, H)->( +xHomModules := (n, d, H)->( -- want components {p,q} = Hom(-p, q) with p + q = d and p <= n - apply( (H#d).cache.indices, - i -> if - (i#0) <= n then - image (id_(((H#d).cache.components)#(((H#d).cache.indexComponents)#i))) - else image(0* id_(((H#d).cache.components)#(((H#d).cache.indexComponents)#i)))) ); - - -xComplex := (T,n) -> - (K := new ChainComplex; - K.ring = T.ring; - for i from min T to max T do ( - if T#?(i-1) then - K.dd_i = inducedMap(directSum(xmodules(n,i-1,T)),directSum(xmodules(n,i,T)),T.dd_i)); - K - ) + apply(indices H_d, components H_d, + (ind, M) -> if -ind#0 <= n + then image id_M + else image(0 * id_M))) + +xHomComplex := (T,n) -> ( + (lo, hi) := concentration T; + if lo == hi + then complex(directSum(xHomModules(n, lo, T), Base => lo)) + else complex applyPairs(T.dd.map, + (i,f) -> i => inducedMap(directSum(xHomModules(n, i-1, T)), directSum(xHomModules(n, i, T)), f))) -- produce the "x-filtration" of the Hom complex. -Hom (FilteredComplex, ChainComplex):= FilteredComplex => opts -> (K, D) -> ( - C := complete D; +Hom (FilteredComplex, Complex):= FilteredComplex => opts -> (K, C) -> ( supp := support K_infinity; -- try to handle the boundary cases -- if supp != {} and #supp > 1 then ( N := - max support K_infinity; P := - min support K_infinity; H := Hom(K_infinity, C, opts); - filteredComplex(reverse for i from N to P - 1 list inducedMap(H, xComplex(H,i)), + filteredComplex(reverse for i from N to P - 1 list inducedMap(H, xHomComplex(H,i)), Shift => - N) ) else ( if #supp == 1 then ( p := min supp; h := Hom(K_infinity, C, opts); - filteredComplex( {inducedMap(h, xComplex(h, p))}, Shift => p + 1 ) + filteredComplex( {inducedMap(h, xHomComplex(h, p))}, Shift => p + 1 ) ) else( hhh := Hom(K_infinity, C, opts); @@ -332,40 +327,35 @@ Hom (FilteredComplex, ChainComplex):= FilteredComplex => opts -> (K, D) -> ( -- next are some functions used in the "y-filtration" of the Hom complex. -ymodules := (n, d, H) -> ( +yHomModules := (n, d, H) -> ( -- want components {p,q} = Hom(-p, q) with p + q = d and q <= n - apply( (H#d).cache.indices, - i -> if (i#1) <= n then - image (id_(((H#d).cache.components)#(((H#d).cache.indexComponents)#i))) - else image(0* id_(((H#d).cache.components)#(((H#d).cache.indexComponents)#i)))) - ) - + apply(indices H_d, components H_d, + (ind, M) -> if ind#1 <= n + then image id_M + else image(0 * id_M))) -yComplex := (T,n) -> - (K := new ChainComplex; - K.ring = T.ring; - for i from min T to max T do ( - if T#?(i-1) then - K.dd_i = inducedMap(directSum(ymodules(n,i-1,T)),directSum(ymodules(n,i,T)),T.dd_i)); - K - ) +yHomComplex := (T,n) -> ( + (lo, hi) := concentration T; + if lo == hi + then complex(directSum(yHomModules(n, lo, T), Base => lo)) + else complex applyPairs(T.dd.map, + (i,f) -> i => inducedMap(directSum(yHomModules(n, i-1, T)), directSum(yHomModules(n, i, T)), f))) -Hom (ChainComplex, FilteredComplex) := FilteredComplex => opts -> (D, K) -> ( - C := complete D; +Hom (Complex, FilteredComplex) := FilteredComplex => opts -> (C, K) -> ( supp := support K_infinity; -- try to handle the boundary cases -- if supp != {} and #supp > 1 then ( N := max support K_infinity; P := min support K_infinity; H := Hom(C, K_infinity, opts); - filteredComplex(reverse for i from P to N - 1 list inducedMap(H, yComplex(H,i)), + filteredComplex(reverse for i from P to N - 1 list inducedMap(H, yHomComplex(H,i)), Shift => - P) ) else ( if #supp == 1 then ( p := min supp; h := Hom(C, K_infinity, opts); - filteredComplex( {inducedMap(h, yComplex(h, p))}, Shift => - p + 1 ) + filteredComplex( {inducedMap(h, yHomComplex(h, p))}, Shift => - p + 1 ) ) else( hhh := Hom(C, K_infinity, opts); @@ -377,14 +367,14 @@ Hom (ChainComplex, FilteredComplex) := FilteredComplex => opts -> (D, K) -> ( -- I-adic filtration code -- -- the following script allows us to multiply a chain complex by an ideal -Ideal * ChainComplex := ChainComplex => (I,C) -> ( - D := new ChainComplex; - D.ring = C.ring; - apply(drop(spots C, 1), i -> D.dd_i = inducedMap(I * C_(i-1), I * C_i, C.dd_i)); - D - ) +Ideal * Complex := Complex => (I,C) -> ( + (lo, hi) := concentration C; + if lo == hi + then complex(I * C_lo, Base => lo) + else complex applyValues(C.dd.map, + f -> inducedMap(I * target f, I * source f, f))) -filteredComplex(Ideal,ChainComplex,ZZ) := FilteredComplex => opts -> (I,C,n) ->( +filteredComplex(Ideal,Complex,ZZ) := FilteredComplex => opts -> (I,C,n) ->( if n < 0 then error "expected a non-negative integer" else filteredComplex(apply(n, i -> inducedMap(C, I^(i+1) * C)), Shift => n) @@ -791,18 +781,20 @@ SpectralSequencePageMap ^ List := Matrix => (d,i)-> (d_(-i)) -- auxiliary spectral sequence stuff. filteredComplex SpectralSequence := FilteredComplex => opts -> E -> E.filteredComplex -chainComplex SpectralSequence := ChainComplex => E -> chainComplex filteredComplex E +complex SpectralSequence := Complex => {} >> opts -> E -> complex E.filteredComplex + -- given a morphism f: A --> B -- compute the connecting map -- HH_{n+1}( coker f) --> HH_n (im f) connectingMorphism = method() -connectingMorphism(ChainComplexMap,ZZ) := (a,n) -> ( +connectingMorphism(ComplexMap,ZZ) := (a,n) -> ( K := filteredComplex ({a}) ; e := spectralSequence K ; e^1 .dd_{1, n} ) + -- here are some needed functions related to Hilbert polynomials -- hilbertPolynomial ZZ := ProjectiveHilbertPolynomial => o -> (M) -> ( if M == 0 then new ProjectiveHilbertPolynomial from {} else @@ -846,24 +838,19 @@ basis (List,SpectralSequencePage) := opts -> (deg,E) -> ( -- edgeComplex = method() - edgeComplex(SpectralSequence) := (E) -> ( if E.Prune == true then error "not currently implemented for pruned spectral sequences"; - if E.Prune == true then error "not currently implemented for pruned spectral sequences"; M := select(spots E^2 .dd, i -> E^2_i != 0); l := min apply(M, i -> i#0); m := min apply(M, i -> i#1); - C := chainComplex E; + C := complex E; if M != {} then ( - chainComplex {inducedMap(E^2_{l + 1, m}, HH_(l + m + 1) C, id_(C_(l + m + 1))), + complex {inducedMap(E^2_{l + 1, m}, HH_(l + m + 1) C, id_(C_(l + m + 1))), inducedMap(HH_(l + m + 1) C, E^2_{l,m + 1}, id_(C_(l + m + 1))), E^2 .dd_{l + 2,m}, inducedMap(E^2_{l + 2, m}, HH_(l + m + 2) C, id_(C_(l + m + 2)))}) - else - (c := new ChainComplex; c.ring = E.filteredComplex _infinity .ring; - c) - ) + else complex C.ring) + - filteredHomologyObject = method() filteredHomologyObject(ZZ, ZZ,FilteredComplex) := (p,n,K) -> ( From cb14a421cc48eab940abd2232096118ef627caa6 Mon Sep 17 00:00:00 2001 From: Mahrud Sayrafi Date: Tue, 8 Jul 2025 12:32:18 -0500 Subject: [PATCH 3/8] updated docs in SpectralSequences --- M2/Macaulay2/packages/SpectralSequences.m2 | 241 +++++++++++---------- 1 file changed, 123 insertions(+), 118 deletions(-) diff --git a/M2/Macaulay2/packages/SpectralSequences.m2 b/M2/Macaulay2/packages/SpectralSequences.m2 index 1cc1136e57d..10cac1e889f 100644 --- a/M2/Macaulay2/packages/SpectralSequences.m2 +++ b/M2/Macaulay2/packages/SpectralSequences.m2 @@ -1078,7 +1078,7 @@ doc /// Example B = QQ[a..d] J = ideal vars B - C = complete res monomialCurveIdeal(B,{1,3,4}) + C = res monomialCurveIdeal(B,{1,3,4}) K = filteredComplex(J,C,4) Text Here are some higher pages of the associated spectral sequence: @@ -1272,25 +1272,25 @@ doc /// R = QQ[x,y,z,w] ; c2 = matrix(R,{{1},{0}}) ; c1 = matrix(R,{{0,1}}) ; - C = chainComplex({c1,c2}) + C = complex({c1,c2}) D_2 = image matrix(R,{{1}}); D_1 = image matrix(R,{{1,0},{0,0}}); D_0 = image matrix(R,{{1}}); - D = chainComplex({inducedMap(D_0,D_1,C.dd_1),inducedMap(D_1,D_2,C.dd_2)}) + D = complex({inducedMap(D_0,D_1,C.dd_1),inducedMap(D_1,D_2,C.dd_2)}) E_2 = image matrix(R,{{0}}); E_1 = image matrix(R,{{1,0},{0,0}}); E_0 = image matrix(R,{{1}}); - E = chainComplex({inducedMap(E_0,E_1,C.dd_1),inducedMap(E_1,E_2,C.dd_2)}) + E = complex({inducedMap(E_0,E_1,C.dd_1),inducedMap(E_1,E_2,C.dd_2)}) Text We now make our chain complex maps. Example - d = chainComplexMap(C,D,apply(spots C, i-> inducedMap(C_i,D_i,id_C _i))) - e = chainComplexMap(C,E,apply(spots C, i->inducedMap(C_i,E_i, id_C _i))) + d = map(C,D,apply(spots C, i-> inducedMap(C_i,D_i,id_C _i))) + e = map(C,E,apply(spots C, i->inducedMap(C_i,E_i, id_C _i))) Text We can check that these are indeed chain complex maps: Example - isChainComplexMap d - isChainComplexMap e + isWellDefined d + isWellDefined e Text Now, given the list of chain complex maps $\{d, e\}$, we obtain a filtration of $C$ by: @@ -1429,7 +1429,7 @@ doc /// Text We can check that the homology of the simplicial complex twoSphere agrees with that of $\mathbb{S}^2$. Example - C = truncate(chainComplex complex twoSphere,1) + C = naiveTruncation(complex twoSphere, 1) prune HH C Text We now write down our simplicial complex whose topological realization @@ -1441,7 +1441,7 @@ doc /// Again we can check that we've entered a simplicial complex whose homology agrees with that of the real projective plane. Example - B = truncate(chainComplex complex realProjectivePlane,1) + B = naiveTruncation(complex realProjectivePlane, 1) prune HH B Text We now compute the fibers of the anti-podal quotient map @@ -1496,7 +1496,7 @@ doc/// We can check that the homology of this simplicial complex agrees with that of the Klein Bottle: Example - C = truncate(chainComplex complex Delta,1) + C = naiveTruncation(complex Delta, 1) prune HH C Text Let $S$ be the simplicial complex with facets $\{A_0 A_1, A_0 A_2, A_1 A_2\}$. Then $S$ is a triangulation of $S^1$. The simplicial map @@ -1547,7 +1547,7 @@ doc /// $\Delta$ agrees with that of the torus $\mathbb{S}^1 \times \mathbb{S}^1 $ Example - C = truncate(chainComplex complex Delta,1) + C = naiveTruncation(complex Delta, 1) prune HH C Text Let $S$ be the simplicial complex with facets $\{A_0 A_1, A_0 A_2, A_1 A_2\}$. Then $S$ is a triangulation of $S^1$. The simplicial map @@ -1597,8 +1597,8 @@ doc /// B = B_*/(x -> x^2)//ideal; -- need to take a large enough power. -- it turns out that 2 is large enough for this example - G = complete res image gens B; - F = koszul gens I; + G = res image gens B; + F = koszulComplex gens I; K = Hom(G, filteredComplex(F)); E = prune spectralSequence K; E^1 @@ -1654,11 +1654,10 @@ doc /// M = intersect(ideal(a_0,a_1),ideal(b_0,b_1)) ; -- irrelevant ideal M = M_*/(x -> x^5)//ideal ; -- Suitably high Frobenius power of M G = res image gens M ; - I = ideal random(R^1, R^{{-3,-3}}) -- ideal of C - b = chainComplex gradedModule R^{{1,0}} -- make line bundle a chain complex - a = chainComplex gradedModule R^{{-2,-3}} + b = complex R^{{1,0}} -- make line bundle a chain complex + a = complex R^{{-2,-3}} -- make the map OO(-2, -3) --> OO(1,0) - f = chainComplexMap(b, a,{random(R^1, R^{{-3,-3}})}) ; + f = randomComplexMap(b, a, Degree => 0) K = filteredComplex ({Hom(G,f)}) ; -- the two step filtered complex we want E = prune spectralSequence K ; Text @@ -1944,9 +1943,9 @@ doc /// f = map(S,R,{s^2,s*t,t^2}); N = coker vars S; M = coker vars R --; - F := complete res N; + F := res N; pushFwdF := pushFwd(f,F); - G := complete res M; + G := res M; E := spectralSequence(filteredComplex(G) ** pushFwdF); EE := spectralSequence(G ** (filteredComplex pushFwdF)); e = prune E; @@ -2315,7 +2314,7 @@ doc /// Example B = QQ[a..d]; J = ideal vars B; - C = complete res monomialCurveIdeal(B,{1,3,4}); + C = res monomialCurveIdeal(B,{1,3,4}); K = filteredComplex(J,C,4); Text The infinity page of the resulting spectral sequence is computed below. @@ -2405,7 +2404,7 @@ doc /// Example B = QQ[a..d]; J = ideal vars B; - C = complete res monomialCurveIdeal(B,{1,3,4}); + C = res monomialCurveIdeal(B,{1,3,4}); K = filteredComplex(J,C,4); Text We compute an example of a pruning map below. @@ -2435,13 +2434,13 @@ doc /// doc /// Key - (spots, ChainComplex) + (spots, Complex) Headline which spots does the given chain complex has a module. Usage s = spots L Inputs - L:ChainComplex + L:Complex Outputs s:List Description @@ -2462,7 +2461,7 @@ doc /// Inputs L:List or - L:ChainComplex + L:Complex or L:SpectralSequence ReducedHomology => Boolean @@ -2558,7 +2557,7 @@ doc /// Example B = QQ[a..d]; J = ideal vars B; - C = complete res monomialCurveIdeal(B,{1,3,4}); + C = res monomialCurveIdeal(B,{1,3,4}); K = filteredComplex(J,C,4); E = spectralSequence K Text @@ -2594,7 +2593,7 @@ doc /// Example B = QQ[a..d]; J = ideal vars B; - C = complete res monomialCurveIdeal(B,{1,3,4}); + C = res monomialCurveIdeal(B,{1,3,4}); K = filteredComplex(J,C,4); E = spectralSequence K Text @@ -2609,24 +2608,36 @@ doc /// "Examples of filtered complexes and spectral sequences" /// - - doc /// - Key - (truncate, ChainComplex, ZZ) - Headline - compute the hard truncation of a chain complex - Description - Text - Computes the hard truncation of a chain complex as a specified homological degree. - Example - B = QQ[a..d]; - C = koszul vars B - truncate(C,1) - truncate(C,-1) - truncate(C,-10) - truncate(C,10) -/// + Key + (naiveTruncation, Complex, ZZ) + Headline + compute the hard truncation of a chain complex + Usage + naiveTruncation(C, n) + Inputs + C:Complex + n:ZZ + Outputs + :Complex + Description + Text + This method returns the naive truncation of $C$ by truncating + the low homological degrees if $n$ is positive (i.e. from left) + and high homological degrees if $n$ is negative (i.e. from right). + Example + B = QQ[a..d]; + C = (koszulComplex vars B)[2] + naiveTruncation(C, 10) + naiveTruncation(C, 2) + naiveTruncation(C, 1) + naiveTruncation(C, 0) + naiveTruncation(C,-1) + naiveTruncation(C,-2) + naiveTruncation(C,-10) + SeeAlso + (naiveTruncation, Complex, ZZ, ZZ) +/// doc /// Key @@ -2648,7 +2659,7 @@ doc /// Example B = QQ[a..d]; J = ideal vars B; - C = complete res monomialCurveIdeal(B,{1,3,4}); + C = res monomialCurveIdeal(B,{1,3,4}); K = filteredComplex(J,C,4); Text We compute an example of a pruning map below. @@ -2664,7 +2675,7 @@ doc /// doc /// Key - (support,ChainComplex) + (support,Complex) Headline nonzero parts of a chain complex Description @@ -2673,13 +2684,13 @@ doc /// Example A = QQ[x,y]; - C = koszul vars A + C = koszulComplex vars A support C - D = truncate(C,1) + D = naiveTruncation(C, 1) spots D support D SeeAlso - (spots, ChainComplex) + (spots, Complex) /// @@ -2697,7 +2708,7 @@ doc /// Example B = QQ[a..d]; J = ideal vars B; - C = complete res monomialCurveIdeal(B,{1,3,4}); + C = res monomialCurveIdeal(B,{1,3,4}); K = filteredComplex(J,C,4); Text We compute an example of a pruning map below. @@ -2736,38 +2747,38 @@ doc /// R = QQ[x,y,z,w] d2 = matrix(R,{{1},{0}}) d1 = matrix(R,{{0,1}}) - C = chainComplex({d1,d2}) + C = complex({d1,d2}) Text We now make the modules of the another chain complex which we will label D. Example D_2 = image matrix(R,{{1}}) D_1 = image matrix(R,{{1,0},{0,0}}) D_0 = image matrix(R,{{1}}) - D = chainComplex({inducedMap(D_0,D_1,C.dd_1),inducedMap(D_1,D_2,C.dd_2)}) + D = complex({inducedMap(D_0,D_1,C.dd_1),inducedMap(D_1,D_2,C.dd_2)}) Text Now make a chain complex map. Example - d = chainComplexMap(C,D,apply(spots C, i-> inducedMap(C_i,D_i,id_C _i))) - isChainComplexMap d - d == chainComplexMap(C,D,{inducedMap(C_0,D_0,id_(C_0)),inducedMap(C_1,D_1,id_(C_1)),inducedMap(C_2,D_2,id_(C_2))}) + d = map(C,D,{inducedMap(C_0,D_0,id_(C_0)),inducedMap(C_1,D_1,id_(C_1)),inducedMap(C_2,D_2,id_(C_2))}) + isWellDefined d Text We now make the modules of another chain complex which we will label E. Example E_2 = image matrix(R,{{0}}) E_1 = image matrix(R,{{1,0},{0,0}}) E_0 = image matrix(R,{{1}}) - E = chainComplex({inducedMap(E_0,E_1,C.dd_1),inducedMap(E_1,E_2,C.dd_2)}) + E = complex({inducedMap(E_0,E_1,C.dd_1),inducedMap(E_1,E_2,C.dd_2)}) Text Now make a chain complex map. Example - e = chainComplexMap(C,E,apply(spots C, i->inducedMap(C_i,D_i, id_C _i))) + e = map(C,E,{inducedMap(C_0,E_0,id_(C_0)),inducedMap(C_1,E_1,id_(C_1)),inducedMap(C_2,E_2,id_(C_2))}) + isWellDefined e Text Now make a filtered complex from a list of chain complex maps. Example K = filteredComplex({d,e}) Text We can make a filtered complex, with a specified minimum filtration degree - from a list of ChainComplexMaps by using the Shift option. + from a list of ComplexMaps by using the Shift option. Example L = filteredComplex({d,e},Shift => 1) M = filteredComplex({d,e},Shift => -1) @@ -2790,13 +2801,13 @@ doc /// doc /// Key - (filteredComplex, ChainComplex) + (filteredComplex, Complex) Headline obtain a filtered complex from a chain complex Usage K = filteredComplex C Inputs - C: ChainComplex + C: Complex -- these options don't do anything for this constructor. ReducedHomology => Boolean Shift => ZZ @@ -2806,12 +2817,11 @@ doc /// Text Produces the filtered complex obtained by successively truncating the complex. Example - needsPackage "SpectralSequences" A = QQ[x,y] - C = koszul vars A + C = koszulComplex vars A K = filteredComplex C SeeAlso - (truncate, ChainComplex,ZZ) + (naiveTruncation, Complex, ZZ, ZZ) /// doc /// @@ -2848,10 +2858,9 @@ doc /// Example C = filteredComplex E SeeAlso - --(_, FilteredComplex,InfiniteNumber) - --(^,FilteredComplex,InfiniteNumber) -/// - + (symbol _, FilteredComplex, InfiniteNumber) + (symbol ^, FilteredComplex, InfiniteNumber) +/// doc /// Key @@ -2876,7 +2885,7 @@ doc /// Example B = QQ[a..d]; J = ideal vars B; - C = complete res monomialCurveIdeal(B,{1,3,4}); + C = res monomialCurveIdeal(B,{1,3,4}); K = filteredComplex(J,C,4); Text We compute the degree $0$ piece of the $E^3$ page below. @@ -2908,7 +2917,7 @@ doc /// Example B = QQ[a..d]; J = ideal vars B; - C = complete res monomialCurveIdeal(B,{1,3,4}); + C = res monomialCurveIdeal(B,{1,3,4}); K = filteredComplex(J,C,4); Text We compute the degree $0$ piece of the $E^3$ page below. @@ -2919,23 +2928,23 @@ doc /// doc /// Key - (chainComplex, FilteredComplex) + (complex, FilteredComplex) Headline the ambient chain complex of a filtered complex Usage - C = chainComplex K + C = complex K Inputs K:FilteredComplex Outputs - C:ChainComplex + C:Complex Description Text Returns the ambient chain complex of the filtered complex. Example A = QQ[x,y]; - C = koszul vars A + C = koszulComplex vars A K = filteredComplex C; - chainComplex K + complex K K_infinity SeeAlso (symbol _, FilteredComplex, ZZ) @@ -2968,7 +2977,7 @@ doc /// Example B = QQ[a..d]; J = ideal vars B; - C = complete res monomialCurveIdeal(B,{1,3,4}); + C = res monomialCurveIdeal(B,{1,3,4}); K = filteredComplex(J,C,4); Text Compare some pages of the non-pruned version of the spectral sequence @@ -3010,7 +3019,7 @@ doc /// Example B = QQ[a..d]; J = ideal vars B; - C = complete res monomialCurveIdeal(B,{1,3,4}); + C = res monomialCurveIdeal(B,{1,3,4}); K = filteredComplex(J,C,4); Text Compare some pruned and non-prunded pages the spectral sequence $E$ below. @@ -3045,22 +3054,22 @@ doc /// Returns the spectral sequence associated to the filtered complex. Example A = QQ[x,y]; - C = koszul vars A + C = koszulComplex vars A K = filteredComplex C; E = spectralSequence K /// doc /// Key - (Hom, FilteredComplex, ChainComplex) - (Hom, ChainComplex, FilteredComplex) + (Hom, FilteredComplex, Complex) + (Hom, Complex, FilteredComplex) Headline the filtered Hom complex Usage f = Hom(K,C) Inputs K:FilteredComplex - C:ChainComplex + C:Complex Outputs f:FilteredComplex Description @@ -3079,24 +3088,24 @@ doc /// doc /// Key - (chainComplex, SpectralSequence) + (complex, SpectralSequence) Headline the underlying chain complex of a Spectral Sequence Usage - K = chainComplex E + K = complex E Inputs E:SpectralSequence Outputs - K:ChainComplex + K:Complex Description Text Returns the underlying chain complex of a spectral sequence. Example A = QQ[x,y]; - C = koszul vars A + C = koszulComplex vars A K = filteredComplex C; E = spectralSequence K - chainComplex E + complex E /// doc /// @@ -3122,7 +3131,7 @@ doc /// Example B = QQ[a..d]; J = ideal vars B; - C = complete res monomialCurveIdeal(B,{1,3,4}); + C = res monomialCurveIdeal(B,{1,3,4}); K = filteredComplex(J,C,4); Text @@ -3214,7 +3223,7 @@ doc /// Example B = QQ[a..d]; J = ideal vars B; - C = complete res monomialCurveIdeal(B,{1,3,4}); + C = res monomialCurveIdeal(B,{1,3,4}); K = filteredComplex(J,C,4); Text @@ -3255,7 +3264,7 @@ doc /// Example B = QQ[a..d]; J = ideal vars B; - C = complete res monomialCurveIdeal(B,{1,3,4}); + C = res monomialCurveIdeal(B,{1,3,4}); K = filteredComplex(J,C,4); Text We compute a map on the third page of the spectral sequence associated to $K$. @@ -3289,7 +3298,7 @@ doc /// Example B = QQ[a..d]; J = ideal vars B; - C = complete res monomialCurveIdeal(B,{1,3,4}); + C = res monomialCurveIdeal(B,{1,3,4}); K = filteredComplex(J,C,4); Text We compute a map on the third page of the spectral sequence associated to $K$. @@ -3323,7 +3332,7 @@ doc /// Example B = QQ[a..d]; J = ideal vars B; - C = complete res monomialCurveIdeal(B,{1,3,4}); + C = res monomialCurveIdeal(B,{1,3,4}); K = filteredComplex(J,C,4); Text @@ -3378,7 +3387,7 @@ doc /// (Using cohomological or upper indexing conventions.) The relationship $E^{-i,-j} = E_{i,j}$ holds. Example A = QQ[x,y] - C = koszul vars A; + C = koszulComplex vars A; K = filteredComplex C; E = spectralSequence K E_0 @@ -3408,7 +3417,7 @@ doc /// (Using homological or lower indexing conventions.) The relationship $E_{i,j} = E^{-i,-j}$ holds. Example A = QQ[x,y] - C = koszul vars A; + C = koszulComplex vars A; K = filteredComplex C; E = spectralSequence K E^0 @@ -3421,15 +3430,15 @@ doc /// doc /// Key - (symbol **, ChainComplex, FilteredComplex) - (symbol **, FilteredComplex, ChainComplex) + (symbol **, Complex, FilteredComplex) + (symbol **, FilteredComplex, Complex) Headline filtered tensor product of complexes Usage KK = C ** K KK = K ** C Inputs - C:ChainComplex + C:Complex K:FilteredComplex Outputs KK:FilteredComplex @@ -3440,26 +3449,26 @@ doc /// The following example illustrates the syntax. Example A = QQ[x,y]; - B = koszul vars A; - C = koszul vars A; + B = koszulComplex vars A; + C = koszulComplex vars A; F' = (filteredComplex B) ** C F'' = B ** (filteredComplex C) SeeAlso "Filtrations and tensor product complexes" /// - + doc /// Key - (tensor, RingMap, ChainComplex) + (tensor, RingMap, Complex) Headline tensor product of a chain complex by a ring map Usage D = tensor(f,C) Inputs f:RingMap - C:ChainComplex + C:Complex Outputs - D:ChainComplex + D:Complex Description Text Given a ring map R -> S and a chain complex over R, @@ -3488,7 +3497,7 @@ doc /// K:FilteredComplex i:ZZ Outputs - f:ChainComplexMap + f:ComplexMap Description Text Returns the chain complex map specifying the inclusion of the i piece @@ -3496,7 +3505,7 @@ doc /// complex to the ambient chain complex. Example A = QQ[x,y]; - C = koszul vars A; + C = koszulComplex vars A; K = filteredComplex C inducedMap(K,1) /// @@ -3514,14 +3523,14 @@ doc /// j:ZZ an integer, infinity, or -infinity Outputs - C:ChainComplex + C:Complex Description Text Returns the chain complex in (homological) filtration degree j. The relationship $K _ j = K ^{(-j)}$ holds. Example A = QQ[x,y]; - C = koszul vars A; + C = koszulComplex vars A; K = filteredComplex C K_0 K_1 @@ -3550,14 +3559,14 @@ doc /// j:ZZ an integer, infinity, or -infinity Outputs - C:ChainComplex + C:Complex Description Text Returns the chain complex in (cohomological) filtration degree j. The relationship $K ^ j = K _{(-j)}$ holds. Example A = QQ[x,y]; - C = koszul vars A; + C = koszulComplex vars A; K = filteredComplex C K_0 K_1 @@ -3582,7 +3591,7 @@ doc /// Usage g = connectingMorphism(f, n) Inputs - f:ChainComplexMap + f:ComplexMap n:ZZ Outputs g:Matrix @@ -3594,13 +3603,13 @@ doc /// doc /// Key - (connectingMorphism, ChainComplexMap,ZZ) + (connectingMorphism, ComplexMap,ZZ) Headline use spectral sequences to compute connecting morphisms Usage g = connectingMorphism(f, n) Inputs - f:ChainComplexMap + f:ComplexMap n:ZZ Outputs g:Matrix @@ -3743,10 +3752,6 @@ doc /// /// ---doc /// --- Key --- associatedGradedHomologyObject ---/// doc /// Key @@ -3834,7 +3839,7 @@ doc /// Inputs E: SpectralSequence Outputs - C: ChainComplex + C: Complex Description Text Suppose that $E$ is a spectral sequence with the properties that: @@ -3886,14 +3891,14 @@ doc /// doc /// Key - (filteredComplex, Ideal, ChainComplex, ZZ) + (filteredComplex, Ideal, Complex, ZZ) Headline I-adic filtrations of chain complexes Usage K = filteredComplex(I,C,n) Inputs I: Ideal - C: ChainComplex + C: Complex n: ZZ Outputs K: FilteredComplex @@ -3903,7 +3908,7 @@ doc /// Example B = QQ[a..d] J = ideal vars B - C = complete res monomialCurveIdeal(B,{1,3,4}) + C = res monomialCurveIdeal(B,{1,3,4}) K = filteredComplex(J,C,4) Text Here are higher some pages of the associated spectral sequence: From 61962f3bca33bd4c712130154e388498b02cb481 Mon Sep 17 00:00:00 2001 From: Mahrud Sayrafi Date: Tue, 8 Jul 2025 12:33:12 -0500 Subject: [PATCH 4/8] updated tests in SpectralSequences --- M2/Macaulay2/packages/SpectralSequences.m2 | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/M2/Macaulay2/packages/SpectralSequences.m2 b/M2/Macaulay2/packages/SpectralSequences.m2 index 10cac1e889f..24a5eabbb3d 100644 --- a/M2/Macaulay2/packages/SpectralSequences.m2 +++ b/M2/Macaulay2/packages/SpectralSequences.m2 @@ -4028,19 +4028,14 @@ doc /// TEST /// -restart; -needsPackage "SpectralSequences"; A = QQ[a,b,c]; -C = new ChainComplex; -C.ring = A; +C = complex A^0 K = filteredComplex C; assert(K_0 == C); assert(K_1 == C); /// TEST /// -restart; -needsPackage "SpectralSequences"; A = QQ[a,b,c]; D = simplicialComplex {a*b*c}; F2D = D; @@ -4064,8 +4059,6 @@ assert(all(keys support e^5, j -> isIsomorphism homologyIsomorphism(e,j#0,j#1,5) /// TEST /// -restart -needsPackage "SpectralSequences"; -- The following example is taken from p. 127, Fig 7.2 of -- Zomorodian's "Topology for computing" A = ZZ [s,t,u,v,w] ; @@ -4120,8 +4113,6 @@ assert(all(keys support e^12, j -> isIsomorphism homologyIsomorphism(e,j#0,j#1,1 /// TEST /// -restart -needsPackage "SpectralSequences"; A = QQ[a,b,c,d]; D = simplicialComplex {a*d*c, a*b, a*c, b*c}; F2D = D; @@ -4159,11 +4150,9 @@ assert(all(keys support e^12, j -> isIsomorphism homologyIsomorphism(e,j#0,j#1,1 /// TEST /// -restart -needsPackage "SpectralSequences"; B = QQ[a..d]; J = ideal vars B; -C = complete res monomialCurveIdeal(B,{1,3,4}); +C = res monomialCurveIdeal(B,{1,3,4}); K = filteredComplex(J,C,4); e = prune spectralSequence K; assert(all(keys support e^0, j -> isIsomorphism homologyIsomorphism(e,j#0,j#1,0))) @@ -4175,8 +4164,6 @@ assert(all(keys support e^4, j -> isIsomorphism homologyIsomorphism(e,j#0,j#1,4) TEST /// -restart -needsPackage "SpectralSequences"; S = ZZ/101[x,y]; I = ideal(x^2,x*y,y^2); R = S/I; @@ -4206,7 +4193,3 @@ installPackage("SpectralSequences", RemakeAllDocumentation => true) check "SpectralSequences"; viewHelp SpectralSequences ------------------------------------------ - -Status API Training Shop Blog About -© 2016 GitHub, Inc. Terms Privacy Security Contact Help - From 88ccc7769f556fc5c5b29492114890870019c17d Mon Sep 17 00:00:00 2001 From: Mahrud Sayrafi Date: Tue, 8 Jul 2025 15:11:02 -0500 Subject: [PATCH 5/8] fixed the filteredComplex(List) constructor --- M2/Macaulay2/packages/SpectralSequences.m2 | 67 +++++++++++----------- 1 file changed, 35 insertions(+), 32 deletions(-) diff --git a/M2/Macaulay2/packages/SpectralSequences.m2 b/M2/Macaulay2/packages/SpectralSequences.m2 index 24a5eabbb3d..f211d49499a 100644 --- a/M2/Macaulay2/packages/SpectralSequences.m2 +++ b/M2/Macaulay2/packages/SpectralSequences.m2 @@ -165,38 +165,41 @@ filteredComplex = method(Options => { ReducedHomology => true}) filteredComplex(List) := FilteredComplex => opts -> L -> ( - local maps; - local C; - if #L === 0 - then error "expected at least one chain complex map or simplicial complex"; - if all(#L, p -> class L#p === SimplicialComplex) then ( - kk := coefficientRing L#0; - if opts.ReducedHomology == true then ( - C = complex L#0; -- By default the ambient simplicial complex is the first element of the list - maps = apply(#L-1, p -> map(C, complex L#(p+1), - i -> sub(contract(transpose matrix{faces(i,L#0)}, matrix{faces(i,L#(p+1))}), kk)))) - else (C = naiveTruncation(complex L#0,1); -- By default the ambient simplicial complex is the first element of the list - maps = apply(#L-1, p -> map(C, naiveTruncation(complex L#(p+1),1), - i -> sub(contract(transpose matrix{faces(i,L#0)}, matrix{faces(i,L#(p+1))}), kk)))) - ) - else ( - maps = L; - if any(#maps, p -> class maps#p =!= ComplexMap) then ( - error "expected sequence of chain complexes"); - C = target maps#0;-- By default the ambient chain complex is target of first map. - if any(#maps, p -> target maps#p != C) then ( - error "expected all map to have the same target")); - Z := image map(C, C, i -> 0*id_(C_i)); -- make zero subcomplex as a subcomplex of ambient complex - P := {}; - myList := {}; - for p from 0 to #maps - 1 do ( - myList = myList | - {#maps - (p+1) -opts.Shift => image maps#p}; - ); - if myList != {} then (P = {(#maps-opts.Shift) => C} | myList) - else P = { - opts.Shift => C} ; - if (last P)#1 != Z then (P = P | {(-1-opts.Shift) => Z}); - return new FilteredComplex from P | {symbol zero => (ring C)^0, symbol cache => new CacheTable}) + if #L == 0 then error "expected at least one complex map or simplicial complex"; + if not uniform L then error "expected a list of complex maps or simplicial complexes"; + -- + maps := if instance(L#0, SimplicialComplex) then ( + kk := coefficientRing L#0; + if opts.ReducedHomology == true then ( + -- By default the ambient simplicial complex is the first element of the list + C := complex L#0; + apply(#L-1, p -> map(C, complex L#(p+1), + i -> sub(contract(transpose matrix{faces(i,L#0)}, matrix{faces(i,L#(p+1))}), kk)))) + else ( + -- By default the ambient simplicial complex is the first element of the list + C = complex L#0; + C = naiveTruncation(C, 1); + apply(#L-1, p -> map(C, naiveTruncation(complex L#(p+1), 1), + i -> sub(contract(transpose matrix{faces(i,L#0)}, matrix{faces(i,L#(p+1))}), kk)))) + ) + else if instance(L#0, ComplexMap) then ( + -- By default the ambient chain complex is target of first map. + C = target L#0; + if same apply(L, target) then L + else error "expected all maps to have the same target") + else error "expected a list of complex maps or simplicial complexes"; + -- + Z := image map(C, C, i -> 0*id_(C_i)); -- make zero subcomplex as a subcomplex of ambient complex + P := {}; + myList := {}; + for p from 0 to #maps - 1 do ( + myList = myList | + {#maps - (p+1) -opts.Shift => image maps#p}; + ); + if myList != {} then (P = {(#maps-opts.Shift) => C} | myList) + else P = { - opts.Shift => C} ; + if (last P)#1 != Z then (P = P | {(-1-opts.Shift) => Z}); + return new FilteredComplex from P | {symbol zero => (ring C)^0, symbol cache => new CacheTable}) -------------------------------------------------------------------------------- From c963094cf4a6f234eb6c80ed4d44529204802d88 Mon Sep 17 00:00:00 2001 From: Mahrud Sayrafi Date: Tue, 8 Jul 2025 13:04:14 -0500 Subject: [PATCH 6/8] fixed the filteredComplex(Complex) constructor --- M2/Macaulay2/packages/SpectralSequences.m2 | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/M2/Macaulay2/packages/SpectralSequences.m2 b/M2/Macaulay2/packages/SpectralSequences.m2 index f211d49499a..82b1b44cb15 100644 --- a/M2/Macaulay2/packages/SpectralSequences.m2 +++ b/M2/Macaulay2/packages/SpectralSequences.m2 @@ -208,14 +208,12 @@ filteredComplex(List) := FilteredComplex => opts -> L -> ( -- make the filtered complex associated to the "naive truncation of a chain complex" -filteredComplex Complex := FilteredComplex => opts-> C->( - (n, m) := concentration C; - p := length C; - if p > 0 then ( - H := for i from 1 to p list inducedMap(C, naiveTruncation(C, -i)); - filteredComplex( H, Shift => - m) ) - else filteredComplex {map(C, image(0 * id_C), id_C)}--{map(C, id_C} -- now the constructor supports the zero chain complex - ) +filteredComplex Complex := FilteredComplex => opts -> C -> ( + (lo, hi) := concentration C; + if lo == hi + then filteredComplex{ map(C, image(0 * id_C), id_C) } + else filteredComplex(Shift => -lo, + apply(hi-lo, i -> inducedMap(C, naiveTruncation(C, lo, hi-i-1))))) --produce the "x-filtration" of the tensor product complex. xTensormodules := (p,q,T) -> ( From 0130943536ce902a93f488c109e29e079cebbd74 Mon Sep 17 00:00:00 2001 From: Mahrud Sayrafi Date: Tue, 8 Jul 2025 15:05:48 -0500 Subject: [PATCH 7/8] fixed an indexing bug in SpectralSequences --- M2/Macaulay2/packages/SpectralSequences.m2 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/M2/Macaulay2/packages/SpectralSequences.m2 b/M2/Macaulay2/packages/SpectralSequences.m2 index 82b1b44cb15..9b68288dcf4 100644 --- a/M2/Macaulay2/packages/SpectralSequences.m2 +++ b/M2/Macaulay2/packages/SpectralSequences.m2 @@ -567,7 +567,7 @@ SpectralSequence ^ InfiniteNumber:= -- again trying to handle the case of the zero complex -- if min K_(infinity) < infinity and max K_infinity > - infinity then ( for p from min K to max K do ( - for q from - p + min K_(infinity) to max K_(infinity) do ( + for q from -p + min K_(infinity) to max K_(infinity) + 1 do ( if E.Prune == false then H#{p,q} = epq(K,p,q,s) else H#{p,q} = prune epq(K,p,q,s) ); @@ -637,7 +637,7 @@ page SpectralSequencePage := Page => opts -> E -> ( -- again trying to handle the case of the zero complex -- if min K_(infinity) < infinity and max K_infinity > - infinity then ( for p from min K to max K do ( - for q from -p + min K_(infinity) to max K_(infinity) do ( + for q from -p + min K_(infinity) to max K_(infinity) + 1 do ( -- H#{p,q} = E^s_{p,q} if E.Prune == false then H#{p,q} = epq(K,p,q,s) else H#{p,q} = prune epq(K,p,q,s) From c372dd059c2d39de5f1bde68e4fe2f2807b7ed17 Mon Sep 17 00:00:00 2001 From: Mahrud Sayrafi Date: Tue, 8 Jul 2025 15:21:28 -0500 Subject: [PATCH 8/8] updated version of SpectralSequences --- M2/Macaulay2/packages/SpectralSequences.m2 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/M2/Macaulay2/packages/SpectralSequences.m2 b/M2/Macaulay2/packages/SpectralSequences.m2 index 9b68288dcf4..06bb5436a45 100644 --- a/M2/Macaulay2/packages/SpectralSequences.m2 +++ b/M2/Macaulay2/packages/SpectralSequences.m2 @@ -18,8 +18,8 @@ newPackage( "SpectralSequences", -- AuxiliaryFiles => true, - Version => "1.0", - Date => "20 September 2016", + Version => "1.1", + Date => "8 July 2025", Authors => { { Name => "David Berlekamp",