diff --git a/M2/Macaulay2/packages/CotangentSchubert.m2 b/M2/Macaulay2/packages/CotangentSchubert.m2 index 6ac03912ae2..55b3c77dc00 100644 --- a/M2/Macaulay2/packages/CotangentSchubert.m2 +++ b/M2/Macaulay2/packages/CotangentSchubert.m2 @@ -1,13 +1,13 @@ newPackage( "CotangentSchubert", AuxiliaryFiles => true, - Version => "0.71", - Date => "25 Jul 2023", -- "22 Mar 2021", + Version => "0.8", + Date => "15 June 2026", -- "22 Mar 2021", Authors => {{Name => "Paul Zinn-Justin", Email => "pzinn@unimelb.edu.au", HomePage => "http://blogs.unimelb.edu.au/paul-zinn-justin/"}}, Headline => "Cotangent Schubert calculus", - Keywords => {"Intersection Theory"}, + Keywords => {"Intersection Theory", "Flag Varieties", "Equivariant Cohomology"}, PackageImports => {"VectorGraphics"}, AuxiliaryFiles => true, DebuggingMode => false, @@ -51,11 +51,23 @@ multidoc /// References: @BR{}@ [1] A. Knutson and P. Zinn-Justin, Schubert puzzles and integrability I: invariant trilinear forms, + Communications of the American Mathematical Society 6:1-67, @HREF{"http://arxiv.org/abs/1706.10019","arXiv:1706.10019"}@. @BR{}@ [2] A. Knutson and P. Zinn-Justin, Schubert puzzles and integrability II: multiplying motivic Segre classes, + Communications of the American Mathematical Society 6:68–152, @HREF{"http://arxiv.org/abs/2102.00563","arXiv:2102.00563"}@. @BR{}@ [3] A. Knutson and P. Zinn-Justin, Schubert puzzles and integrability III: separated descents, @HREF{"http://arxiv.org/abs/2306.13855","arXiv:2306.13855"}@. + Node + Key + LabelList + Headline + A list encoding a fixed point or puzzle label + Description + Text + @TT "LabelList"@ is a subtype of @TO{List}@ used to encode fixed points of flag + varieties and the corresponding labels of puzzles. The label list returned by + @TO{setupCotangent}@ consists of objects of this type. Node Key setupCotangent @@ -96,6 +108,31 @@ multidoc /// Text the first output is a "diagonal algebra", i.e., a vector space over @TT "FF"@ with componentwise product. The last two outputs are the same as above. + Node + Key + Partial + Headline + Choose the partial or full flag variety ring + Description + Text + This boolean option applies to class computations after using @TO{setupCotangent}@ with + @TT "Presentation=>Borel"@. Setting @TT "Partial=>true"@ returns a class in the + cohomology or K-theory ring @TT "A"@ of the specified partial flag variety, while + @TT "Partial=>false"@ returns the corresponding class in the ring @TT "B"@ of the + full flag variety. + + The option is accepted by @TO{tautoClass}@, @TO{zeroSection}@, + @TO{dualZeroSection}@, @TO{canonicalClass}@, and the class families + @TO{sClass}@, @TO{stableClass}@, @TO{segreClass}@, @TO{chernClass}@, + @TO{schubertClass}@ and their primed variants. + + When the ring @TT "A"@ is supplied explicitly, the default is @TT "Partial=>true"@. + When @TT "B"@ is supplied, or when the ring argument is omitted, the default is + @TT "Partial=>false"@. + Example + (A,B,FF,I) = setupCotangent(2,4,Presentation=>Borel,Equivariant=>false); + schubertClass("0101",Partial=>true) + schubertClass("0101",Partial=>false) Node Key chernClass @@ -194,16 +231,18 @@ multidoc /// Headline Compute the class of a tautological bundle Usage - tautoClass (i,j) - tautoClass (i,j,A) + tautoClass (j,i) + tautoClass (j,i,A) Inputs - i : ZZ j : ZZ + i : ZZ A : Ring Description Text - This function computes the i-th Chern class of the j-th tautological bundle of the flag variety whose K-theory (or cohomology) + This function computes the j-th Chern class of the i-th tautological bundle of the flag variety whose K-theory (or cohomology) ring is given by @TT "A"@. If @TT "A"@ is not specified, then the ring that was defined last is used. + Example + (A,B,FF,I) = setupCotangent(2,3,Presentation=>Borel); {tautoClass(1,1,A),tautoClass(2,1,A),tautoClass(1,2,A)} Node Key pushforwardToPoint @@ -267,9 +306,10 @@ multidoc /// Class of the canonical bundle of a flag variety Description Text - This function returns the class of the canonical bundle of the flag variety - in the cohomology ring given as argument (or the last ring defined with @TO {setupCotangent}@ - if no argument is given). + This function returns the K-theory class of the canonical bundle of the flag variety + when @TT "Ktheory=>true"@, and its first Chern class when @TT "Ktheory=>false"@. + The ring is given as argument, or is the last ring defined with @TO {setupCotangent}@ + if no argument is given. Node Key puzzle @@ -279,6 +319,7 @@ multidoc /// [puzzle, Equivariant] [puzzle, Labels] [puzzle, Paths] + [puzzle, Separation] [puzzle, Steps] Puzzle Headline @@ -313,9 +354,15 @@ multidoc /// this will not occur in normal puzzle computations). The special symbol "#" stands for any single digit, whereas "*" stands for any puzzle label. + Note that only puzzles up to d=3 are implemented. + + One more symbol in boundary strings is allowed, namely "_"; this will trigger the option @TT "Separation"@ which allows the computation + of separated or almost separated descent puzzles, see paper [3] for details. + @TT "Labels"@ and @TT "Paths"@ are drawing options which only affect HTML and TeX output of puzzles. Example puzzle ("0101","1001",Equivariant=>false) + puzzle("1_20__","4_32_4",Generic=>false,Equivariant=>false) Node Key fugacity @@ -395,11 +442,8 @@ multidoc /// Caveat At the moment, the interactive part only works on nonequivariant puzzles. /// --- TODO: 12 of the symbols listed below as `undocumented` also appear in --- option-doc Usage sub-keys via [puzzle, Ktheory], [setupCotangent, Borel], --- etc. Either give each its own doc node or remove it from doc Usage. undocumented { - Presentation, Ktheory, Equivariant, Partial, Borel, EquivLoc, + Presentation, Ktheory, Equivariant, Borel, EquivLoc, Paths, Labels, Length, Steps, Ktheory', Separation, (restrict,Matrix),(restrict,Matrix,RingElement), (inversion,String), @@ -444,6 +488,9 @@ assert(class stableClass "0101" === B and class stableClass' "0101" === B) /// TEST /// -- tautoClass, zeroSection, dualZeroSection, and pushforwardToPointFromCotangent +(A,B,FF,I)=setupCotangent(1,2,3,Presentation=>Borel) +-- on a full flag, first Chern classes are just variables +assert(all(1..3,i->tautoClass(1,i)==x_i)) (A,B,FF,I) = setupCotangent(2,4,Presentation=>Borel,Ktheory=>false,Equivariant=>false); -- the 0-th Chern class of any tautological bundle is the identity assert(tautoClass(0,1) == 1) @@ -458,6 +505,22 @@ assert(pushforwardToPoint 1_A == 0) assert(pushforwardToPointFromCotangent(zeroSection A * dualZeroSection A) == #I) /// +TEST /// -- canonicalClass in cohomology and K-theory +-- on P^1, the first Chern class is the difference of the two Chern roots +(A,B,FF,I) = setupCotangent(1,2,Presentation=>Borel,Ktheory=>false,Equivariant=>false); +assert(canonicalClass A == tautoClass(1,2,A) - tautoClass(1,1,A)) +assert(canonicalClass() == canonicalClass B) +-- the Borel and localization presentations agree after restriction +(A,B,FF,I) = setupCotangent(1,2,Presentation=>Borel,Ktheory=>false,Equivariant=>true); +r = restrict canonicalClass A; +(D,FF,I) = setupCotangent(1,2,Presentation=>EquivLoc,Ktheory=>false,Equivariant=>true); +assert(r == canonicalClass D) +assert(canonicalClass() == canonicalClass D) +-- retain the existing multiplicative K-theory behavior +(D,FF,I) = setupCotangent(1,2,Presentation=>EquivLoc,Ktheory=>true,Equivariant=>true); +assert(canonicalClass() == canonicalClass D) +/// + TEST /// -- inversion counts the inversions of a label string assert(inversion "01" == 0) assert(inversion "10" == 1) diff --git a/M2/Macaulay2/packages/CotangentSchubert/cotangent.m2 b/M2/Macaulay2/packages/CotangentSchubert/cotangent.m2 index 3893038a566..bb0a2e2262d 100644 --- a/M2/Macaulay2/packages/CotangentSchubert/cotangent.m2 +++ b/M2/Macaulay2/packages/CotangentSchubert/cotangent.m2 @@ -15,7 +15,6 @@ cotOpts := opts ++ { Presentation => EquivLoc } debug Core -- to use BaseRing, generatorSymbols, frame -- labeling of classes --- TODO: LabelList is exported (at CotangentSchubert.m2:33) but has no doc node. LabelList = new Type of List; new LabelList from String := (T,s) -> ( l:=separate(" ",s); @@ -62,17 +61,9 @@ expandElem := (P,vrs,els) -> ( sub(C,ring first els) * product(#vrs, i -> (els#i)^(ee#i)) + expandElem(Q,vrs,els) ) --- FIXME: tautoClass(i,j) errors with "array index out of bounds" when j is --- outside the (undocumented) range of valid tautological-bundle indices for --- the current setup. The doc gives no bound on j; on setupCotangent(2,4) --- only j=1 is accepted (tautoClass(0,2) errors). tautoClass = method(Dispatch=>{Thing,Thing,Type},Options=>true); -- "Chern classes" -- renamed tautoClass to avoid confusion with motivic classes zeroSection = method(Dispatch=>{Type},Options=>true) -- note the {} dualZeroSection = method(Dispatch=>{Type},Options=>true) -- note the {} --- FIXME: canonicalClass is exported and documented but no method appears to --- be installed in setupCotangent's body; calling canonicalClass on any ring --- produced by setupCotangent (Borel/EquivLoc, equivariant or not) errors with --- "no method found". See the doc node at CotangentSchubert.m2:263-272. canonicalClass = method(Dispatch=>{Type},Options=>true) -- note the {} zeroSectionInv = method(Dispatch=>{Type},Options=>true) -- internal use only segreClass = method(Dispatch=>{Thing,Type},Options=>true) @@ -153,7 +144,8 @@ defineB = (FF,n,Kth,Equiv) -> ( -- TODO remove FF -- diagonal algebra DiagonalAlgebra = new Type of Type; -DiagonalAlgebra List := (D,l) -> new D from {map(D.Module,(ring D)^1,apply(splice l, i -> {i}))}; -- cannot be new D from List because would break existing Vector code +-- Infer the source degree as vector does; new D from List breaks inherited Vector code. +DiagonalAlgebra List := (D,l) -> new D from {map(D.Module,,apply(splice l, i -> {i}))}; new DiagonalAlgebra from Module := (X,M) -> ( D := new DiagonalAlgebra of Vector from hashTable { global Module => M }; new D from Vector := (D,v) -> ( @@ -258,9 +250,9 @@ setupCotangent = cotOpts >> curCotOpts -> dims0 -> ( BB := defineB(FF,n,curCotOpts.Ktheory,curCotOpts.Equivariant); x := getSymbol "x"; -- Chern classes - inds := splice apply(d+1, i -> apply(1..dimdiffs#i,j->(j,i))); - v := (j,i) -> x_(j,toList(dims#i+1..dims#(i+1))); -- variable name - e := (j,i) -> elem(j,apply(dims#i..dims#(i+1)-1,k->BB_k)); -- expression in terms of Chern roots + inds := splice apply(d+1, i -> apply(1..dimdiffs#i,j->(j,i+1))); + v := (j,i) -> x_(j,toList(dims#(i-1)+1..dims#i)); -- variable name + e := (j,i) -> elem(j,apply(dims#(i-1)..dims#i-1,k->BB_k)); -- expression in terms of Chern roots args := v\inds; if curCotOpts.Ktheory then ( args = append(args,DegreeRank=>0); @@ -283,12 +275,16 @@ setupCotangent = cotOpts >> curCotOpts -> dims0 -> ( b = sub(b,AB); -- scan(d+1,i->b=expandElem(b,toList(AB_(dims#i)..AB_(dims#(i+1)-1)),toList(AB_(n+dims#i)..AB_(n+dims#(i+1)-1)))); -- fails because of https://github.com/Macaulay2/M2/issues/2020 - v := seq -> apply(toList seq, j -> AB_j); - scan(d+1,i->b=expandElem(b,v(dims#i..dims#(i+1)-1),v(n+dims#i..n+dims#(i+1)-1))); + vv := seq -> apply(toList seq, j -> AB_j); + scan(d+1,i->b=expandElem(b,vv(dims#i..dims#(i+1)-1),vv(n+dims#i..n+dims#(i+1)-1))); sub(b,AA) ),BB,AA); -- - tautoClass (ZZ,ZZ,AA) := { Partial => true} >> o -> (j,i,AA) -> if o.Partial then AA_(dims#i+j-1) else e (j,i); + tautoClass (ZZ,ZZ,AA) := { Partial => true} >> o -> (j,i,AA) -> ( -- j^th Chern class of i^th tautological bundle + if i<1 or i>d+1 then error ("second index outside the range 1.."|toString(d+1)); + if j<0 or j>dimdiffs#(i-1) then error ("first index outside the range 0.."|toString(dimdiffs#(i-1))); + if o.Partial then AA_(dims#(i-1)+j-1) else e (j,i) + ); zeroSection AA := { Partial => true} >> o -> (cacheValue (zeroSection,o.Partial)) (if o.Partial then AA -> lift(zeroSection(AA,Partial=>false),AA) else if curCotOpts.Ktheory then AA -> product(n,j->product(n,k->if ω0#j<ω0#k then 1-FF_0^2*BB_j*BB_k^(-1) else 1)) @@ -297,8 +293,10 @@ setupCotangent = cotOpts >> curCotOpts -> dims0 -> ( else if curCotOpts.Ktheory then AA -> product(n,j->product(n,k->if ω0#j<ω0#k then 1-FF_0^-2*BB_k*BB_j^(-1) else 1)) else AA -> product(n,j->product(n,k->if ω0#j<ω0#k then -FF_0+BB_j-BB_k else 1))); - if curCotOpts.Ktheory then canonicalClass AA := { Partial => true} >> o -> (cacheValue (canonicalClass,o.Partial)) (if o.Partial then AA -> lift(canonicalClass(AA,Partial=>false),AA) - else AA -> product(n,j->product(n,k->if ω0#j<ω0#k then BB_k*BB_j^(-1) else 1))); + canonicalClass AA := { Partial => true} >> o -> (cacheValue (canonicalClass,o.Partial)) (if o.Partial then AA -> lift(canonicalClass(AA,Partial=>false),AA) + else if curCotOpts.Ktheory then + AA -> product(n,j->product(n,k->if ω0#j<ω0#k then BB_k*BB_j^(-1) else 1)) + else AA -> sum(n,j->sum(n,k->if ω0#j<ω0#k then BB_k-BB_j else 0_BB))); zeroSectionInv AA := { Partial => true } >> o -> (cacheValue (zeroSectionInv,o.Partial)) (AA -> (zeroSection(AA,o))^(-1)); -- Segre Classes TODO rethink: closure? sClasses AA := {Partial=>true} >> o -> (cacheValue (sClasses,o.Partial)) (if o.Partial then AA -> lift(sClasses(AA,Partial=>false),AA) @@ -542,18 +540,23 @@ setupCotangent = cotOpts >> curCotOpts -> dims0 -> ( weights D := (cacheValue weights) (D -> map(FF^1,M, { apply(I,i->product(n,j->product(n,k->if i#j map(FF^1,M, { apply(I,i->product(n,j->product(n,k->if i#j> o -> (cacheValue canonicalClass) (D -> D apply(I,i->product(n,j->product(n,k->if i#j>o->()->canonicalClass D); ) else ( zeroSection D := {} >> o -> (cacheValue zeroSection) (D -> D apply(I,i->product(n,j->product(n,k->if i#j> o -> (cacheValue zeroSectionInv) (D -> D apply(I,i->product(n,j->product(n,k->if i#j> o -> (cacheValue dualZeroSection) (D -> D apply(I,i->product(n,j->product(n,k->if i#j map(FF^1,M, { apply(I,i->product(n,j->product(n,k->if i#j map(FF^1,M, { apply(I,i->product(n,j->product(n,k->if i#j> o -> (cacheValue canonicalClass) (D -> D apply(I,i->sum(n,j->sum(n,k->if i#j>o->()->zeroSection D); installMethod(dualZeroSection,{}>>o->()->dualZeroSection D); + installMethod(canonicalClass,{}>>o->()->canonicalClass D); -- Chern classes of tautological bundles - tautoClass (ZZ,ZZ,D) := {} >> o -> (j,i,AA) -> D apply(I,s->elem(j,apply((subs s)#i,k->FF_(k+1)))); + tautoClass (ZZ,ZZ,D) := {} >> o -> (j,i,AA) -> ( + if i<1 or i>d+1 then error ("second index outside the range 1.."|toString(d+1)); + if j<0 or j>dimdiffs#(i-1) then error ("first index outside the range 0.."|toString(dimdiffs#(i-1))); + D apply(I,s->elem(j,apply((subs s)#(i-1),k->FF_(k+1)))) + ); tautoClass (ZZ,ZZ) := {} >> o -> (j,i) -> tautoClass(j,i,D); -- pushforward to point pushforwardToPoint D := pushforwardToPoint Vector := m -> ((weights D)*m)_0; diff --git a/M2/Macaulay2/packages/CotangentSchubert/puzzles.m2 b/M2/Macaulay2/packages/CotangentSchubert/puzzles.m2 index 6dc186f4ee3..468c35fbcca 100644 --- a/M2/Macaulay2/packages/CotangentSchubert/puzzles.m2 +++ b/M2/Macaulay2/packages/CotangentSchubert/puzzles.m2 @@ -281,9 +281,7 @@ neside = p -> new LabelList from apply(p.Length,i->p#(0,i,0)) -- computation of (d<=3) equivariant fugacities myload "fugacity.m2" --- TODO: `assoc` is exported here but has no doc node and is not on the --- undocumented {} list at CotangentSchubert.m2:398-405. -export { "puzzle", "bottom", "fugacity", "fugacityTally", "fugacityVector", "Puzzle", "assoc", "doublePuzzle" } +export { "puzzle", "bottom", "fugacity", "fugacityTally", "fugacityVector", "Puzzle", "doublePuzzle" } end -- ex of use diff --git a/M2/Macaulay2/packages/CotangentSchubert/puzzles/assoc.js b/M2/Macaulay2/packages/CotangentSchubert/puzzles/assoc.js index 295588c3417..55eed28d2aa 100644 --- a/M2/Macaulay2/packages/CotangentSchubert/puzzles/assoc.js +++ b/M2/Macaulay2/packages/CotangentSchubert/puzzles/assoc.js @@ -1,6 +1,6 @@ if (this.anim) return; e=event.target; -while (e.tagName!='use') { e=e.parentElement; if (e===null) return; } +while (e.tagName!='use') { e=e.parentElement; if (e===null) return; }; xx=e.x.baseVal.value; yy=e.y.baseVal.value; k=(xx+yy)%2; i=(yy-xx-k)/2; j=(yy+xx+k)/2; // just shift so always same set up @@ -23,7 +23,7 @@ nodes[0].before(nodes[2]); nodes[1].before(nodes[3]); window.setTimeout(() => { // need small pause for transition to work correctly after nodes moved // update colors - c=nodes.map(u=>+u.dataset.col) + c=nodes.map(u=>+u.dataset.col); mis=[0,1,2,3].filter(x=>c.indexOf(x)<0); if (c[0]==c[2]) nodes[0].dataset.col=nodes[2].dataset.col = c[0] { // need small pause for transition to work correctly a for (l=0; l<4; l++) { nodes[l].x.baseVal.value += shifts[l][0]; nodes[l].y.baseVal.value += shifts[l][1]; - } + }; this.anim=''; },0); + diff --git a/M2/Macaulay2/packages/CotangentSchubert/puzzles/assoc.m2 b/M2/Macaulay2/packages/CotangentSchubert/puzzles/assoc.m2 index 4bb595367dc..8cc5d822a6b 100644 --- a/M2/Macaulay2/packages/CotangentSchubert/puzzles/assoc.m2 +++ b/M2/Macaulay2/packages/CotangentSchubert/puzzles/assoc.m2 @@ -34,6 +34,9 @@ cvS := hashTable { "0" => 0, "1" => 1, "10" => 3 } -- hcol S side -- DoublePuzzle = new SelfInitializingType of BasicList html DoublePuzzle := html @@ hypertext +getPuzzleJS := get (puzzleDir|"assoc.js"); +getPuzzleJS = replace("\n"," ",replace("//.*$","",getPuzzleJS)) + hypertext DoublePuzzle := A -> ( (P1,P2) := toSequence A; n:=P1#Length; @@ -92,9 +95,9 @@ hypertext DoublePuzzle := A -> ( "style"=>"width:"|sz|";height:"|sz|";stroke:black;stroke-width:0.01", "viewBox"=>toString(-n-1)|" -1 "|toString(2*n+1)|" "|toString(2*n+1), lst1,lst2,defs, - "onclick"=>get (puzzleDir|"assoc.js")}, -- , "class" => "labels" - INPUT{"type"=>"checkbox","id"=>"labels","onclick"=>Sid|".classList.toggle('labels')"}, - LABEL{"for"=>"labels","Labels"} + "onclick"=>getPuzzleJS}, -- , "class" => "labels" + INPUT{"type"=>"checkbox","id"=>Sid|"toggle","onclick"=>Sid|".classList.toggle('labels')"}, + LABEL{"for"=>Sid|"toggle","Labels"} } ) @@ -112,4 +115,3 @@ doublePuzzle = puzzleOpts >> o -> (a,b,c,d) -> ( flatten apply(P,p->apply(puzzle(c,d,reverse bottom p,o),q->DoublePuzzle(p,q))) ) --- if topLevelMode === WebApp then print STYLE get (puzzleDir|"assoc.css")