Skip to content
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

Promote #3494

Open
wants to merge 4 commits into
base: development
Choose a base branch
from
Open

Promote #3494

Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion M2/Macaulay2/editors/emacs
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This hash changed again.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a pain, we should set up the emacs stuff differently so it doesn't occur...

Submodule emacs updated 1 files
+6 −6 M2.el
73 changes: 56 additions & 17 deletions M2/Macaulay2/m2/enginering.m2
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,40 @@ commonEngineRingInitializations = (F) -> (
*-
)

-----------------------------------------------------------------------------
------------------------------------------------------------------------------
-- TODO improve this, or deprecate promote/lift(List,R,S)
defaultDegMap := (R,S) -> (
n:=degreeLength S-degreeLength R;
if n==0 then identity
else if n<0 then d -> take(d,degreeLength S)
else d -> d|toList(n:0)
)

-- automate promote
setupPromote = method()
setupPromote (Function,Ring,Ring,Function) := (f,R,S,degmap) -> (
promote(R,S) := (a,S) -> f a;
promote(List,R,S) := (m,R,S) -> apply(m,degmap);
-- promote(Matrix,R,S) :=
-- promote(MutableMatrix,R,S) := -- doesn't work, cf https://github.com/Macaulay2/M2/issues/2192
Comment on lines +242 to +243
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confused about these commented lines. Don't you have these exact methods implemented two lines below?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, but not as S ** M

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would it be? That wouldn't even work because Ring ** Matrix calls Ring ** Module which then calls promote(Matrix, Ring), so it would be a loop.

promote(Module,R,S) := (M,R1,S1) -> S ** M;
promote(Matrix,R,S) := (m,R,S) -> map(promote(target m,S),promote(source m,S),applyTable(entries m,x->promote(x,S)));
promote(MutableMatrix,R,S) := (m,R,S) -> mutableMatrix applyTable(entries m,x->promote(x,S));
)
setupPromote (Function,Ring,Ring) := (f,R,S) -> setupPromote(f,R,S,defaultDegMap(R,S));

-- automate (to some extent) lift
setupLift = method()
setupLift (Function,Ring,Ring,Function) := (f,R,S,degmap) -> (
lift(R,S) := opts -> (a,S) -> if opts.Verify then f a else try f a;
lift(List,R,S) := opts -> (m,R,S) -> apply(m,degmap);
lift(Module,R,S) := opts -> (M,R,S) -> S ** M;
lift(Matrix,R,S) := opts -> (m,R,S) -> map(lift(target m,S),lift(source m,S),applyTable(entries m,x->lift(x,S)));
lift(MutableMatrix,R,S) := opts -> (m,R,S) -> mutableMatrix applyTable(entries m,x->lift(x,S));
Comment on lines +253 to +257
Copy link
Member

@mahrud mahrud Oct 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have any lift methods of matching e.g. lift(Module, R, S) that isn't defined here automatically? Because if not, I think all of these should just be e.g. lift(Module, Ring, Ring), and we can rename lift(x,S) to something else that is defined per ring.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good question. lift(Module,...) only works for free modules anyway, it seems the definition I give could work universally. that being said it's not how it's done for the usual internal lift, and I don't dare to change too much.

)
setupLift (Function,Ring,Ring) := (f,R,S) -> setupLift(f,R,S,defaultDegMap(R,S));

