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

Make Generic.Poly similar and zero steal parents if appropriate. #907

Merged
merged 4 commits into from
Jul 9, 2021

Conversation

wbhart
Copy link
Contributor

@wbhart wbhart commented Jun 21, 2021

Fixes #897

Note that there is a corresponding Nemo fix required for this to pass.

This is the most conservative fix I can come up with which fixes 897 and does what we all agree on.

If this is accepted I will do the same thing for power series.

The system is still inconsistent, but we all agree the current functionality is not useful. The principle here is:

  • If the polynomial being created would have lived in the exact same (AbstractAlgebra/Nemo) ring (if parents had been cached), then "zero" and "similar" steal the parent from the original polynomial rather than create a new one.

At least this fix is not inconsistent with matrices, given that parents are not stored in the objects anyway. We probably should use @rfourquet's parent comparison idea there instead.

I should point out that I actually don't see a way to have zero and similar return a polynomial with exactly the same parent as the one that is being copied in all cases. Yes, one could steal or deepcopy and modify the parent in other cases too, but then there is no way to know if the stolen parent actually matches the polynomial we are creating, as one has no idea how that original polynomial was constructed.

It's worse for power series, since one might want exactly the same kind of parent, just with a different max_precision or something like that. This problem already occurs for polynomials if you change the variable (not that either of these cases would have been compatible with the original polynomial in the first place).

The only thing you can guarantee is that if the original polynomial was created with an optimal parent for the current package, the new one will have the same parent if it is meant to be compatible with the original.

I believe the current code does at least do that.

@codecov
Copy link

codecov bot commented Jun 21, 2021

Codecov Report

Merging #907 (1033ee2) into master (e8e038c) will increase coverage by 0.02%.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #907      +/-   ##
==========================================
+ Coverage   82.34%   82.37%   +0.02%     
==========================================
  Files          86       86              
  Lines       20045    20047       +2     
==========================================
+ Hits        16506    16513       +7     
+ Misses       3539     3534       -5     
Impacted Files Coverage Δ
src/Poly.jl 91.52% <100.00%> (+0.50%) ⬆️
src/generic/Misc/Poly.jl 0.00% <0.00%> (-58.00%) ⬇️
src/RelSeries.jl 94.30% <0.00%> (-0.59%) ⬇️
src/generic/RelSeries.jl 96.44% <0.00%> (-0.51%) ⬇️
src/generic/LaurentSeries.jl 92.99% <0.00%> (-0.31%) ⬇️
src/Matrix.jl 91.45% <0.00%> (-0.16%) ⬇️
src/generic/MPoly.jl 94.17% <0.00%> (-0.04%) ⬇️
src/AbstractAlgebra.jl 38.98% <0.00%> (ø)
src/generic/SparsePoly.jl 27.16% <0.00%> (+0.17%) ⬆️
... and 1 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update e8e038c...1033ee2. Read the comment docs.

@wbhart
Copy link
Contributor Author

wbhart commented Jun 25, 2021

@fieker @thofma @tthsqe12 Can someone comment on whether this approach is acceptable. I will do the same for power series if so. No need to touch matrices as parents aren't stored in the objects there.

src/Poly.jl Outdated Show resolved Hide resolved
@thofma
Copy link
Member

thofma commented Jun 25, 2021

I am not in favor of the different parent comparisons. I still believe removing the cached argument from zero(p::PolyElem; cached) and just doing

zero(p::PolyElem) = zero(parent(p))

would have been easier (I proposed this in the other issue). Similar for similar(p::PolyElem; cached).

Edit: Probably this definition I suggest also has some drawbacks. I would like to hear your opinion on that.

@tthsqe12
Copy link
Contributor

tthsqe12 commented Jun 25, 2021

I don't see anything wrong with this, nor do I see anything wrong with

zero(p::PolyElem) = zero(parent(p))

How much pain is there going to be on the nemo side?

@wbhart
Copy link
Contributor Author

wbhart commented Jun 25, 2021

@thofma For zero I can understand your perspective, but I don't get what you mean for similar. Similar absolutely has to do what it currently does, and it was actually you that convinced us of that.

Consider for example a polynomial over a number field and you ask for a similar polynomial over ZZ. A number field poly is generic but a poly over ZZ is not, so similar can't return the same sort of polynomial.

There are also issues in Singular. For example consider a Singular polynomial ring over a Nemo ZZ. You definitely don't want to create an fmpz_mpoly when you call similar there. You want it to use a Singular polynomial type.

So similar has to be complicated.

I agree zero could work the way you said. I just followed what was done for matrices (i.e. call similar). I'd be happy to change both matrices and polynomials to work the same way, if that's what you want. But existing tests will fail.

The other issue that is very important is that the similar system has to be manageable. We spent really a lot of time coming up with a system that does not require n^2 different implementations of similar if there are n polynomial types (e.g. all the Flint and Singular polynomial types). A system which satisfies all these constraints is basically forced to do exactly what similar does right now.

The only way we could do better would be to implement polynomials and matrices over number fields in Antic C so that we don't have this issue of them being generic. Then we could have a much simpler similar system. But, well, you know that no one is encouraging such a project, so that's not going to happen.

zero could definitely still be changed though, assuming everyone agrees to the change. Similar is not used very much by the user, whereas zero may be, so it is probably worth getting right.

@wbhart
Copy link
Contributor Author

wbhart commented Jun 25, 2021

Just to clarify: I have no problem with zero(p) = zero(parent(p)), so long as that is how it works for matrices too! People need to be able to reason about the system, and inconsistency makes that impossible.

@wbhart
Copy link
Contributor Author

wbhart commented Jun 25, 2021

As I said, the zero function for matrices arose out of the fact that similar creates a matrix with undefined entries, for performance reasons. This wasn't considered convenient and so zero was born.

But as I've pointed out, people can call zero_matrix(base_ring(M), m, n) instead of zero(M, m, n) if they want a zero matrix. It's more typing, but I don't think that matters (apart from the fact that we may have to change some of our existing code to use zero_matrix instead of zero).

@wbhart
Copy link
Contributor Author

wbhart commented Jun 25, 2021

And if you are wondering why I can't make zero(M) call zero(parent(M)) and make zero(M, m, n) have the current behaviour, the answer is that I don't know how to implement the latter without calling similar (I actually looked into this, it's really difficult). Therefore zero for matrices would be completely inconsistent and hard to reason about if I did that.

@thofma
Copy link
Member

thofma commented Jun 28, 2021

Let's merge this here. We can add

similar(x::PolyElem; cached) = zero(parent(x))
zero(x::PolyElem; cached) = similar(x)

later if we want to avoid the (small) overhead introduced here.

I will probably remove the breaking label, since this is a bugfix in my opinion.

@thofma
Copy link
Member

thofma commented Jun 28, 2021

PS.: Before merging I suggest making those === changes.

@wbhart
Copy link
Contributor Author

wbhart commented Jun 28, 2021

Yeah it's only breaking without the Nemo patches.

I'll make the changes after lunch.

src/Poly.jl Outdated Show resolved Hide resolved
Co-authored-by: thofma <thofma@gmail.com>
@thofma
Copy link
Member

thofma commented Jun 28, 2021

Thanks. Just out of curiosity, why is this breaking without the Nemo patch? It seems that downstream tests are all passing.

@wbhart
Copy link
Contributor Author

wbhart commented Jun 28, 2021

Well I suppose no one is using it, but obviously only Nemo can create Nemo parents correctly.

@thofma thofma merged commit 5807f8f into Nemocas:master Jul 9, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

zero(f::PolyElem) is producing elements with the wrong parent
3 participants