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 as a Module #3032

Draft
wants to merge 9 commits into
base: development
Choose a base branch
from
Draft
1 change: 1 addition & 0 deletions M2/Macaulay2/m2/exports.m2
Expand Up @@ -237,6 +237,7 @@ export {
"LUdecomposition",
"Layout",
"Left",
"LeftIdeal",
"LengthLimit",
"Lex",
"Limit",
Expand Down
5 changes: 5 additions & 0 deletions M2/Macaulay2/m2/intersect.m2
Expand Up @@ -85,6 +85,11 @@ intersect(Module, Module) := Module => moduleIntersectOpts >> opts -> L -> inter
Ideal.intersect = idealIntersectOpts >> opts -> L -> intersectHelper(L, (intersect, Ideal, Ideal), opts)
Module.intersect = moduleIntersectOpts >> opts -> L -> intersectHelper(L, (intersect, Module, Module), opts)

-- Left ideals
intersect LeftIdeal := LeftIdeal => moduleIntersectOpts >> o -> I -> ideal intersect(module I, o)
intersect(LeftIdeal, LeftIdeal) := LeftIdeal => moduleIntersectOpts >> o -> (I, J) -> ideal intersect(module I, module J, o)
LeftIdeal.intersect = moduleIntersectOpts >> o -> L -> ideal intersect(module \ L, o)

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

-- The algorithm below is optimized for intersecting all modules at once.
Expand Down
84 changes: 79 additions & 5 deletions M2/Macaulay2/m2/matrix1.m2
Expand Up @@ -418,17 +418,24 @@ cokernel Matrix := Module => m -> (
cokernel RingElement := Module => f -> cokernel matrix {{f}}
image RingElement := Module => f -> image matrix {{f}}

-----------------------------------------------------------------------------
-- Ideal type declaration
-----------------------------------------------------------------------------
-- Note: all ideals will be two-sided

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

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

-- printing
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

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

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

Expand All @@ -443,7 +450,7 @@ promote(Ideal,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
quotient Ideal := o -> I -> (ring I) / I
module Ideal := Module => (cacheValue symbol module) (I -> image generators I)

genera Ideal := (I) -> genera ((ring I)^1/I)
Expand Down Expand Up @@ -488,8 +495,6 @@ generator Module := RingElement => (M) -> (
Ideal / Ideal := Module => (I,J) -> module I / module J
Module / Ideal := Module => (M,J) -> M / (J * M)

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

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
Expand Down Expand Up @@ -534,6 +539,67 @@ Ideal == Ideal := (I,J) -> (
Ideal == Module := (I,M) -> module I == M
Module == Ideal := (M,I) -> M == module I

-----------------------------------------------------------------------------
-- Left ideals
-----------------------------------------------------------------------------

LeftIdeal = new Type of Module -- or LeftModule, or ImmutableType?
LeftIdeal.synonym = "left-ideal"

expression LeftIdeal := lookup(expression, Ideal)
LeftIdeal#AfterPrint = Ideal#AfterPrint
LeftIdeal#AfterNoPrint = Ideal#AfterNoPrint

isTwoSidedIdeal = I -> isIdeal I and (
-- variables appearing in I
sup := index \ support I;
-- differential variables in ring of I
dxs := last \ (ring I).WeylAlgebra;
-- check that they don't have any intersection
#sup + #dxs == #unique join(sup, dxs))

comodule LeftIdeal := Module => I -> cokernel generators I
quotient LeftIdeal := o -> I -> (ring I) / I
Ring / LeftIdeal := (R, I) -> (
if isTwoSidedIdeal I then R / new Ideal from I else
error "Ring / LeftIdeal is not implemented for left ideals")

LeftIdeal * RingElement := LeftIdeal => (I, f) -> (
if isTwoSidedIdeal I then (new Ideal from I) * f else
error "LeftIdeal * RingElement is not implemented for left ideals")
LeftIdeal * Module := Module => ((I, M) -> subquotient(generators I ** generators M, relations M)) @@ samering

LeftIdeal + LeftIdeal := LeftIdeal => ((I, J) -> ideal(generators I | generators J)) @@ tosamering
LeftIdeal + RingElement := LeftIdeal + Number := LeftIdeal => ((I, r) -> I + ideal r) @@ tosamering
RingElement + LeftIdeal := Number + LeftIdeal := LeftIdeal => ((r, I) -> ideal r + I) @@ tosamering

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

Number % LeftIdeal := (r, I) -> promote(r, ring I) % I
RingElement % LeftIdeal := (r, I) -> (
if (R := ring I) =!= ring r then error "expected ring element and ideal for the same ring";
if r == 0 then r else if isHomogeneous I and heft R =!= null
then r % gb(I, DegreeLimit => degree r) else r % gb I)

Matrix % LeftIdeal := Matrix => ((f,I) -> map(target f, source f, apply(entries f, row -> matrix row % gb I))) @@ samering
Vector % LeftIdeal := Vector => ((v,I) -> new class v from {v#0%I}) @@ samering

dim LeftIdeal := I -> dim comodule I
module LeftIdeal := I -> new Module from I
numgens LeftIdeal := I -> numgens source generators I

LeftIdeal_* := List => I -> first entries generators I
LeftIdeal_ZZ := RingElement => (I, n) -> (generators I)_(0,n)

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

-----------------------------------------------------------------------------
-- Primary constructor
-----------------------------------------------------------------------------

ideal = method(Dispatch => Thing, TypicalValue => Ideal)
ideal Matrix := Ideal => (f) -> (
R := ring f;
if not isFreeModule target f or not isFreeModule source f
Expand All @@ -547,23 +613,29 @@ ideal Matrix := Ideal => (f) -> (
g := map(R^1,,f); -- in case the degrees are wrong
if isHomogeneous g then f = g;
);
if isWeylAlgebra R then
new LeftIdeal from subquotient(f, null) else
new Ideal from { symbol generators => f, symbol ring => R, symbol cache => new CacheTable } )

ideal Module := Ideal => (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"
)

idealPrepare = method()
idealPrepare RingElement :=
idealPrepare Number := identity
idealPrepare Matrix := m -> flatten entries m
idealPrepare Ideal := 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 Ring := R -> ideal map(R^1,R^0,0)

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

Ideal ^ Array := (I, e) -> (
R := ring I;
n := numgens R;
Expand All @@ -579,6 +651,8 @@ Ideal ^ Array := (I, e) -> (
ideal phi generators I
)

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

homology(Matrix,Matrix) := Module => opts -> (g,f) -> (
if g == 0 then cokernel f
else if f == 0 then kernel g
Expand Down
8 changes: 4 additions & 4 deletions M2/Macaulay2/m2/matrix2.m2
Expand Up @@ -438,10 +438,10 @@ indices RingElement := (f) -> rawIndices raw f
indices Matrix := (f) -> rawIndices raw f

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 RingElement :=
support Matrix := f -> apply(try rawIndices raw f else {}, i -> (ring f)_i)
support LeftIdeal :=
support Ideal := I -> support generators I
--------------------
-- homogenization --
--------------------
Expand Down
8 changes: 7 additions & 1 deletion M2/Macaulay2/m2/newring.m2
Expand Up @@ -62,7 +62,11 @@ QuotientRing ** PolynomialRing :=
PolynomialRing ** QuotientRing :=
QuotientRing ** QuotientRing := (R,S) -> tensor(R,S)

tensor(PolynomialRing, PolynomialRing) :=
tensor(PolynomialRing, PolynomialRing) := monoidTensorDefaults >> optns -> (R, S) -> (
if (kk := coefficientRing R) === coefficientRing S
then kk tensor(monoid R, monoid S, optns)
else error "expected rings to have the same coefficient ring")

tensor(QuotientRing, PolynomialRing) :=
tensor(PolynomialRing, QuotientRing) :=
tensor(QuotientRing, QuotientRing) := monoidTensorDefaults >> optns -> (R, S) -> (
Expand Down Expand Up @@ -125,6 +129,8 @@ coerce(Thing,Thing) := (x,Y) -> if instance(x,Y) then x else error("no method fo
coerce(Ideal,Ring) := quotient @@ first
coerce(Thing,Nothing) := (x,Nothing) -> null -- avoid using this one, to save time earlier
coerce(Ring,Ideal) := (R,Ideal) -> ideal R -- avoid using this one, to save time earlier
coerce(LeftIdeal,Ring) := quotient @@ first
coerce(LeftIdeal,Ideal) := first
preprocessResultTemplate = (narrowers,r) -> (
if instance(r,ZZ) then r = r:null;
r = apply(sequence r,x -> if x === null then Thing else x);
Expand Down
1 change: 1 addition & 0 deletions M2/Macaulay2/m2/ringmap.m2
Expand Up @@ -209,6 +209,7 @@ RingMap Module := Module => (f, M) -> (
-- use the same module if we can
if R === S and d === e then M else S^-e)
)
RingMap LeftIdeal := LeftIdeal => (f, I) -> ideal f module I

-- misc
tensor(RingMap, Module) := Module => {} >> opts -> (f, M) -> (
Expand Down