-
Notifications
You must be signed in to change notification settings - Fork 292
Added the Subring package #3736
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
base: development
Are you sure you want to change the base?
Changes from 24 commits
e2e4fba
f1f3aa0
2564a4a
2b35a8a
c5e7721
ce9c38d
c81444a
c6774f2
308d007
98da806
b38618a
6d807f5
1a37f6f
fdf5ff2
287c51b
79bc995
c9bb90c
9785924
0dd0ba9
7332fd8
6624403
149d940
89210ef
69c567b
2f4dcb4
b4777fe
7b061ac
ce6a670
27ee670
67170be
2c5af3e
1492759
571b39c
7b8351d
6b67548
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| # This workflow builds the Macaulay2 testbot Docker image from | ||
| # M2/BUILD/docker/testbot/Dockerfile and pushes it to GitHub Packages, | ||
| # tagged with the current Macaulay2 version (see M2/VERSION) and "latest". | ||
| # | ||
| # The resulting image is published at | ||
| # https://github.com/Macaulay2/M2/pkgs/container/testbot | ||
|
|
||
| name: Build and push testbot Docker image | ||
|
|
||
| on: workflow_dispatch | ||
|
|
||
| env: | ||
| IMAGE_NAME: ghcr.io/macaulay2/testbot | ||
|
|
||
| jobs: | ||
| docker-testbot: | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| packages: write | ||
|
|
||
| steps: | ||
| - uses: actions/checkout@v6 | ||
|
|
||
| - name: Determine image tags | ||
| run: | | ||
| M2_VERSION=$(cat M2/VERSION) | ||
| echo "M2_VERSION=$M2_VERSION" >> "$GITHUB_ENV" | ||
|
|
||
| - name: Log in to GitHub Container Registry | ||
| uses: docker/login-action@v3 | ||
| with: | ||
| registry: ghcr.io | ||
| username: ${{ github.actor }} | ||
| password: ${{ secrets.GITHUB_TOKEN }} | ||
|
|
||
| - name: Build and push image | ||
| uses: docker/build-push-action@v6 | ||
| with: | ||
| context: M2/BUILD/docker/testbot | ||
| push: true | ||
| tags: | | ||
| ${{ env.IMAGE_NAME }}:v${{ env.M2_VERSION }} | ||
| ${{ env.IMAGE_NAME }}:latest |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,204 @@ | ||
| -- -*- coding: utf-8 -*- | ||
| newPackage( | ||
| "Subrings", | ||
| Version => "1.1", | ||
| Date => "July 3, 2026", | ||
| Authors => { | ||
| {Name => "Francesca Gandini", Email => "fra.gandi.phd@gmail.com"}, | ||
| {Name => "Casey Hill", Email => "casey.hill@uky.edu"}, | ||
| {Name => "Trevor K. Karn", Email => "karnx018@umn.edu"}, | ||
| {Name => "Miranda Moore", Email => "moor2340@umn.edu"}, | ||
| {Name => "Christopher O'Neill", Email => "cdoneill@sdsu.edu"}, | ||
| {Name => "Oliver Clarke", Email => "oliver.clarke@durham.ac.uk"} | ||
| }, | ||
|
|
||
| Headline => "a package for subrings", | ||
| Keywords => {"Commutative Algebra"}, | ||
| AuxiliaryFiles => true, | ||
| DebuggingMode => true | ||
|
ollieclarke8787 marked this conversation as resolved.
Outdated
|
||
| ) | ||
|
|
||
|
|
||
| export {"subring", | ||
| "subringGenerators", | ||
| "presentationRing", | ||
| "presentationMap", | ||
| "presentationIdeal", | ||
| "toQuotientRing", | ||
| "isSubringElement", | ||
| "GeneratorSymbol", | ||
| "flattenedRing" | ||
|
ollieclarke8787 marked this conversation as resolved.
Outdated
|
||
| } | ||
|
|
||
| Subring = new Type of HashTable | ||
|
|
||
| -- a method to create subrings from a `Matrix` of generators | ||
| subring = method( | ||
| Options => {GeneratorSymbol=>null} | ||
| ) | ||
| subring Matrix := opts -> genMatrix -> ( | ||
| if genMatrix.cache#?Subring then return genMatrix.cache#Subring; | ||
| -- compute presentation ring | ||
| R := ring genMatrix; | ||
| -- deal with towers of rings | ||
| (F,RtoF,FtoR) := flattenRing(R,Result=>3); | ||
| coeffRing := coefficientRing F; | ||
| local subductionRing; | ||
| if instance(opts.GeneratorSymbol,Nothing) then | ||
| subductionRing = coeffRing(monoid[Variables => numcols genMatrix]) | ||
| else if instance(opts.GeneratorSymbol,Symbol) then | ||
| subductionRing = coeffRing[opts.GeneratorSymbol_1..opts.GeneratorSymbol_(numcols genMatrix)] | ||
| else error("Invalid GeneratorSymbol option"); | ||
| presentationMap := map(R,subductionRing,genMatrix); | ||
| S := new Subring from { | ||
| "ambientRing" => R, | ||
| "flattenedRing" => F, | ||
| "generators" => RtoF genMatrix, | ||
| "originalGenerators" => genMatrix, | ||
| "presentationRing" => subductionRing, | ||
| "presentationMap" => presentationMap, | ||
| "flatteningMap" => RtoF, | ||
| "inverseFlatteningMap" => FtoR, | ||
| cache => new CacheTable from {} | ||
| }; | ||
| genMatrix.cache#Subring = S | ||
| ) | ||
|
|
||
| -- a method to create subrings from a `List` of generators | ||
| subring List := opts -> genList -> ( | ||
| subring(matrix {genList}, opts) | ||
| ) | ||
|
|
||
| flattenedRing = method() | ||
| flattenedRing Subring := S -> S#"flattenedRing" | ||
|
Comment on lines
+71
to
+72
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not just install a method
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
|
||
| presentationRing = method() | ||
| presentationRing Subring := S -> ( | ||
| S#"presentationRing" | ||
| ) | ||
|
|
||
| presentationMap = method() | ||
| presentationMap Subring := S -> ( | ||
| S#"presentationMap" | ||
| ) | ||
|
|
||
| presentationIdeal = method() | ||
| presentationIdeal Subring := S -> ( | ||
| f := presentationMap S; | ||
| return ker f; --kernel is cached automatically | ||
| ) | ||
|
|
||
| -- a quotient ring isomorphic to the image of the subring inside of the presentation ring | ||
| toQuotientRing = method() | ||
| toQuotientRing Subring := S -> ( | ||
| P := presentationRing S; | ||
| I := presentationIdeal S; | ||
| return P/I; | ||
| ) | ||
|
|
||
| subringGenerators = method() -- gens that live in flattened ring | ||
| subringGenerators Subring := S -> S#"generators" | ||
|
|
||
| generators Subring := Matrix => opts -> S -> ( -- gens that live in ambient ring | ||
| S#"originalGenerators" | ||
| ) | ||
|
|
||
| ambient Subring := S -> S#"ambientRing" | ||
|
|
||
| numgens Subring := S -> numcols gens S | ||
|
|
||
| -- format printing of Subring type | ||
| net Subring := S -> ( | ||
| R := ambient S; | ||
| P := presentationRing S; | ||
| g := flatten entries gens S; | ||
| genstr := ""; | ||
| if #g <= 3 then ( | ||
| genstr = toString(g_{0 .. min(2, #g-1)}); | ||
| ) else ( | ||
| genstr = "{" | toString(g_0) | ", " | toString(g_1) | ", " | toString(g_2) | ", ...}"; | ||
| ); | ||
|
|
||
| "Subring of " | toString(R) | " generated by " | genstr | " with presentation ring " | toString(P) | ||
| ) | ||
|
|
||
| -* | ||
| TODO: | ||
| -- use hooks, see: | ||
| -- help "using hooks" | ||
| -- to dynamically dispatch the task of computing the subring membership | ||
| -- this will allow other packages to provide more efficient algorithms later | ||
| -- For example, the SublagebraBases package can 'addHook' some function that | ||
| -- checks if there is a SAGBI basis, and if there is, uses subduction to check membership | ||
| *- | ||
|
|
||
|
|
||
| -- given a subring S and an element x of the ambient ring, checks whether x is in S | ||
| isSubringElement = method() | ||
| isSubringElement(RingElement, Subring) := (r, S) -> ( | ||
| if not S.cache#?"tensorGraphIdeal" and not S.cache#?"ambientToTensor" then ( | ||
| R := ambient S; | ||
| F := flattenedRing S; | ||
| P := presentationRing S; | ||
| T := tensor(F, P, MonomialOrder=>Eliminate(numgens F)); | ||
| gT := vars T; | ||
| F2T := map(T, F, gT_{0 .. numgens F - 1}); | ||
| R2T := F2T * (S#"flatteningMap"); | ||
| P2T := map(T, P, gT_{numgens F .. numgens T - 1}); | ||
| subringGens := subringGenerators S; | ||
| presGens := matrix {gens P}; | ||
| graphIdealGens := P2T(presGens) - F2T(subringGens); | ||
| I := ideal graphIdealGens; | ||
| S.cache#"tensorGraphIdeal"=I; | ||
| S.cache#"ambientToTensor"=R2T; | ||
| ); | ||
| M := matrix {{S.cache#"ambientToTensor"(r) % S.cache#"tensorGraphIdeal"}}; | ||
| selectInSubring(1, M) == M | ||
| ) | ||
|
|
||
| -- equality of Subrings | ||
| -- check that every generator of S1 is in S2 and every generator of S2 is in S1 | ||
| Subring == Subring := (S1, S2) -> ( | ||
| if not (ambient S1) === (ambient S2) then return false; | ||
| all(entries(subringGenerators S1)_0, f -> isSubringElement(f, S2)) and all(entries(subringGenerators S2)_0, f -> isSubringElement(f, S1)) | ||
| ) | ||
|
|
||
|
|
||
| ----------------------------------------- | ||
| --- Load documentation and test files --- | ||
| ----------------------------------------- | ||
| beginDocumentation() | ||
|
|
||
| load "./Subrings/SubringDoc.m2" | ||
| load "./Subrings/SubringTests.m2" | ||
|
|
||
| end-- | ||
|
|
||
| restart | ||
| installPackage "Subrings" | ||
| R = QQ[x] | ||
| S1 = subring {x, x^2} | ||
| S2 = subring {x^2} | ||
| S3 = subring {x} | ||
| S1 == S3 --true | ||
| S1 == S2 --false | ||
|
|
||
| net S3 | ||
|
|
||
| mingens S1 | ||
| presentationRing S1 | ||
| mingens | ||
|
|
||
| gens S1 | ||
|
|
||
| -- run tests | ||
| check Subring | ||
|
|
||
|
|
||
|
|
||
| R = QQ[x][y] | ||
| S = subring {x+y, x*y} | ||
| r = x^4 + y^4 | ||
| isSubringElement(r, S) | ||
| isSubringElement(r + x, S) | ||
| isSubringElement(r + x*y, S) | ||
Uh oh!
There was an error while loading. Please reload this page.