Skip to content

Commit

Permalink
Merge pull request #3519 from mahrud/quickfix/basis
Browse files Browse the repository at this point in the history
basis improvements for Artinian tower rings
  • Loading branch information
d-torrance authored Oct 31, 2024
2 parents 490000a + bbc9f09 commit 4b6f3ca
Show file tree
Hide file tree
Showing 11 changed files with 116 additions and 28 deletions.
49 changes: 39 additions & 10 deletions M2/Macaulay2/m2/basis.m2
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@ inf := t -> if t === infinity then -1 else t
-----------------------------------------------------------------------------

-- the output of this is used in BasisContext
getVarlist = (R, varlist) -> (
if varlist === null then toList(0 .. numgens R - 1)
else if instance(varlist, List) then apply(varlist, v ->
getVarlist = (R, varlist) -> toList(
numvars := R.numallvars ?? numgens R;
if varlist === null then toList(0 .. numvars - 1)
else if instance(varlist, VisibleList) then apply(varlist, v ->
-- TODO: what if R = ZZ?
if instance(v, R) then index v else
if instance(v, ZZ) then v
Expand Down Expand Up @@ -127,7 +128,7 @@ basis = method(TypicalValue => Matrix,
basis Module := opts -> M -> basis(-infinity, infinity, M, opts)
basis Ideal := opts -> I -> basis(module I, opts)
basis Ring := opts -> R -> basis(module R, opts)
-- TODO: add? basis Matrix := opts -> m -> basis(-infinity, infinity, m, opts)
basis Matrix := opts -> m -> basis(-infinity, infinity, m, opts)

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

Expand Down Expand Up @@ -173,6 +174,18 @@ basis(ZZ, ZZ, Ring) := opts -> (lo, hi, R) -> basis(lo,

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

inducedBasisMap = (G, F, f) -> (
-- Assumes G = image basis(deg, target f) and F = image basis(deg, source f)
-- this helper routine is useful for computing basis of a pair of composable
-- matrices or a chain complex, when target f is the source of a matrix which
-- we previously computed basis for.
psi := f * inducedMap(source f, , generators F);
phi := last coefficients(ambient psi, Monomials => generators G);
map(G, F, phi, Degree => degree f))
-- TODO: benchmark against inducedTruncationMap in Truncations.m2
-- f' := f * inducedMap(source f, F) * inducedMap(F, source generators F, generators F);
-- map(G, F, inducedMap(G, source f', f') // inducedMap(G, source generators G, generators G), Degree => degree f))

basis(List, Matrix) :=
basis(ZZ, Matrix) := opts -> (deg, M) -> basis(deg, deg, M, opts)
basis(InfiniteNumber, InfiniteNumber, Matrix) :=
Expand All @@ -183,12 +196,28 @@ basis(List, List, Matrix) :=
basis(List, ZZ, Matrix) :=
basis(ZZ, InfiniteNumber, Matrix) :=
basis(ZZ, List, Matrix) :=
basis(ZZ, ZZ, Matrix) := opts -> (lo, hi, M) -> (
BF := basis(lo, hi, target M, opts);
BG := basis(lo, hi, source M, opts);
-- TODO: is this general enough?
BM := last coefficients(matrix (M * BG), Monomials => BF);
map(image BF, image BG, BM))
basis(ZZ, ZZ, Matrix) := opts -> (lo, hi, M) -> inducedBasisMap(
image basis(lo, hi, target M, opts), image basis(lo, hi, source M, opts), M)

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

-- Note: f needs to be homogeneous, otherwise returns nonsense
basis RingMap := Matrix => opts -> f -> basis(({}, {}), f, opts)
basis(ZZ, RingMap) :=
basis(List, RingMap) := Matrix => opts -> (degs, f) -> basis((degs, degs), f, opts)
basis(Sequence, RingMap) := Matrix => opts -> (degs, f) -> (
-- if not isHomogeneous f then error "expected a graded ring map (try providing a DegreeMap)";
if #degs != 2 then error "expected a sequence (tardeg, srcdeg) of degrees for target and source rings";
(T, S) := (target f, source f);
(tardeg, srcdeg) := degs;
if tardeg === null then tardeg = f.cache.DegreeMap srcdeg;
if srcdeg === null then srcdeg = f.cache.DegreeLift tardeg;
targens := basis(tardeg, tardeg, T);
srcgens := basis(srcdeg, srcdeg, S);
-- TODO: should matrix RingMap return this map instead?
-- mon := map(module T, image matrix(S, { S.FlatMonoid_* }), f, matrix f)
mat := last coefficients(f cover srcgens, Monomials => targens);
map(image targens, image srcgens, f, mat))

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

Expand Down
2 changes: 1 addition & 1 deletion M2/Macaulay2/packages/Book3264Examples.m2
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ placeholderToSchubertBasis(RingElement,FlagBundle) := (c,G) -> (
(k,q) := toSequence(G.BundleRanks);
P := diagrams(q,k);
M := apply(P, i-> placeholderSchubertCycle(i,G));
E := flatten entries basis(R);
E := flatten entries basis(R, Variables => 0 .. numgens R - 1);
local T';
if R.cache.?htoschubert then T' = R.cache.htoschubert else (
T := transpose matrix apply (M, i -> apply(E, j-> coefficient(j,i))); --matrix converting from schu-basis
Expand Down
2 changes: 1 addition & 1 deletion M2/Macaulay2/packages/DGAlgebras.m2
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ getBasis (ZZ,DGAlgebra) := opts -> (homDegree,A) -> getBasis(homDegree,A.natural
getBasis (ZZ,Ring) := opts -> (homDegree,R) -> (
local retVal;
myMap := map(R, R.cache.basisAlgebra);
tempList := (flatten entries basis(homDegree, R.cache.basisAlgebra, Limit => opts.Limit)) / myMap;
tempList := (flatten entries basis(homDegree, R.cache.basisAlgebra, Limit => opts.Limit, Variables => 0 .. numgens R-1)) / myMap;
if tempList == {} then retVal = map((R)^1,(R)^0, 0) else
(
-- move this to an assert?
Expand Down
3 changes: 2 additions & 1 deletion M2/Macaulay2/packages/GradedLieAlgebras.m2
Original file line number Diff line number Diff line change
Expand Up @@ -2787,7 +2787,8 @@ basToMat(ZZ,List,LieAlgebra):=(d,m,L)->(
basToMat(ZZ,ZZ,List,LieAlgebra):=(d,j,m,L)->(
if m==={} or L#cache.dim#d==0 then matrix{{0_(L#Field)}} else
(
idm:=entries (basis((L#Field)^(dim(d,j,L))));
F := L#Field;
idm := entries basis(F^(dim(d,j,L)), Variables => F_*);
transpose matrix apply(m, x->if x==0 then
flatten table(1,dim(d,j,L),x->0_(L#Field))
else sum(
Expand Down
8 changes: 7 additions & 1 deletion M2/Macaulay2/packages/Macaulay2Doc/functions/basis-doc.m2
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,16 @@ doc ///
(basis, List, Matrix)
(basis, List, Module)
(basis, List, Ring)
(basis, List, RingMap)
(basis, List, ZZ, Ideal)
(basis, List, ZZ, Matrix)
(basis, List, ZZ, Module)
(basis, List, ZZ, Ring)
(basis, Matrix)
(basis, Module)
(basis, Ring)
(basis, RingMap)
(basis, Sequence, RingMap)
(basis, ZZ, Ideal)
(basis, ZZ, InfiniteNumber, Ideal)
(basis, ZZ, InfiniteNumber, Matrix)
Expand All @@ -44,6 +48,7 @@ doc ///
(basis, ZZ, Matrix)
(basis, ZZ, Module)
(basis, ZZ, Ring)
(basis, ZZ, RingMap)
(basis, ZZ, ZZ, Ideal)
(basis, ZZ, ZZ, Matrix)
(basis, ZZ, ZZ, Module)
Expand Down Expand Up @@ -145,7 +150,8 @@ doc ///
Example
A = ZZ/101[a..d];
B = A[x,y]/(a*x, x^2, y^2);
basis B
try basis B
basis(B, Variables => B_*)
Text
If $M$ is an ideal or module, the resulting map looks somewhat strange, since maps between modules
are given from generators, in terms of the generators of the target module. Use @TO super@ or @TO cover@
Expand Down
8 changes: 4 additions & 4 deletions M2/Macaulay2/packages/PushForward.m2
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ pushAuxHgs(RingMap):=(f)-> (
if isInclusionOfCoefficientRing f then (
--case when the source of f is the coefficient ring of the target:
if not isModuleFinite target f then error "expected a finite map";
matB = basis B;
matB = basis(B, Variables => 0 .. numgens B - 1);
mapf = if isHomogeneous f
then (b) -> (
(mons,cfs) := coefficients(b,Monomials=>matB);
Expand Down Expand Up @@ -775,7 +775,7 @@ TEST///
L = A[symbol b, symbol c, Join => false]/(b*c-s*t, t*b^2-s*c^2, b^3-s*c^2, c^3 - t*b^2)
isHomogeneous L
describe L
basis L
basis(L, Variables => L_*)
inc = map(L, A)
assert isInclusionOfCoefficientRing inc
assert isModuleFinite L
Expand All @@ -796,7 +796,7 @@ TEST///
L = A[symbol b, symbol c, Join => false]/(b*c-s*t,c^3-b*t^2,s*c^2-b^2*t,b^3-s^2*c)
isHomogeneous L
describe L
basis L
basis(L, Variables => L_*)
inc = map(L, A)
assert isInclusionOfCoefficientRing inc
assert isModuleFinite L
Expand Down Expand Up @@ -837,7 +837,7 @@ TEST///
assert((M1,B1) == (M,B))
assert(pushFwd matrix{{y}} == pushFwd(map(R,A),matrix{{y}}))
assert(isFreeModule M and rank M == 7)
assert(B == basis R)
assert(B == basis(R, Variables => R_*))
assert( pf(y+x)- matrix {{x}, {1}, {0}, {0}, {0}, {0}, {0}} == 0)
R' = integralClosure R
(M,B,pf) = pushFwd map(R',R)
Expand Down
2 changes: 1 addition & 1 deletion M2/Macaulay2/packages/Schubert2.m2
Original file line number Diff line number Diff line change
Expand Up @@ -1767,7 +1767,7 @@ schubertRing(FlagBundle) := G -> (
(k,q) := toSequence(G.BundleRanks);
P := diagrams(q,k);
M := apply(P, i-> schubertCycle(i,G));
E := flatten entries basis(R);
E := flatten entries basis(R, Variables => 0 .. numgens R - 1);
local T';
T := transpose matrix apply (M, i -> apply(E, j-> coefficient(j,i))); --matrix converting from schu-basis
--to h-basis
Expand Down
8 changes: 4 additions & 4 deletions M2/Macaulay2/packages/SumsOfSquares.m2
Original file line number Diff line number Diff line change
Expand Up @@ -474,12 +474,12 @@ createSOSModel(Matrix,Matrix) := o -> (F,v) -> (

-- monomials in vvT
vvT := entries(v* transpose v);
mons := g -> set first entries monomials g;
K1 := toList \\ sum \\ mons \ flatten vvT;
mons := g -> unique first entries monomials g;
K1 := unique \\ flatten \\ mons \ flatten vvT;

-- monomials in F and not in vvT
lmf := sum \\ mons \ flatten entries F;
K2 := toList(lmf - K1);
lmf := unique \\ flatten \\ mons \ flatten entries F;
K2 := lmf - set K1;
K := K1 | K2;

-- Linear constraints: b
Expand Down
14 changes: 9 additions & 5 deletions M2/Macaulay2/packages/Truncations.m2
Original file line number Diff line number Diff line change
Expand Up @@ -260,12 +260,16 @@ truncate(List, Module) := Module => truncateModuleOpts >> opts -> (degs, M) -> (

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

inducedTruncationMap = (G, F, f) -> (
-- Assumes G = truncate(deg, target f) and F = truncate(deg, source f)
-- this helper routine is useful for truncating complexes or a pair of
-- composable matrices, when target f is the source of a previously
-- truncated matrix, so we have truncated it once already.
f' := f * inducedMap(source f, F) * inducedMap(F, source gens F, gens F);
map(G, F, inducedMap(G, source f', f') // inducedMap(G, source gens G, gens G)))

truncate(List, Matrix) := Matrix => truncateModuleOpts >> opts -> (degs, f) -> (
F := truncate(degs, source f, opts);
G := truncate(degs, target f, opts);
-- FIXME, what is right?
fgenF := (f * inducedMap(source f, F) * inducedMap(F, source gens F, gens F));
map(G, F, inducedMap(G, source fgenF, fgenF) // inducedMap(G, source gens G, gens G)))
inducedTruncationMap(truncate(degs, target f, opts), truncate(degs, source f, opts), f))

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

Expand Down
14 changes: 14 additions & 0 deletions M2/Macaulay2/packages/Truncations/tests.m2
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,20 @@ TEST /// -- test of truncationPolyhedron with Nef option
assert(HH_0 D == M1 and HH_1 D == 0 and HH_2 D == 0) -- good, fixed in v1.0
///

TEST /// -- test of inducedTruncationMap
debug needsPackage "Truncations"
S = QQ[x,y,z]
gbTrace = 2
M = image map(S^3, , {{x}, {y}, {z}})
f = inducedMap(S^3, M)
(tar, src) = (truncate(2, S^3), truncate(2, M))
g = inducedTruncationMap(tar, src, f)
assert isWellDefined g
assert(g === truncate(2, f))
assert(tar === target g)
assert(src === source g)
///

end--

restart
Expand Down
34 changes: 34 additions & 0 deletions M2/Macaulay2/tests/normal/basis3.m2
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@ assert(basis(0, 1, R) == matrix{{1, a, b}})
assert(basis(0, 2, R) == matrix{{1, a, a^2, a*b, b, b^2}})
assert(basis(0, 1, R) == matrix{{1, a, b}})

-- c.f. examples "part(List,Complex)"
R = QQ[a..d]
M = coker matrix {{a*b, a*c, b*c, a*d}}
N = image map(R^{4:-2}, , {{-c, -c, 0, -d}, {b, 0, -d, 0}, {0, a, 0, 0}, {0, 0, c, b}})
P = image map(R^{4:-3}, , {{d}, {0}, {-c}, {b}})
assert(basis(4, map(R^0, M, 0)) == 0)
assert(basis(4, map(M, N, 0)) == 0)
assert(basis(4, map(N, P, 0)) == 0)
assert(basis(4, map(P, R^0, 0)) == 0)

-- partial multidegrees
-- see https://github.com/Macaulay2/M2/pull/2056
assert(basis({3}, A = ZZ/101[a..d, Degrees=>{2:{1,2},2:{0,1}}]) == matrix"a3,a2b,ab2,b3")
Expand Down Expand Up @@ -47,6 +57,11 @@ assert(basis(0, R) == gens R^1) -- ignores degree 0 vars
assert try (basis(0, R, Variables => {0}); false) else true
assert(basis(1, R) == 0)

S = ZZ/101[s,t]
R = S[a..d]
assert(basis({0,1}, R) == sub(vars S, R))
assert(basis({1,0}, R) == vars R)

-- FIXME: these are also broken
R = ZZ/101[a,b, Degrees => {0,1}]
basis(1, R)
Expand All @@ -59,6 +74,12 @@ assert(basis(0, A = ZZ/101[a, Degrees => {0}]) == gens A^1)
-- this is finite over the field, so we include all vars
assert(basis(0, A = ZZ/101[a, Degrees => {0}]/ideal(a^3)) == matrix"1,a,a2")
assert(basis A == matrix"1,a,a2")
assert(basis id_(A^1) == id_(image basis A))
assert(basis map(A,A) == id_(image basis A))

A = quotient ideal conwayPolynomial(2, 3)
B = image basis A
assert(basis map(A, A, {a^2}) == map(B, B, {{1, 0, 0}, {0, 0, 1}, {0, 1, 1}}))

-- https://github.com/Macaulay2/M2/issues/1312
R = QQ[]
Expand Down Expand Up @@ -110,3 +131,16 @@ assert(basis(2, R) == matrix"a2,b")
-- FIXME: assert(basis(2, R, Truncate => true) == matrix "b,a2,c")
assert(basis(2, R) == matrix"a2,b")

-- tests for basis of ring maps
R = ZZ/32003[s,t][a..d]
f = map(A := coefficientRing R, R, DegreeMap => d -> take(d, - degreeLength A))
assert(entries basis(({2}, {0,2}), f) == entries id_(ZZ^3))

f = map(QQ[s,t], QQ[w,x,y,z], matrix"s3,s2t,st2,t3")
b = basis((6, 2), f)
-- FIXME: this is very non-minimal, but ker b doesn't work if f is homogeneous ...
K = image map(source b, , gens ker b)
-- FIXME: why isn't ker b a submodule of source b already?
-- assert isSubset(ker b, source b)
assert isSubset(K, source b)
assert(ker f == K)

0 comments on commit 4b6f3ca

Please sign in to comment.