-----------------------------------------------------------------------------
reduce := (r,s) -> (
z := syz( matrix{{r,s}}, SyzygyLimit => 1 );
a := z_(1,0);
Expand Down Expand Up @@ -329,6 +362,10 @@ frac EngineRing := R -> if isField R then R else if R.?frac then R.frac else (
if R.?indexSymbols then F.indexSymbols = applyValues(R.indexSymbols, r -> promote(r,F));
if R.?indexStrings then F.indexStrings = applyValues(R.indexStrings, r -> promote(r,F));
if R.?numallvars then F.numallvars=R.numallvars;
scan(R.baseRings, S -> if S.?frac and not isPromotable(S.frac,F) then (
setupPromote(a->fraction(promote(numerator a,R),promote(denominator a,R)),S.frac,F);
setupLift(a->fraction(lift(numerator a,S),lift(denominator a,S)),F,S.frac);
));
F)

-- methods for all ring elements
Expand Down Expand Up @@ -466,6 +503,8 @@ swap = (x,y) -> (y,x)
promoterightexact = swap @@ promoteleftexact @@ swap
promoterightinexact = swap @@ promoteleftinexact @@ swap

isPromotable = (R,S) -> lookup(promote,R,S) =!= null
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be defined next to promote?


divmod := R -> (f,g) -> (
(q,r) := rawDivMod(raw f, raw g);
(new R from q, new R from r))
Expand All @@ -474,10 +513,10 @@ quotientRemainder(RingElement,RingElement) := (f,g) -> (
S := ring g;
m := quotientRemainder(R,S) := (
if R === S then divmod R
else if isMember(R,S.baseRings) then (
else if isPromotable(R,S) then (
(x,y) -> divmod(promote(x,S), y)
)
else if isMember(S,R.baseRings) then (
else if isPromotable(S,R) then (
(x,y) -> divmod(x, promote(y,R))
)
else error "expected pair to have a method for quotientRemainder"
Expand All @@ -500,10 +539,10 @@ RingElement % RingElement := RingElement => (f,g) -> (
if R === S then (
(x,y) -> new R from raw x % raw y
)
else if isMember(R,S.baseRings) then (
else if isPromotable(R,S) then (
(x,y) -> promote(x,S) % y
)
else if isMember(S,R.baseRings) then (
else if isPromotable(S,R) then (
(x,y) -> x % promote(y,R)
)
else error "expected pair to have a method for '%'"
Expand All @@ -523,10 +562,10 @@ RingElement // RingElement := RingElement => (f,g) -> (
if R === S then (
(x,y) -> new R from raw x // raw y
)
else if isMember(R,S.baseRings) then (
else if isPromotable(R,S) then (
(x,y) -> promote(x,S) // y
)
else if isMember(S,R.baseRings) then (
else if isPromotable(S,R) then (
(x,y) -> x // promote(y,R)
)
else error "expected pair to have a method for '//'"
Expand All @@ -544,10 +583,10 @@ RingElement - RingElement := RingElement => (f,g) -> (
if R === S then (
(x,y) -> new R from raw x - raw y
)
else if isMember(R,S.baseRings) then (
else if isPromotable(R,S) then (
(x,y) -> promote(x,S) - y
)
else if isMember(S,R.baseRings) then (
else if isPromotable(S,R) then (
(x,y) -> x - promote(y,R)
)
else error "expected pair to have a method for '-'"
Expand All @@ -565,10 +604,10 @@ RingElement * RingElement := RingElement => (f,g) -> (
if R === S then (
(x,y) -> new R from raw x * raw y
)
else if isMember(R,S.baseRings) then (
else if isPromotable(R,S) then (
(x,y) -> promote(x,S) * y
)
else if isMember(S,R.baseRings) then (
else if isPromotable(S,R) then (
(x,y) -> x * promote(y,R)
)
else error "expected pair to have a method for '*'"
Expand All @@ -586,10 +625,10 @@ RingElement + RingElement := RingElement => (f,g) -> (
if R === S then (
(x,y) -> new R from raw x + raw y
)
else if isMember(R,S.baseRings) then (
else if isPromotable(R,S) then (
(x,y) -> promote(x,S) + y
)
else if isMember(S,R.baseRings) then (
else if isPromotable(S,R) then (
(x,y) -> x + promote(y,R)
)
else error "expected pair to have a method for '+'"
Expand All @@ -611,10 +650,10 @@ RingElement == RingElement := (f,g) -> (
if R === S then (
(x,y) -> raw x === raw y
)
else if isMember(R,S.baseRings) then (
else if isPromotable(R,S) then (
(x,y) -> promote(x,S) == y
)
else if isMember(S,R.baseRings) then (
else if isPromotable(S,R) then (
(x,y) -> x == promote(y,R)
)
else error "expected pair to have a method for '=='"
Expand All @@ -630,10 +669,10 @@ RingElement / RingElement := RingElement => (f,g) -> (
frac R;
(r,s) -> fraction (r,s)
)
else if isMember(R,S.baseRings) then (
else if isPromotable(R,S) then (
(x,y) -> promote(x,S) / y
)
else if isMember(S,R.baseRings) then (
else if isPromotable(S,R) then (
(x,y) -> x / promote(y,R)
)
else error "expected pair to have a method for '/'"
Expand Down
2 changes: 2 additions & 0 deletions M2/Macaulay2/m2/exports.m2
Original file line number Diff line number Diff line change
Expand Up @@ -1127,6 +1127,8 @@ export {
"setRandomSeed",
"setup",
"setupEmacs",
"setupLift",
"setupPromote",
"shield",
"show",
"showClassStructure",
Expand Down
6 changes: 3 additions & 3 deletions M2/Macaulay2/m2/matrix.m2
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,9 @@ Matrix * Matrix := Matrix => (m,n) -> (
else (
R := ring m;
S := ring target n;
if R =!= S then (
try m = m ** S else
try n = n ** R else
if R =!= S then ( -- use toSameRing?
try m = promote(m,S) else
try n = promote(n,R) else
error "maps over incompatible rings";
);
M = target m;
Expand Down
10 changes: 9 additions & 1 deletion M2/Macaulay2/m2/newring.m2
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,15 @@ tensor(QuotientRing, QuotientRing) := monoidTensorDefaults >> optns -> (R, S)
fg := substitute(f,(vars AB)_{0 .. m-1}) | substitute(g,(vars AB)_{m .. m+n-1});
-- forceGB fg; -- if the monomial order chosen doesn't restrict, then this
-- is an error!! MES
AB/image fg)
RS := AB/image fg;
setupPromote map(RS,R,(vars AB)_{0 .. m-1});
setupLift map(R,RS,generators A | toList(n:0));
if S =!= R then (
setupPromote map(RS,S,(vars AB)_{m .. m+n-1});
setupLift map(S,RS,toList(m:0) | generators B);
);
RS
)

-------------------------
-- Graph of a ring map --
Expand Down
7 changes: 6 additions & 1 deletion M2/Macaulay2/m2/polyrings.m2
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,12 @@ selectVariables(List,PolynomialRing) := (v,R) -> (
o.Variables = o.Variables_v;
o.Degrees = o.Degrees_v;
o = new OptionTable from o;
(S := (coefficientRing R)(monoid [o]),map(R,S,(generators R)_v)))
S := (coefficientRing R)(monoid [o]);
f := map(R,S,(generators R)_v);
g := map(S,R,apply(generators R, v->substitute(v,S)));
setupPromote f;
setupLift g;
(S,f))

-----------------------------------------------------------------------------

Expand Down
2 changes: 1 addition & 1 deletion M2/Macaulay2/m2/quotring.m2
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ char QuotientRing := (stashValue symbol char) ((S) -> (
g := generators gb relns;
if g == 0 then return char ring g;
m := g_(0,0);
if liftable(m,ZZ) then lift(m,ZZ) else 0))
lift(m,ZZ,Verify=>false) ?? 0))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if I understand the motivation in this change. I like ?? and ??= in certain situations (e.g. caching) but I'm concerned that in places like this it might make debugging more difficult. For instance, I imagine we would like to see an error if isLiftable returned true but lift failed here, because that would be a bug and an error would help us locate it, but ?? hides the error here and silently returns zero.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in general I would agree with you but here's a pretty clear-cut case where we're basically calling lift twice for no reason.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm actually a little confused about what's happening in this code, but sure.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On a second thought, basically any time someone calls isLiftable, a potential call to lift is on the horizon, no?


singularLocus = method()
singularLocus(Ring) := QuotientRing => (R) -> (
Expand Down
1 change: 0 additions & 1 deletion M2/Macaulay2/m2/rationals.m2
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ assert (hash ZZ < hash QQ)
lift(QQ,ZZ) := opts -> (r,o) -> if denominator r === 1 then numerator r else if opts.Verify then error "rational number is not an integer"
liftable(QQ,ZZ) := (r,o) -> denominator r === 1
lift(QQ,QQ) := opts -> (r,QQ) -> r
liftable(QQ,QQ) := (QQ,QQ) -> true

QQ.degreeLength = 0
isUnit Number := x -> x != 0
Expand Down
18 changes: 14 additions & 4 deletions M2/Macaulay2/m2/ringmap.m2
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ needs "mutablemat.m2"
-- should do something about the degree map here
degmap0 := n -> ( d := toList ( n : 0 ); e -> d )

workable = f -> try (f(); true) else false

-----------------------------------------------------------------------------
-- RingMap type declarations and basic methods
-----------------------------------------------------------------------------
Expand Down Expand Up @@ -85,7 +83,7 @@ map(Ring, Ring, Matrix) := RingMap => opts -> (R, S, m) -> (
" into a degree of length ", toString degreeLength R);
opts.DegreeMap
)
else if workable (() -> promote({},S,R)) then (d -> first promote({d},S,R))
else if (pr:=lookup(promote,List,S,R)) =!= null then (d -> first pr({d},S,R))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh, I didn't know promote(List,S,R) is for promoting the degree till now ...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the record I fixed this line because it could create infinite loops. It pretty much never occurred before because there were few promote, but now with the added flexibility of promoteFromMap (or whatever we're going to end up calling), it can easily happen.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I would be in favor of deprecating promote(List, Ring, Ring) and instead given a ring map f make use of f.degreeMap and f.degreeLift.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or maybe just degreeGroup f defined as degreeGroup RingMap := f -> f.degreeMap, which is similar to how NormalToricVarieties supports picardGroup ToricMap to give the map of Picard groups functorially.

else if degreeLength R === degreeLength S then identity
else if degreeLength S === 0 or degreeLength R === 0 then degmap0 degreeLength R
else (
Expand Down Expand Up @@ -125,7 +123,7 @@ map(Ring, Ring, Matrix) := RingMap => opts -> (R, S, m) -> (
else if r < n then error ("encountered values for ", toString r, " variables, but expected ", toString n)
else if r == n then (
if numgens A > 0 then (
if A === R or isMember(A, R.baseRings) then (
if A === R or isPromotable(A, R) then (
-- we can promote
mE = mE | promote(vars A, R);
if instance(A,GaloisField) and A.rawGaloisField then (
Expand Down Expand Up @@ -569,6 +567,18 @@ map(Module,Module,RingMap,List) := Matrix => o -> (M,N,p,f) -> map(M,N,p,map(M,r
map(Module,Nothing,RingMap,List) := Matrix => o -> (M,N,p,f) -> map(M,N,p,map(M,,f),o)
map(Module,RingMap) := Matrix => o -> (M,p) -> map(M,,p,map(M,cover M,1),o)

--
setupPromote (RingMap,Ring,Ring,Function) := lookup(setupPromote,Function,Ring,Ring,Function)
setupPromote (RingMap,Ring,Ring) := (f,R,S) -> setupPromote(f,R,S,f.cache.DegreeMap)
-- note that promote(Module,R,S) := (M,R,S) -> f ** M would make more sense, but promote only works with free modules anyway
setupPromote RingMap := f -> setupPromote(f,source f,target f)
setupPromote (Ring,Ring) := (R,S) -> setupPromote map(S,R)

setupLift (RingMap,Ring,Ring) := (f,R,S) -> -- f is a partial inverse to the promote map
setupLift( a -> ( b := f a; if promote(b,R) == a then b else error "cannot lift" ), R,S,f.cache.DegreeMap);

setupLift RingMap := f -> setupLift(f,source f,target f)

-- Local Variables:
-- compile-command: "make -C $M2BUILDDIR/Macaulay2/m2 "
-- End:
3 changes: 2 additions & 1 deletion M2/Macaulay2/m2/rings.m2
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,13 @@ toExternalString Ring := toString @@ describe
-- promote, lift, liftable, and isConstant
-----------------------------------------------------------------------------

-- TODO rename isLiftable; currently impossible due to conflict with Varieties::isLiftable
-- some remnants from lift and promote, version 2
liftable = method(TypicalValue => Boolean, Dispatch => {Thing, Type, Type})
liftable(Number, Number) :=
liftable(Number, RingElement) :=
liftable(RingElement, Number) :=
liftable(RingElement, RingElement) := (f, R) -> null =!= lift(f, R, Verify => false)
liftable(RingElement, RingElement) := (f, R) -> lookup(lift,class f,R) =!= null and null =!= lift(f, R, Verify => false)

isConstant = method(TypicalValue => Boolean)
isConstant RingElement := r -> liftable(r, coefficientRing ring r)
Expand Down
33 changes: 9 additions & 24 deletions M2/Macaulay2/packages/CotangentSchubert/cotangent.m2
Original file line number Diff line number Diff line change
Expand Up @@ -61,18 +61,6 @@ expandElem := (P,vrs,els) -> (
sub(C,ring first els) * product(#vrs, i -> (els#i)^(ee#i)) + expandElem(Q,vrs,els)
)

-- automate promotion
promoteFromMap = method()
promoteFromMap (Ring,Ring,RingMap) := (R,S,f) -> (
promote(R,S) := (a,S1) -> f a;
promote(Matrix,R,S) :=
promote(MutableMatrix,R,S) := -- doesn't work, cf https://github.com/Macaulay2/M2/issues/2192
promote(Module,R,S) := (M,R1,S1) -> f M;
-- promote(List,R,S) := (L,R1,S1) -> f\L; -- TODO put back!!!!!!!!!!
S.baseRings = prepend(R,S.baseRings); -- temporary -- until promotability test improved in enginering.m2
)
promoteFromMap (Ring,Ring) := (R,S) -> promoteFromMap(R,S,map(S,R))

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 {}
Expand Down Expand Up @@ -114,18 +102,18 @@ pushforwardToPointFromCotangent=method(); -- pushforward to a point from K(T^*(G
q := getSymbol "q"; zbar := getSymbol "zbar";
FK_-1 = frac(factor(ZZ (monoid[q,zbar,DegreeRank=>0]))); -- same as FK_1, really but diff variable name
FK_0 = frac(factor(ZZ (monoid[q,DegreeRank=>0])));
promoteFromMap(FK_0,FK_-1);
setupPromote(FK_0,FK_-1);

h := getSymbol "h"; ybar := getSymbol "ybar";
FH_-1 = frac(factor(ZZ (monoid[h,ybar]))); -- same as FH_1, really but diff variable name
FH_0 = frac(factor(ZZ (monoid[h])));
promoteFromMap(FH_0,FH_-1);
setupPromote(FH_0,FH_-1);

defineFK = n -> (
if not FK#?n then (
z := getSymbol "z"; -- q := getSymbol "q";
FK_n = frac(factor(ZZ (monoid[q,z_1..z_n,DegreeRank=>0,MonomialOrder=>{Weights=>{n+1:1},RevLex}])));
promoteFromMap(FK_0,FK_n);
setupPromote(FK_0,FK_n);
);
FK#n
)
Expand All @@ -134,7 +122,7 @@ defineFH = n -> (
if not FH#?n then (
y := getSymbol "y"; -- h := getSymbol "h";
FH_n = frac(factor(ZZ (monoid[h,y_1..y_n,MonomialOrder=>{Weights=>{n+1:1},Weights=>{1,n:0},RevLex}])));
promoteFromMap(FH_0,FH_n);
setupPromote(FH_0,FH_n);
);
FH#n
)
Expand All @@ -149,6 +137,7 @@ defineB = (FF,n,Kth,Equiv) -> ( -- TODO remove FF
-if Equiv then elem(k,drop(gens FF,1)) else if Kth then binomial(n,k) else 0);
BB := BB0/J;
BBs#(n,Kth,Equiv) = BB;
if Equiv then setupPromote(map(BB,if Kth then FK_0 else FH_0,{FF_0}));
);
BBs#(n,Kth,Equiv)
)
Expand Down Expand Up @@ -258,7 +247,6 @@ setupCotangent = cotOpts >> curCotOpts -> dims0 -> (
);
if curCotOpts.Presentation === Borel then (
BB := defineB(FF,n,curCotOpts.Ktheory,curCotOpts.Equivariant);
if curCotOpts.Equivariant then promoteFromMap(FF0,BB,map(BB,FF0,{FF_0})); -- TODO move elsewhere
x := getSymbol "x";
-- Chern classes
inds := splice apply(d+1, i -> apply(1..dimdiffs#i,j->(j,i)));
Expand All @@ -278,21 +266,18 @@ setupCotangent = cotOpts >> curCotOpts -> dims0 -> (
R1 := FF monoid new Array from args;
f := map(BB,R1,e\inds);
AA := R1 / kernel f;
if curCotOpts.Equivariant then promoteFromMap(FF0,AA,map(AA,FF0,{FF_0}));
promoteFromMap(AA,BB,f*map(R1,AA));
if curCotOpts.Equivariant then setupPromote(map(AA,FF0,{FF_0}));
setupPromote(f*map(R1,AA));
-- reverse transformation
lift(Module,BB,AA) := opts -> (v,b,AA) -> vector apply(entries v,x->lift(x,AA));
lift(Matrix,BB,AA) := opts -> (m,b,AA) -> matrix applyTable(entries m,x->lift(x,AA));
lift (BB,AA) := opts -> (b,AA) -> (
if d == n-1 then return (map(AA,BB,gens AA)) b; -- special case of full flag
setupLift( if #(unique dims) == n+1 then map(AA,BB,gens AA) else b -> ( -- special case of full flag
AB := FF monoid (BB.generatorSymbols | AA.generatorSymbols); -- no using it
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)));
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);
zeroSection AA := { Partial => true} >> o -> (cacheValue (zeroSection,o.Partial)) (if o.Partial then AA -> lift(zeroSection(AA,Partial=>false),AA)
Expand Down
Loading
Loading