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

monomial basis for MPolyQuoLocRing #4235

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/Rings/mpoly-affine-algebras.jl
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ end

@doc raw"""
monomial_basis(A::MPolyQuoRing)
monomial_basis(R::MPolyRing, I::MPolyIdeal)

If, say, `A = R/I`, where `R` is a multivariate polynomial ring over a field
`K`, and `I` is an ideal of `R`, return a vector of monomials of `R`
Expand Down Expand Up @@ -151,6 +152,11 @@ function monomial_basis(A::MPolyQuoRing)
return gens(MPolyIdeal(base_ring(I), si))
end

function monomial_basis(R::MPolyRing, I::MPolyIdeal)
base_ring(I) == R || error("ideal does not belong to the correct ring")
Comment on lines +155 to +156
Copy link
Member

Choose a reason for hiding this comment

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

Looking at this I was wondering "Why does one have to specify R at all? Why not just this:"

Suggested change
function monomial_basis(R::MPolyRing, I::MPolyIdeal)
base_ring(I) == R || error("ideal does not belong to the correct ring")
function monomial_basis(I::MPolyIdeal)
R = base_ring(I)

Perhaps the answer is "because this is not really a "monomial basis of I so we want to avoid the impression that is by giving two arguments". I can see why one would want to avoid writing down a quotient "just" to get this monomial basis. But it still feels at odds with fundamental OSCAR principles (where we like to avoid such tricks). And in any case, you still compute quo in here, so there is nothing being saved here...

Mathematically I think this is about finding a monomial basis of a complement of I in R. So an alternatively would be to do something like this:

Suggested change
function monomial_basis(R::MPolyRing, I::MPolyIdeal)
base_ring(I) == R || error("ideal does not belong to the correct ring")
function monomial_basis_of_complement(I::MPolyIdeal)
R = base_ring(I)

And then one could go a step further and move most of the body of the monomial_basis(A::MPolyQuoRing) method in here, as it only uses I, not the quotient ring?

Copy link
Collaborator

@afkafkafk13 afkafkafk13 Oct 30, 2024

Choose a reason for hiding this comment

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

Perhaps the answer is "because this is not really a "monomial basis of I so we want to avoid the impression that is by giving two arguments". I can see why one would want to avoid writing down a quotient "just" to get this monomial basis. But it still feels at odds with fundamental OSCAR principles (where we like to avoid such tricks). And in any case, you still compute quo in here, so there is nothing being saved here...

This is indeed the reason. monomial_basis(I) is absolutely not the way to go w.r.t. Oscar principles. But in particular in the context of germs and of ideal sheaves, you internally usually have an ideal in your hands and not a quotient ring when you find yourself in a setting to call monomial_basis.

To the remark with the quo: The lines here are not the key contribution of this PR. This is only the compatibility change, which currently does not touch the old code (as I do not know whether we are allowed to change this). The new contribution is in the local case (other file below) and there the quo is not computed, but monomial_basis(R,I) is the inner worker, whereas monomial_basis(quo...) is the outside appearance.
By the way, I would like to change the non-local case in the same way, if we are allowed to.

Mathematically I think this is about finding a monomial basis of a complement of I in R. So an alternatively would be to do something like this:
And then one could go a step further and move most of the body of the monomial_basis(A::MPolyQuoRing) method in here, as it only uses I, not the quotient ring?

NO, we are not looking at the complement. We are looking at the number of elements(=classes mod I) of the factorring R/I. I could live with monomial_basis_of_quo(I), but how do you type-dispatch on the type of the localization of R with this notation?

Copy link
Collaborator

Choose a reason for hiding this comment

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

By the way: quo(R,I) also contains the R, even though it is not necessary. We simply tried to stay in tune with quo (thinking that it would certainly follow OSCAR's principles).

Copy link
Collaborator

@thofma thofma Oct 30, 2024

Choose a reason for hiding this comment

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

Since this is not returning a basis of $R/I$, but a lifted basis of $R/I$ to $R$, it is in fact a basis for the complement of $I$, complement as a $K$-subspace of $R$.

Copy link
Collaborator

Choose a reason for hiding this comment

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

@wdecker: nobody wants to get rid of monomial_basis(A)! This is the way the average user should use it!

It is just a question of having a more internal, but documented variant for specialists (e.g. scripting, programming), which avoids creating the quo specifically to call monomial_basis which in turn immediately passes back to the modulus. This change is not done here yet. It is only done in the local case below. (But I would like to do it here as well.)

Copy link
Collaborator

Choose a reason for hiding this comment

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

If you document it, the user will find it. If it is internal, you may also put an _ in front. Also, you compute the quo anyway. So what do you gain?. Typing monomial_basis(R, I) instead of monomial_basis(quo(R, I)[1])? But, if it is important to you, I will not stand in your way.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I see this as an ok to put the work into the internal monomial_basis(R,I) and let the outside one monomial_basis(A) call it, like in the local case.

return monomial_basis(quo(R,I)[1])
end

@doc raw"""
monomial_basis(A::MPolyQuoRing, g::FinGenAbGroupElem)

