M2 icon indicating copy to clipboard operation
M2 copied to clipboard

LeftIdeal (take two)

Open antonleykin opened this issue 1 year ago • 29 comments

(This is a fresh take on https://github.com/Macaulay2/M2/pull/2912)

Ideal is a type of LeftIdeal now.

  • Most functions are defined for LeftIdeal;
  • the ones that make sense only for a two-sided ideal are defined for Ideal.
  • The method ideal constructs an ideal typical for the given ring: e.g.,
    • LeftIdeal for a Weyl algebra and
    • Ideal for all other algebras: e.g., polynomial ring, skew-commutative ring, AssociativeAlgebra, etc.

Current state:

  • there seem to be no errors in the build process
  • there still may be methods that can migrate from Ideal to LeftIdeal; currently
    • (clean session of M2) #methods Ideal is 223 and # methods LeftIdeal is 66
    • (after needsPackage "BernsteinSato") #methods Ideal is 271 and # methods LeftIdeal is 151

Whoever is interested in noncommutative things, please look at this.

antonleykin avatar Nov 29 '23 17:11 antonleykin

I still don't understand why we care about left ideals (or right ideals, for that matter), cf my comment in the other PR.

pzinn avatar Dec 03 '23 01:12 pzinn

I still don't understand why we care about left ideals (or right ideals, for that matter), cf my comment in the other PR.

In the ideal world (pun intended), one may not care about ideals. Left, right, or two-sided --- all of them are modules (as we know and as you stressed). In the real world of M2, a design decision was made 20+ years ago to incorporate Weyl algebras and make low-level core GB functionality work for left ideals (left ideals is what $D$-modules people care about). No new type was introduced at that point. The purpose of this pull request is to correct the latter.

At some future point, once all kinds of modules are present --- left, right, two-sided, perhaps ones with multiple left/right actions --- one can come back to the discussion of not having ideals (or having all of the ideal types derived from module types).

antonleykin avatar Dec 04 '23 20:12 antonleykin

make low-level core GB functionality work for left ideals

I don't understand. Which core GB functionality is implemented for left ideals specifically, or even ideals for that matter? I think the only GB related methods used in Dmodules and friends (raw or top level) take in the generator matrices of the given ideals, and things like gb Ideal directly call gb module I.

With that in mind, an alternative way to "correct the latter" could be to directly define left modules (for now only modules that are the image of a 1-by-n matrix), add a new subtype called LeftIdeal, redefine all Dmodule methods to take in a LeftIdeal instead of an Ideal, and give an error for ideals in Weyl algebras.

mahrud avatar Dec 04 '23 22:12 mahrud

@d-torrance , I'm having problems reproducing the errors (which relate to RInterface) in the builds. I'm using brewed R on MacOS.

antonleykin avatar Dec 13 '23 17:12 antonleykin

That bug was fixed in #3034, so merging/rebasing onto development should work!

d-torrance avatar Dec 13 '23 18:12 d-torrance

My (possibly biased) summary of the discussion we've had. The main concern is the fact that people who only care about commutative algebra (which is probably 95% of users at the moment) could be confused by the lack of methods for Ideal (as obtained by say methods Ideal) because a lot of them have been transferred to LeftIdeal (a type which commutative algebra users don't care about, nor should they need to). It's also clear that something must be done to fix the current situation which is unsatisfactory, and it seems like the alternatives are met with even more resistance... I do feel it's a bit early to merge this into the next release, but that's just my opinion.

pzinn avatar Jan 23 '24 22:01 pzinn

Oh, I couldn't attend the meeting, but I don't think this is ready to be merged either.

mahrud avatar Jan 23 '24 22:01 mahrud

I do feel it's a bit early to merge this into the next release, but that's just my opinion.

I agree with Paul's assessment. Mike suggested that we wait with it until the release after the next. It'd be good to set up a small group meeting to talk about it.

