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

LeftIdeal (take two) #3020

Draft
wants to merge 11 commits into
base: development
Choose a base branch
from
1 change: 1 addition & 0 deletions M2/Macaulay2/m2/exports.m2
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ export {
"Homogeneous",
"Homogeneous2",
"HorizontalSpace",
"LeftIdeal",
"Ideal",
"IgnoreExampleErrors",
"ImmutableType",
Expand Down
2 changes: 1 addition & 1 deletion M2/Macaulay2/m2/gb.m2
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ degreeToHeft = (R, d) -> (
-----------------------------------------------------------------------------

gb = method(TypicalValue => GroebnerBasis, Options => gbDefaults)
gb Ideal := GroebnerBasis => opts -> I -> gb (module I, opts)
gb LeftIdeal := GroebnerBasis => opts -> I -> gb (module I, opts)
gb Module := GroebnerBasis => opts -> M -> (
if M.?relations then (
if not M.cache#?"full gens" then M.cache#"full gens" = generators M | relations M;
Expand Down
12 changes: 6 additions & 6 deletions M2/Macaulay2/m2/intersect.m2
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ moduleIntersectOpts := {
}

-- ideally this should be unnecessary, but some code seems to depend on this
intersect Ideal := Ideal => idealIntersectOpts >> opts -> I -> doTrim(opts, I)
intersect LeftIdeal := LeftIdeal => idealIntersectOpts >> opts -> I -> doTrim(opts, I)
intersect Module := Module => moduleIntersectOpts >> opts -> M -> doTrim(opts, M)

-- intersect is a MethodFunctionBinary, so arbitrary lists
Expand All @@ -77,12 +77,12 @@ intersect Module := Module => moduleIntersectOpts >> opts -> M -> doTrim(opts, M
-- installing a method (intersect, S, T) => T enables intersect(S, T, T, ...)
-- installing a method (intersect, S, S) => S enables intersect(S, S, T, T, ...)
-- installing a method (intersect, T, S) => S enables intersect(S, T, S, T, ...)
intersect(Ideal, Ideal) := Ideal => idealIntersectOpts >> opts -> L -> intersectHelper(L, (intersect, Ideal, Ideal), opts)
intersect(LeftIdeal, LeftIdeal) := LeftIdeal => idealIntersectOpts >> opts -> L -> intersectHelper(L, (intersect, LeftIdeal, LeftIdeal), opts)
intersect(Module, Module) := Module => moduleIntersectOpts >> opts -> L -> intersectHelper(L, (intersect, Module, Module), opts)

-- Specializations for intersecting many objects at once, e.g. Modules,
-- can be installed on (symbol intersect, T), which calls T.intersect
Ideal.intersect = idealIntersectOpts >> opts -> L -> intersectHelper(L, (intersect, Ideal, Ideal), opts)
LeftIdeal.intersect = idealIntersectOpts >> opts -> L -> intersectHelper(L, (intersect, LeftIdeal, LeftIdeal), opts)
Module.intersect = moduleIntersectOpts >> opts -> L -> intersectHelper(L, (intersect, Module, Module), opts)

-----------------------------------------------------------------------------
Expand Down Expand Up @@ -112,7 +112,7 @@ scan({Default}, strategy ->

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

algorithms#(intersect, Ideal, Ideal) = new MutableHashTable from {
algorithms#(intersect, LeftIdeal, LeftIdeal) = new MutableHashTable from {
Default => (opts, L) -> ideal intersect(opts, apply(L, module)),

-- TODO: can this be extended to do more than 2 at once?
Expand Down Expand Up @@ -145,6 +145,6 @@ algorithms#(intersect, Ideal, Ideal) = new MutableHashTable from {
newMonomialIdeal(R, rawIntersect(raw monomialIdeal I, raw monomialIdeal J)))),
}

-- Installing hooks for intersect(Ideal, Ideal)
-- Installing hooks for intersect(LeftIdeal, LeftIdeal)
scan({Default, "Elimination", Monomial}, strategy ->
addHook(key := (intersect, Ideal, Ideal), algorithms#key#strategy, Strategy => strategy))
addHook(key := (intersect, LeftIdeal, LeftIdeal), algorithms#key#strategy, Strategy => strategy))
143 changes: 87 additions & 56 deletions M2/Macaulay2/m2/matrix1.m2
Original file line number Diff line number Diff line change
Expand Up @@ -420,52 +420,54 @@ cokernel Matrix := Module => m -> (
cokernel RingElement := Module => f -> cokernel matrix {{f}}
image RingElement := Module => f -> image matrix {{f}}

Ideal = new Type of HashTable
LeftIdeal = new Type of HashTable
Ideal = new Type of LeftIdeal
Ideal.synonym = "ideal"

ideal = method(Dispatch => Thing, TypicalValue => Ideal)

expression Ideal := (I) -> (expression ideal) unsequence apply(toSequence first entries generators I, expression)
net Ideal := (I) -> net expression I
toString Ideal := (I) -> toString expression I
toExternalString Ideal := (I) -> "ideal " | toExternalString generators I
texMath Ideal := (I) -> texMath expression I
expression LeftIdeal := (I) -> (expression ideal) unsequence apply(toSequence first entries generators I, expression)
net LeftIdeal := (I) -> net expression I
toString LeftIdeal := (I) -> toString expression I
toExternalString LeftIdeal := (I) -> "ideal " | toExternalString generators I
texMath LeftIdeal := (I) -> texMath expression I

isIdeal Ideal := I -> true
isHomogeneous Ideal := (I) -> isHomogeneous generators I
isIdeal LeftIdeal := I -> true
isHomogeneous LeftIdeal := (I) -> isHomogeneous generators I

degrees Ideal := I -> degrees source generators I
degrees LeftIdeal := I -> degrees source generators I
-- TODO: deprecate these
degreeLength Ideal := I -> degreeLength ring I
degreesRing Ideal := I -> degreesRing ring I
degreeLength LeftIdeal := I -> degreeLength ring I
degreesRing LeftIdeal := I -> degreesRing ring I

promote(Ideal,Number) :=
promote(Ideal,RingElement) := (I,R) -> ideal promote(generators I, R)
promote(LeftIdeal,Number) :=
promote(LeftIdeal,RingElement) := (I,R) -> ideal promote(generators I, R)

comodule Module := Module => M -> cokernel super map(M,M,1)
quotient Module := Module => opts -> M -> comodule M
comodule Ideal := Module => I -> cokernel generators I
quotient Ideal := Module => opts -> I -> (ring I) / I
module Ideal := Module => (cacheValue symbol module) (I -> image generators I)
comodule LeftIdeal := Module => I -> cokernel generators I
quotient LeftIdeal := Module => opts -> I -> (ring I) / I
module LeftIdeal := Module => (cacheValue symbol module) (I -> image generators I)

genera Ideal := (I) -> genera ((ring I)^1/I)
genus Ideal := (I) -> genus ((ring I)^1/I)
genera LeftIdeal := I -> genera ((ring I)^1/I)
genus LeftIdeal := I -> genus ((ring I)^1/I)

eulers(Ideal) := (I) -> eulers((ring I)^1/I)
euler(Ideal) := (I) -> euler((ring I)^1/I)
eulers LeftIdeal := I -> eulers((ring I)^1/I)
euler LeftIdeal := I -> euler((ring I)^1/I)

-- two-sided ideal expected
RingElement * Ideal := Ideal => (r,I) -> ideal (r ** generators I)
Ideal * RingElement := Ideal => (I,r) -> ideal ((generators I)**r)
ZZ * Ideal := (r,I) -> ideal (r * generators I)
Ideal * ZZ := (I,r) -> ideal (r * generators I)

generators Ideal := Matrix => opts -> (I) -> I.generators
Ideal_* := I -> first entries generators I
Ideal / Function := List => (I,f) -> apply(flatten entries generators I, f)
Function \ Ideal := List => (f,I) -> apply(flatten entries generators I, f)
generators LeftIdeal := Matrix => opts -> (I) -> I.generators
LeftIdeal_* := I -> first entries generators I
LeftIdeal / Function := List => (I,f) -> apply(flatten entries generators I, f)
Function \ LeftIdeal := List => (f,I) -> apply(flatten entries generators I, f)

generator = method()
generator Ideal := RingElement => (I) -> (
generator LeftIdeal := RingElement => I -> (
if I.cache.?trim then I = I.cache.trim;
R := ring I;
n := numgens I;
Expand All @@ -487,18 +489,36 @@ generator Module := RingElement => (M) -> (
if n == 1 then return M_0;
error "expected ideal to have a single generator")

Ideal / Ideal := Module => (I,J) -> module I / module J
LeftIdeal / LeftIdeal := Module => (I,J) -> module I / module J

-- two-sided ideal expected
Module / Ideal := Module => (M,J) -> M / (J * M)
Module / LeftIdeal := Module => (M,J) -> (
if isFreeModule M and rank M == 1
then comodule J
else "not defined for a left ideal (in general)"
)

Ideal#AfterPrint = Ideal#AfterNoPrint = (I) -> (Ideal," of ",ring I)
LeftIdeal#AfterPrint = LeftIdeal#AfterNoPrint = I -> (LeftIdeal," of ",ring I)
Ideal#AfterPrint = Ideal#AfterNoPrint = I -> (Ideal," of ",ring I)

-- two-sided ideal expected
Ideal ^ ZZ := Ideal => (I,n) -> ideal symmetricPower(n,generators I)
Ideal * Ideal := Ideal => ((I,J) -> ideal flatten (generators I ** generators J)) @@ samering
Ideal * Module := Module => ((I,M) -> subquotient (generators I ** generators M, relations M)) @@ samering
Ideal + Ideal := Ideal => ((I,J) -> ideal (generators I | generators J)) @@ tosamering
Ideal + RingElement := Ideal + Number := ((I,r) -> I + ideal r) @@ tosamering
RingElement + Ideal := Number + Ideal := ((r,I) -> ideal r + I) @@ tosamering
Ideal _ ZZ := RingElement => (I,n) -> (generators I)_(0,n)

LeftIdeal + LeftIdeal := LeftIdeal => ((I,J) -> ideal (generators I | generators J)) @@ tosamering
-- Ideal + Ideal := Ideal => ((I,J) -> ideal (generators I | generators J)) @@ tosamering
LeftIdeal + RingElement := LeftIdeal + Number := ((I,r) -> I + ideal r) @@ tosamering
RingElement + LeftIdeal := Number + LeftIdeal := ((r,I) -> ideal r + I) @@ tosamering
LeftIdeal _ ZZ := RingElement => (I,n) -> (generators I)_(0,n)


-- Matrix % Ideal is a convenience function... and so is Matrix % LeftIdeal
-- the result of the latter has even less (natural) meaning as a map (on a one-sided module)
Matrix % LeftIdeal := Matrix => ((f,I) -> map(target f, source f, apply(entries f, row -> matrix row % gb I))) @@ samering

-- two-sided ideal expected (note: R/I is a problem !!!)
Matrix % Ideal := Matrix => ((f,I) ->
if numRows f === 1
then f % gb I
Expand All @@ -508,23 +528,28 @@ Matrix % Ideal := Matrix => ((f,I) ->
S := R/I;
lift(promote(f,S),R))
) @@ samering
Vector % Ideal := (v,I) -> new class v from {v#0%I}
numgens Ideal := (I) -> numgens source generators I
leadTerm Ideal := Matrix => (I) -> leadTerm generators gb I
leadTerm(ZZ,Ideal) := Matrix => (n,I) -> leadTerm(n,generators gb I)
jacobian Ideal := Matrix => (I) -> jacobian generators I
Ideal _ List := (I,w) -> (module I)_w

ring Ideal := (I) -> I.ring
Vector % LeftIdeal := (v,I) -> new class v from {v#0%I}

numgens LeftIdeal := I -> numgens source generators I
leadTerm LeftIdeal := Matrix => I -> leadTerm generators gb I
leadTerm(ZZ,LeftIdeal) := Matrix => (n,I) -> leadTerm(n,generators gb I)

-- two-sided ideal expected (unless defined for non-polynomial rings!!!)
jacobian Ideal := Matrix => I -> jacobian generators I

LeftIdeal _ List := (I,w) -> (module I)_w

ring LeftIdeal := I -> I.ring

Ideal == Ring := (I,R) -> (
LeftIdeal == Ring := (I,R) -> (
if ring I =!= R
then error "expected ideal in the given ring";
1_R % I == 0)

Ring == Ideal := (R,I) -> I == R
Ring == LeftIdeal := (R,I) -> I == R

Ideal == Ideal := (I,J) -> (
LeftIdeal == LeftIdeal := (I,J) -> (
samering(I,J);
( generators I == generators J or
-- if isHomogeneous I and isHomogeneous J -- can be removed later
Expand All @@ -533,10 +558,10 @@ Ideal == Ideal := (I,J) -> (
isSubset(I,J) and isSubset(J,I) -- can be removed later
))

Ideal == Module := (I,M) -> module I == M
Module == Ideal := (M,I) -> M == module I
LeftIdeal == Module := (I,M) -> module I == M
Module == LeftIdeal := (M,I) -> M == module I

ideal Matrix := Ideal => (f) -> (
ideal Matrix := LeftIdeal => f -> (
R := ring f;
if not isFreeModule target f or not isFreeModule source f
then error "expected map between free modules";
Expand All @@ -549,9 +574,13 @@ ideal Matrix := Ideal => (f) -> (
g := map(R^1,,f); -- in case the degrees are wrong
if isHomogeneous g then f = g;
);
new Ideal from { symbol generators => f, symbol ring => R, symbol cache => new CacheTable } )
new (
-- Ideal == two-sided ideal
if isWeylAlgebra R then LeftIdeal
else Ideal
) from { symbol generators => f, symbol ring => R, symbol cache => new CacheTable } )

ideal Module := Ideal => (M) -> (
ideal Module := LeftIdeal => M -> (
F := ambient M;
if isSubmodule M and rank F === 1 then ideal generators M
else error "expected a submodule of a free module of rank 1"
Expand All @@ -560,13 +589,14 @@ idealPrepare = method()
idealPrepare RingElement :=
idealPrepare Number := identity
idealPrepare Matrix := m -> flatten entries m
idealPrepare Ideal := I -> I_*
idealPrepare LeftIdeal := I -> I_*
idealPrepare Thing := x -> error "expected a list of numbers, matrices, ring elements or ideals"
ideal List := ideal Sequence := Ideal => v -> ideal matrix {flatten apply(toList splice v,idealPrepare)}
ideal RingElement := ideal Number := Ideal => v -> ideal {v}
ideal List := ideal Sequence := LeftIdeal => v -> ideal matrix {flatten apply(toList splice v,idealPrepare)}
ideal RingElement := ideal Number := LeftIdeal => v -> ideal {v}
ideal Ring := R -> ideal map(R^1,R^0,0)

Ideal ^ Array := (I, e) -> (
-- not well-defined (mathwise!!!)
Ideal ^ Array := (I, e) -> (
R := ring I;
n := numgens R;
-- Error if input is not correct.
Expand Down Expand Up @@ -635,7 +665,7 @@ degree Matrix := List => (f) -> (
if N.?generators then d = d + getshift N.generators;
d)

super(Matrix) := Matrix => (f) -> (
super Matrix := Matrix => (f) -> (
M := target f;
if M.?generators then map(super M, M, M.generators) * f
else f
Expand All @@ -644,18 +674,19 @@ super(Matrix) := Matrix => (f) -> (
isInjective Matrix := (f) -> kernel f == 0
isSurjective Matrix := (f) -> cokernel f == 0

-- two-sided ideal expected
scan({ZZ,QQ}, S -> (
lift(Ideal,S) := opts -> (I,S) -> (
lift(LeftIdeal,S) := opts -> (I,S) -> (
-- this will be pretty slow
if ring I === S then I
else (ideal lift(generators I,S,opts)) + ideal (presentation ring I ** S))));

content(RingElement) := Ideal => (f) -> ideal \\ last \ listForm f
content(RingElement, RingElement) := Ideal => (f,x) -> ideal last coefficients(f, Variables => {x})
content RingElement := LeftIdeal => f -> ideal \\ last \ listForm f
content(RingElement, RingElement) := LeftIdeal => (f,x) -> ideal last coefficients(f, Variables => {x})

cover(Matrix) := Matrix => (f) -> matrix f
cover Matrix := Matrix => f -> matrix f

rank Matrix := (f) -> (
rank Matrix := f -> (
if hasEngineLinearAlgebra ring f and isBasicMatrix f
then basicRank f
else rank image f
Expand Down
14 changes: 7 additions & 7 deletions M2/Macaulay2/m2/matrix2.m2
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ complement Matrix := Matrix => (f) -> (
else error "complement: expected matrix over affine ring or finitely generated ZZ-algebra")

-- the method is declared in gb.m2
mingens Ideal := Matrix => opts -> I -> mingens(module I, opts)
mingens LeftIdeal := Matrix => opts -> I -> mingens(module I, opts)
mingens Module := Matrix => opts -> (cacheValue symbol mingens) ((M) -> (
c := runHooks((mingens, Module), (opts, M));
if c =!= null then c else error "mingens: no method implemented for this type of module"))
Expand Down Expand Up @@ -175,7 +175,7 @@ trim QuotientRing := opts -> (R) -> (
A/(trim(ideal f,opts)))

-- TODO: why is the caching key an Option?
trim Ideal := Ideal => opts -> (cacheValue (symbol trim => opts)) ((I) -> ideal trim(module I, opts))
trim LeftIdeal := LeftIdeal => opts -> (cacheValue (symbol trim => opts)) ((I) -> ideal trim(module I, opts))
trim Module := Module => opts -> (cacheValue symbol trim) (M -> (
if isFreeModule M then return M;
c := runHooks((trim, Module), (opts, M));
Expand Down Expand Up @@ -405,12 +405,12 @@ RingElement % Matrix := (r,f) -> (
else error "expected target of matrix to be free, and of rank 1"
)

RingElement % Ideal := (r,I) -> (
RingElement % LeftIdeal := (r,I) -> (
R := ring I;
if ring r =!= R then error "expected ring element and ideal for the same ring";
if r == 0 then return r;
r % if isHomogeneous I and heft R =!= null then gb(I, DegreeLimit => degree r) else gb I)
Number % Ideal := (r,I) -> (
Number % LeftIdeal := (r,I) -> (
R := ring I;
r = promote(r,R);
if r == 0 then return r;
Expand Down Expand Up @@ -441,7 +441,7 @@ support = method()
support RingElement := support Matrix := (f) -> (
x := rawIndices raw f;
apply(x, i -> (ring f)_i))
support Ideal := (I) -> rsort toList sum apply(flatten entries generators I, f -> set support f)
support LeftIdeal := (I) -> rsort toList sum apply(flatten entries generators I, f -> set support f)
--------------------
-- homogenization --
--------------------
Expand Down Expand Up @@ -489,7 +489,7 @@ homogenize(Module,RingElement) := Module => (M,z) -> (
if M.?generators then homogenize(generators gb M.generators,z),
if M.?relations then homogenize(generators gb M.relations,z)))

homogenize(Ideal,RingElement) := Ideal => (I,z) -> ideal homogenize(module I, z)
homogenize(LeftIdeal,RingElement) := LeftIdeal => (I,z) -> ideal homogenize(module I, z)

homogenize(Module,RingElement,List) := Module => (M,z,wts) -> (
if isFreeModule M then M
Expand Down Expand Up @@ -680,7 +680,7 @@ newCoordinateSystem(PolynomialRing, Matrix) := (S,x) -> (
( map(S,R,vars S * toS n), map(R,S,vars R * n^(-1)) )
)

lift(Ideal,RingElement) := Ideal => opts -> (I,S) -> (
lift(LeftIdeal,RingElement) := Ideal => opts -> (I,S) -> (
-- provisional, just for quotient rings
T := ring I;
if T === S then I
Expand Down
10 changes: 5 additions & 5 deletions M2/Macaulay2/m2/modules2.m2
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ issub := (f, g) -> (
-- TODO: we can do better in the homogeneous case!
addHook(ContainmentHooks, Strategy => Inhomogeneous, (f, g) -> -1 === rawGBContains(raw gb g, raw f))

ZZ == Ideal := (n,I) -> I == n
Ideal == ZZ := (I,n) -> (
ZZ == LeftIdeal := (n,I) -> I == n
LeftIdeal == ZZ := (I,n) -> (
if n === 0
then I.generators == 0
else if n === 1
Expand Down Expand Up @@ -367,9 +367,9 @@ isSubset(Module,Module) := (M,N) -> (
false
)
)
isSubset(Ideal,Ideal) := (I,J) -> isSubset(module I, module J)
isSubset(Module,Ideal) := (M,J) -> isSubset(M, module J)
isSubset(Ideal,Module) := (I,N) -> isSubset(module I, N)
isSubset(LeftIdeal,LeftIdeal) := (I,J) -> isSubset(module I, module J)
isSubset(Module,LeftIdeal) := (M,J) -> isSubset(M, module J)
isSubset(LeftIdeal,Module) := (I,N) -> isSubset(module I, N)

-- Local Variables:
-- compile-command: "make -C $M2BUILDDIR/Macaulay2/m2 "
Expand Down
Loading
Loading