Expand Down
50 changes: 50 additions & 0 deletions src/Rings/mpolyquo-localizations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1850,6 +1850,56 @@ function vector_space_dimension(R::MPolyQuoLocRing{<:Field, <:Any,<:Any, <:Any,
return vector_space_dimension(quo(base_ring(R),ideal(base_ring(R),gens(LI)))[1])
end

@doc raw"""
monomial_basis(A::MPolyQuoLocRing{<:Field, <:Any, <:Any, <:Any, <:MPolyComplementOfKPointIdeal})
monomial_basis(L::MPolyLocRing{<:Field, <:Any, <:Any, <:Any, <:MPolyComplementOfKPointIdeal}, I::MPolyLocalizedIdeal)

If, say, `A = L/I`, where `L` is a localization of multivariate polynomial ring over a field
`K` at a point `p`, and `I` is an ideal of `L`, return a vector of monomials of `L`
such that the residue classes of these monomials form a basis of `A` as a `K`-vector
space.
!!! note
The monomials are for readabilty in the varibles of the underlying polynomial ring of `L` and not in the variables of power series ring $K[[x_1-p_1,...,x_n-p_n]]$ in which `L` is embedded.
!!! note
If `A` is not finite-dimensional as a `K`-vector space, an error is thrown.
# Examples
```jldoctest
julia> R, (x,y) = QQ["x","y"];

julia> L,_ = localization(R, complement_of_point_ideal(R, [1,1]));

julia> A,_ = quo(L, ideal(L, [(x-1)^2, (y-1)^2]));

julia> A
Localization
of quotient
of multivariate polynomial ring in 2 variables x, y
over rational field
by ideal (x^2 - 2*x + 1, y^2 - 2*y + 1)
at complement of maximal ideal of point (1, 1)

julia> monomial_basis(A)
4-element Vector{Oscar.MPolyLocRingElem{QQField, QQFieldElem, QQMPolyRing, QQMPolyRingElem, Oscar.MPolyComplementOfKPointIdeal{QQField, QQFieldElem, QQMPolyRing, QQMPolyRingElem}}}:
x*y
y
x
1
```
"""
function monomial_basis(L::MPolyLocRing{<:Field, <:Any, <:Any, <:Any, <:MPolyComplementOfKPointIdeal}, I::MPolyLocalizedIdeal)
base_ring(I) == L || error("ideal does not belong to the correct ring")
Comment on lines +1889 to +1890
Copy link
Member

Choose a reason for hiding this comment

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

Same question as above: why not

Suggested change
function monomial_basis(L::MPolyLocRing{<:Field, <:Any, <:Any, <:Any, <:MPolyComplementOfKPointIdeal}, I::MPolyLocalizedIdeal)
base_ring(I) == L || error("ideal does not belong to the correct ring")
function monomial_basis(I::MPolyLocalizedIdeal)
L = base_ring(I)

(though perhaps with a different name)

Copy link
Collaborator

Choose a reason for hiding this comment

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

See my remark above.

Copy link
Collaborator

Choose a reason for hiding this comment

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

This is not about the name, but about the type dispatch for the localization of the ring.

Copy link
Collaborator

@thofma thofma Oct 30, 2024

Choose a reason for hiding this comment

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

The type of the ring is the first parameter of the ideal, so it would be

blabla(I::MPolyLocalizedIdeal{MPolyLocRing{<:Field, <:Any, <:Any, <:Any, <:MPolyComplementOfKPointIdeal}})

G = numerator.(gens(I))
shift,_ = base_ring_shifts(L)
G_0 = shift.(G)
R = base_ring(L)
LI = leading_ideal(ideal(R, G_0), ordering = negdeglex(R))
return L.(monomial_basis(R, LI))
end

function monomial_basis(A::MPolyQuoLocRing{<:Field, <:Any, <:Any, <:Any, <:MPolyComplementOfKPointIdeal})
return monomial_basis(localized_ring(A), modulus(A))
end

function is_finite_dimensional_vector_space(R::MPolyQuoLocRing)
throw(NotImplementedError(:is_finite_dimensional_vector_space, R))
end
Expand Down
3 changes: 3 additions & 0 deletions test/Rings/mpoly-affine-algebras.jl
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ end

A, _ = quo(R, ideal(R, [one(R)]))
@test isempty(monomial_basis(A))

@test monomial_basis(R, ideal(R, [x, y^2])) == [y, 1]
@test_throws InfiniteDimensionError() monomial_basis(R, ideal(R, x*y))
end

@testset "Subalgebra membership" begin
Expand Down
17 changes: 17 additions & 0 deletions test/Rings/mpolyquo-localizations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -510,3 +510,20 @@ end
@test Oscar._get_generators_string_one_line(ideal(R, x)) == "with 100 generators"
@test Oscar._get_generators_string_one_line(ideal(R, [sum(x)])) == "with 1 generator"
end

@testset "monomial_basis MPolyQuoLocRing" begin
R, (x,y) = QQ["x", "y"]
L, _ = localization(R, complement_of_point_ideal(R, [0,0]))
Q1, _ = quo(L, ideal(L, L(x+1)))
@test isempty(monomial_basis(Q1))
Q2, _ = quo(L, ideal(L, L(x^2)))
@test_throws InfiniteDimensionError() monomial_basis(Q2)
Q3, _ = quo(L, ideal(L, L.([x^2, y^3])))
@test monomial_basis(Q3) == L.([x*y^2, y^2, x*y, y, x, 1])
Q4,_ = quo(L, ideal(L, [x^2-x, y^2-2*y]))
@test monomial_basis(Q4) == [L(1)] #test for difference in localized and non-localized case
@test monomial_basis(L, ideal(L, [x^3*(x-1), y*(y-1)*(y-2)])) == L.([x^2, x, 1])
L1, _ = localization(R, complement_of_point_ideal(R, [1,2]))
@test monomial_basis(L1, ideal(L1, [(x-1)^2, (y-2)^2])) == L1.([x*y, y, x, 1])
@test isempty(monomial_basis(L1, ideal(L1, L1.([x, y]))))
end
Loading