antonleykin avatar Jan 23 '24 23:01 antonleykin

I do feel it's a bit early to merge this into the next release, but that's just my opinion.

I agree with Paul's assessment. Mike suggested that we wait with it until the release after the next. It'd be good to set up a small group meeting to talk about it.

Then mark it as a draft.

DanGrayson avatar Jan 24 '24 17:01 DanGrayson

(I think I converted it back to "Draft".) A quick comment on what seems to be the main issue with this PR for @mahrud.
What would work is just simple duplicating: e.g.,

Ideal + Ideal := lookup(symbol +,LeftIdeal,LeftIdeal)

makes methods Ideal list +. There is probably some way to automate this so that all methods for a "vital" subtype both get listed for the parent type by methods and appear in the documentation. @DanGrayson, what do you think?

@mahrud, yesterday we talked about this as a general issue: my example, similar to Ideal and LeftIdeal, was List and BasicList. (Several beginners asked me over the years why they don't see apply and scan listed by methods List.) Perhaps we should be doing this duplication trick for selected types where people think "beginner confusion" is perceived to be common.

antonleykin avatar Jan 25 '24 02:01 antonleykin

I thought a little bit about how to make methods work to show methods for ancestors after our meeting on Tuesday. One (probably not very efficient) way is unique \\ join \\ toSequence \\ methods \ ancestors X for a given class X, but I think that would give you some methods that you wouldn't actually be able to call. For example:

i1 : X = new Type of HashTable;

i2 : Y = new Type of X;

i3 : f = method();

i4 : f(X, X) := (x,y) -> 1;

i5 : f(X, Y) := (x,y) -> 2;

i6 : f(Y, X) := (x,y) -> 3;

i7 : f(Y, Y) := (x,y) -> 4;

i8 : unique \\ join \\ toSequence \\  methods \ ancestors Y

o8 = {0 => (f, X, Y)                                                         }
     {1 => (f, Y, X)                                                         }
     {2 => (f, Y, Y)                                                         }
     {3 => (f, X, X)                                                         }
     {4 => (#, HashTable)                                                    }
 ...

Ideally, we'd remove (f, X, X) from the list since you'll never actually get it if one of the arguments is a Y object. But that seems tricky to check.

d-torrance avatar Jan 25 '24 15:01 d-torrance

A quick comment on what seems to be the main issue with this PR for @mahrud. What would work is just simple duplicating: e.g.,

  1. duplicating methods is never a good solution in my opinion.
  2. this is definitely not the "main" issue for me, I just gave methods as an example of something a beginner might be confused about. I'm objecting to Ideal being synonymous with "two-sided ideal" in this PR because I think "a left ideal is an ideal" is a correct statement and it should mean that LeftIdeal is a type that implements some abstract methods of Ideal.

mahrud avatar Jan 25 '24 15:01 mahrud

At least in Dummit & Foote (where I first learned these things from), left ideal and right ideal are more general than ideal:

A subset I that is both a left ideal and a right ideal is called an ideal (or, for added emphasis, a two-sided ideal) of R.

Of course, if we want the inheritance in Macaulay2 to work the same way as the mathematical definitions, we have some issues:

  • We don't support multiple inheritance, so there's currently no way for Ideal to be a child of both LeftIdeal and RightIdeal.
  • Even if we did support multiple inheritance, then what would the parents of LeftIdeal and RightIdeal be? SubsetOfRing or something like that?

d-torrance avatar Jan 25 '24 15:01 d-torrance

Even if we did support multiple inheritance, then what would the parents of LeftIdeal and RightIdeal be? SubsetOfRing or something like that?

Module. What is the reason for differentiating them?

mahrud avatar Jan 25 '24 16:01 mahrud

Even if we did support multiple inheritance, then what would the parents of LeftIdeal and RightIdeal be? SubsetOfRing or something like that?

Module. What is the reason for differentiating them?

The parent of LeftIdeal would be LeftModule, and the parent of RightIdeal would be RightModule.

DanGrayson avatar Jan 25 '24 19:01 DanGrayson

The parent of LeftIdeal would be LeftModule, and the parent of RightIdeal would be RightModule.

What would their parents be? Presumably Module would inherit from LeftModule and RightModule as well. And Ideal maybe should inherit from Module in addition to the two one-sided ideal classes. The class diagram could get pretty ugly!

d-torrance avatar Jan 25 '24 19:01 d-torrance

The parent of LeftIdeal would be LeftModule, and the parent of RightIdeal would be RightModule.

What would their parents be? Presumably Module would inherit from LeftModule and RightModule as well. And Ideal maybe should inherit from Module in addition to the two one-sided ideal classes. The class diagram could get pretty ugly!

The parents of LeftModule and RightModule would be ImmutableType.

If we introduce BiModule, then that would inherit from LeftModule and RightModule.

DanGrayson avatar Jan 25 '24 19:01 DanGrayson

We don't have "QuotientModule" and "FreeModule" and "ImageModule" and "SubquotientModule". We just have "Module".

I'll explain more on Zulip soon.

mahrud avatar Jan 25 '24 19:01 mahrud

Yes, but we have to decide whether Module means left module or right module, and convert to LeftModule or RightModule.

We can always introduce BiModule if we wish.

DanGrayson avatar Jan 25 '24 19:01 DanGrayson

but we have to decide whether Module means left module or right module

No, it can mean both! For the same reason that Module can mean both free module or quotient module or torsion module or whatever else.

mahrud avatar Jan 27 '24 07:01 mahrud

but we have to decide whether Module means left module or right module

No, it can mean both! For the same reason that Module can mean both free module or quotient module or torsion module or whatever else.

No, it can't. Consider the method for Hom(Module,Module). What would it do if given a left module and a right module over R?

DanGrayson avatar Jan 29 '24 00:01 DanGrayson

Either return an error or only define the method on left or right modules.

mahrud avatar Jan 29 '24 00:01 mahrud

If $M$ and $N$ are both left and right $R$-modules, what would Hom(M,N) return?

mikestillman avatar Jan 29 '24 00:01 mikestillman

I guess we could have an optional argument LeftModules, or RightModules (or something similar).

mikestillman avatar Jan 29 '24 00:01 mikestillman

If M and N are both left and right R-modules, what would Hom(M,N) return?

It would return a module with both left and right R-module structures.

mahrud avatar Jan 29 '24 01:01 mahrud

The problem is that it eats either the left module structure, or the right module structure, leaving only the other (in the non-commutative case).

mikestillman avatar Jan 29 '24 01:01 mikestillman

The problem is that it eats either the left module structure, or the right module structure, leaving only the other (in the non-commutative case).

I don't understand this comment. I presume you meant the left and right actions on M and N are the same, in which case the left Hom and right Hom should be identical, no?

Otherwise, like I said before, don't define Hom(Module,Module). Only define the methods that make sense, like Hom(LeftModule,LeftModule) and Hom(RightModule, RightModule).

The point is that methods installed on an abstract module type are exactly those that don't care whether it's a left or right module. If Hom cares, then it should only be defined on the appropriate specializations.

mahrud avatar Jan 29 '24 01:01 mahrud

So is the idea that Module is the (possibly abstract) class of all modules, LeftModule, RightModule, and perhaps Bimodule, all inherit from Module (maybe Bimodule inherits from both LeftModule, RightModule, maybe not)? We would need Hom(LeftModule, LeftModule), Hom(RightModule, RightModule), and various versions with Bimodule. Actually, if the arguments are 2 bimodules, we would need a way of dis-ambiguating which Hom we wish to consider.

mikestillman avatar Jan 29 '24 01:01 mikestillman

Yes, exactly.

mahrud avatar Jan 29 '24 02:01 mahrud