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
Draft

Conversation

antonleykin
Copy link
Contributor

@antonleykin antonleykin commented Nov 29, 2023

(This is a fresh take on #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.

@pzinn
Copy link
Contributor

pzinn commented Dec 3, 2023

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

@antonleykin
Copy link
Contributor Author

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).

@mahrud
Copy link
Member

mahrud commented Dec 4, 2023

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.

if numRows f === 1
then f % gb I
else
error "not implemented (defined for two-sided ideals; see `code (symbol %, Matrix, Ideal)`)"
Copy link
Member

@mahrud mahrud Dec 5, 2023

Choose a reason for hiding this comment

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

There is a comment in the two-sided code that says:

we should have an engine routine to reduce each entry of a matrix modulo an ideal, to make this faster

If RingElement % LeftIdeal is defined, why not just run that on every element? Or better yet, like this:

Matrix % LeftIdeal := Matrix => ((f,I) -> map(target f, source f, apply(entries f, row -> matrix row % gb I))) @@ samering

@antonleykin
Copy link
Contributor Author

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

@d-torrance
Copy link
Member

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

@antonleykin antonleykin marked this pull request as ready for review January 23, 2024 21:13
@pzinn
Copy link
Contributor

pzinn commented Jan 23, 2024

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.

@mahrud
Copy link
Member

mahrud commented Jan 23, 2024

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

@antonleykin
Copy link
Contributor Author

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.

@DanGrayson
Copy link
Member

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.

@antonleykin antonleykin marked this pull request as draft January 25, 2024 02:06
@antonleykin
Copy link
Contributor Author

(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.

@d-torrance
Copy link
Member

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.

@mahrud
Copy link
Member

mahrud commented Jan 25, 2024

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.

@d-torrance
Copy link
Member

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?

@mahrud
Copy link
Member

mahrud commented Jan 25, 2024

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?

@DanGrayson
Copy link
Member

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.

@d-torrance
Copy link
Member

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!

@DanGrayson
Copy link
Member

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.

@mahrud
Copy link
Member

mahrud commented Jan 25, 2024

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

I'll explain more on Zulip soon.

@DanGrayson
Copy link
Member

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.

@mahrud
Copy link
Member

mahrud commented Jan 27, 2024

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.

@DanGrayson
Copy link
Member

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?

@mahrud
Copy link
Member

mahrud commented Jan 29, 2024

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

@mikestillman
Copy link
Member

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

@mikestillman
Copy link
Member

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

@mahrud
Copy link
Member

mahrud commented Jan 29, 2024

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.

@mikestillman
Copy link
Member

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).

@mahrud
Copy link
Member

mahrud commented Jan 29, 2024

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.

@mikestillman
Copy link
Member

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.

@mahrud
Copy link
Member

mahrud commented Jan 29, 2024

Yes, exactly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants