-
-
Notifications
You must be signed in to change notification settings - Fork 510
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
Implement QQ['x'] via Flint ZZ['x'] + denominator #4000
Comments
Author: Martin Albrecht |
comment:2
The attached patch provides the basic skeleton for the proposed new implementation. The following already works with the attached patch: sage: from sage.rings.polynomial.polynomial_rational_flint import Polynomial_rational_dense_flint
sage: P.<t> = QQ[]
sage: a = Polynomial_rational_dense_flint(P,1/2)
sage: b = Polynomial_rational_dense_flint(P,2/1)
sage: t = Polynomial_rational_dense_flint(P,is_gen=True)
sage: a*t
1/2*t
sage: a*t*b
t
sage: a*t*b*b
2*t
sage: a*t*b*(b*t)
2*t^2
sage: a*t*b*(b*t)*a
t^2 |
comment:3
I've now implemented most methods in the prototype from the previous patch uploaded, and sent a message to sage-devel under the thread "Improving QQ['x']" with some questions. Sebastian |
comment:4
Some remarks
|
comment:5
Hi Martin, I've now implemented all methods in the prototype. (I'll attach a new patch in a few minutes.) All of your above comments make sense and I can go through this tomorrow. One thing I could not get done is make SAGE use this implementation by default. In the file polynomial_ring.py, I tried replacing the line 1185 with
and while building still works, executing ./sage results in a whole screen full output, ending with
Am I making a mistake in the way I am trying to switch the default, or does this due to problems in the actual new implementation? I've got no idea how to fix this. Of course, I am then happy to do lots of testing. Kind regards, Sebastian |
comment:6
I can take a look tomorrow to debug this. |
comment:7
I fixed the startup crash. I suggest you take a look at sage: P.<x> = QQ[]
sage: f = P.random_element(2000)
sage: g = P.random_element(2000)
sage: %time _ = f*g
CPU times: user 0.01 s, sys: 0.00 s, total: 0.01 s
Wall time: 0.02 s sage: P.<x> = PolynomialRing(QQ,'x',implementation='pari')
sage: f = P.random_element(2000)
sage: g = P.random_element(2000)
sage: %time _ = f*g
CPU times: user 0.59 s, sys: 0.00 s, total: 0.59 s
Wall time: 0.59 s sage: P.<x> = QQ[]
sage: f = P.random_element(5000)
sage: g = P.random_element(5000)
sage: %time _ = f*g
CPU times: user 0.03 s, sys: 0.00 s, total: 0.03 s
Wall time: 0.04 s sage: fM = magma(f)
sage: gM = magma(g)
sage: t = magma.cputime()
sage: _ = fM*gM
sage: magma.cputime(t)
0.12 |
comment:8
Thanks for the quick debugging and making the code accessible in SAGE for testing! I'll upload a new version of the patch later. Here are a few (unsorted) remarks:
Here is a complete (except for XGCD) list of performance comparisons, using the local installation of SAGE 4.1.2.alpha0 plus this patch on my laptop (Ubuntu 8.10, Intel Core 2 Duo). The first few tests, from comparison through to power, involve random polynomials f and g of degrees 2000, the division tests use random polynomials f and d of degrees 800 and 560, and for the GCD test f and d have degree 60 and 42. In each case, the first output line is for the generic implementation, the second output line is for the new implementation using FLINT.
Sebastian |
comment:9
Replying to @sagetrac-spancratz:
Try running Sage with
We should think about how to make it more efficient, e.g. by only multiplying by the multiplier to get the LCM? Magma can do it faster than what we can do it seems.
You are right, the overflow I was expecting doesn't happen (I think this is handled correctly in the base ring). We should consider making
You wrote e.g.
This is encouraging! |
comment:10
Also, I think our design for |
comment:11
Actually, I am not quite sure about this. When working with a random polynomial of degree 2000, which will have lots of non-zero entries all of type fmpz_t, it shouldn't really matter whether we manually initialise a few more for the denominators. I've tried implementing the denominator with the convention that it is either Another idea, which will sometimes help to keep numbers small, is to instead represented the polynomial over the rationals as This still leaves the problem: How can we speed up addition? At the moment, I don't have any further ideas. In fact, I think it might perhaps be the case that we simply can't, since in this kind of implementation we have to at least do a few polynomial scalar multiplications (and perhaps polynomial scalar divisions as well as integer gcd computations to maintain the form of the representation) plus all the coefficient additions. In contrast to this, implementing polynomials as an array of coefficients one only has to do the (rational!) coefficient additions. So the next things I'll do are
Does anyone have any ideas about the addition? Sebastian |
comment:12
Replying to @sagetrac-spancratz:
We shouldn't forget about small polynomials, they should be fast too. Two instead of one system call sounds rather expensive to me for basic arithmetic.
Did you try small examples? Also, how much does the realloc trick you implemented give you?
Did you try the LCM idea? Rationale: sage: P.<x> = QQ[]
sage: f = P.random_element(3000)
sage: g = P.random_element(3000)
sage: fD = f.denominator()
sage: gD = g.denominator()
sage: (fD*gD).nbits()
320
sage: (fD.lcm(gD)).nbits()
228
Well, this other implementation would have to do quite a few rational additions where it would have to deal with denominators quite a bit. I am not convinced yet it has to be this slow. You could also ask on [sage-devel] I am sure, e.g. Bill Hart (main author of FLINT) would have some cool ideas. |
comment:13
I am sorry for the delay in working on this. Rather than trying the approach of writing the polynomial as Hopefully I'll be able to upload something useful tomorrow. Sebastian |
comment:14
The switch to include NULL denominators still isn't quite done. However, I think addition and multiplication are bug-free already and show another massive improvement in speed. There are definitely still bugs in the division method, and the modular exponentiation as well as the gcd methods aren't implemented yet. I should be able to look into this tomorrow. Sebastian |
comment:15
I can't test the most current patch (on geom.math): sage: P.<x> = PolynomialRing(QQ)
sage: f = P.random_element(2000)
...
__celement_den_fit_limbs
Error: division by zero!
/scratch/malb/sage-4.1.2.alpha1/local/bin/sage-sage: line 199: 12195 Aborted sage-ipython "$@" -i |
comment:16
Hi Martin, I am sorry for that. Last night and this morning I fixed another couple of bugs. In a few minutes, I'll upload a new patch (or rather, again the difference from the 20090911 patch). By the way, for debugging purposes all methods in the linkage file now begin with printing the method's name (although in all but the floordiv method, that line begins with '#'). Random (performance!, not correctness...) tests ran fine last night for polynomials of degree 2000 for the methods ==, <, +, -, neg, *, ^. I thought the three division methods should work fine now, until I stumbled across the following segfault:
This strikes me as very odd because the segfault seems to occur in the call I haven't looked at the two gcd methods yet, but I'll do that later today or tomorrow. As the last question about the implementation (for this method), I noticed that polynomials over QQ in SAGE have the method Finally, here are the performance timings, in each case for ten random polynomials of degree 2000, first the time for the generic implementation and then the time for this implementation with FLINT:
Kind regards, Sebastian |
comment:17
Hi Martin, I just started to look at the gcd methods again and I also looked at the logic in polynomial_template.pxi. Here's the question: Since the gcd of two polynomials is only defined up to multiplication by rationals, what's the right way of dealing with this? I think one can make a good argument for always returning the same normalisation. This would also mean that we do not necessarily have gcd(a,0) == a. This is currently the way it's handled in the file polynomial_template.pxi. If we want to normalise the gcd, in which way should this be done? If it's non-zero..
Of course, there are lots more but I think these two might be the most sensible choices. The first one has the advantage that it generalises to all polynomial rings (over commutative rings with 1, at least). Upon adding a method returning the monic scalar multiple of a polynomial to the template file, one can still handle the cases of gcd(a,0) and gcd(0,b) in the template file. Personally though, I am more in favour of the second option, since this might lead to faster code when working with QQ[]. In this case, we should remove the handling of the above two cases from the template file and always pass the call on to celement_gcd. This would mean that we leave the normalisation up to the actual implementation of the polynomial ring, rather than enforcing it across all base rings using the template file. We would then also have to make sure that all celement_gcd methods are happy to deal with zero arguments. What do you think? Sebastian |
comment:18
Replying to @sagetrac-spancratz:
I will (hopefully) take a look later this week.
You would add a method
If I understand this correctly, then addition is 20x faster than the previous implementation just because you avoid a remalloc? |
comment:19
Replying to @sagetrac-spancratz:
I think we should have
This might be worth raising on [sage-devel] where people care much more about this than I do, i.e. I guess it is a relevant corner case for number theory and thus people might have strong feelings about it? |
comment:20
OK, I'll do that.
Yes. Actually, throughout I am now trying very hard to re-use variables rather than allocating new variables all over the place. It makes the code quite ugly... but definitely faster, which this is about, right? :) |
comment:21
Replying to @malb:
I didn't mean the above for rational numbers
In the above case, the monic version would be
OK, I'll do this. Sebastian |
comment:22
I have now opened another ticket, #6941, to change the template implementation, pushing all the logic into the Martin, would you be happy to review that patch? Sebastian |
comment:23
I've now implemented almost all functionality from the former generic implementation, most of it massively improved through FLINT. There are also some new methods. All of this is in the patch I uploaded just now, still as a difference to the 20090911 patch. Running make test still results in many failures, although fewer than last week. Sebastian |
comment:24
Apart from a bad indentation in
All but one of them are memory problems, either in Sebastian |
comment:25
Almost all of the memory problems are now resolved. They were arising because I wrongly assumed
The test in
The test in
I will try to chase down the first problem a little further than the Sebastian |
comment:120
I think this would be the appropriate way to handle this. Sebastian |
comment:121
Applying attachment: trac4000_0.patch to 4.6.alpha2, I get a failed "hunk": --- polynomial_ring.py
+++ polynomial_ring.py
@@ -1220,28 +1220,34 @@
sage: type(R.gen())
<class 'sage.rings.polynomial.polynomial_element_generic.Polynomial_generic_dense_field'>
"""
- if implementation is None: implementation="NTL"
from sage.rings.finite_rings.finite_field_base import is_FiniteField
+ from sage.rings.rational_field import QQ
+ from sage.rings.polynomial.polynomial_singular_interface import can_convert_to_singular
+ if implementation is None:
+ implementation = "NTL"
+
if implementation == "NTL" and is_FiniteField(base_ring):
- p=base_ring.characteristic()
from sage.libs.ntl.ntl_ZZ_pEContext import ntl_ZZ_pEContext
from sage.libs.ntl.ntl_ZZ_pX import ntl_ZZ_pX
+ from sage.rings.polynomial.polynomial_zz_pex import Polynomial_ZZ_pEX
+
+ p = base_ring.characteristic()
self._modulus = ntl_ZZ_pEContext(ntl_ZZ_pX(list(base_ring.polynomial()), p))
- from sage.rings.polynomial.polynomial_zz_pex import Polynomial_ZZ_pEX
- element_class=Polynomial_ZZ_pEX
+ element_class = Polynomial_ZZ_pEX
if not element_class:
if sparse:
element_class = polynomial_element_generic.Polynomial_generic_sparse_field
elif isinstance(base_ring, rational_field.RationalField):
- element_class = polynomial_element_generic.Polynomial_rational_dense
+ from sage.rings.polynomial.polynomial_rational_flint import Polynomial_rational_flint
+ element_class = Polynomial_rational_flint
elif is_RealField(base_ring):
element_class = PolynomialRealDense
else:
element_class = polynomial_element_generic.Polynomial_generic_dense_field
+
PolynomialRing_integral_domain.__init__(self, base_ring, name=name, sparse=sparse, element_class=element_class)
- from sage.rings.polynomial.polynomial_singular_interface import can_convert_to_singular
self._has_singular = can_convert_to_singular(self)
def divided_difference(self, points, full_table=False): Could someone who knows this code please rebase the patch? |
Main patch rebased against 4.6.alpha3 |
Attachment: trac4000_0.2.patch.gz Attachment: trac_4000-sunos_workaround.patch.gz Solaris work around |
comment:122
I've attached a rebased patch and a workaround for the Solaris GCC problem. The patches to apply are now:
|
Changed work issues from Solaris build error, doctest error to none |
comment:123
The tests pass with a trial 4.6.alpha3 (which is probably the same as alpha2 for this ticket) on sage.math, except for sage -t -long -force_lib "devel/sage/sage/rings/number_field/number_field_ideal.py"
**********************************************************************
File "/mnt/usb1/scratch/mpatel/apps/sage-4.6.a3/devel/sage/sage/rings/number_field/number_field_ideal.py", line 194:
sage: NumberField(x^2 + 1, 'a').ideal(7).__hash__()
Expected:
-9223372036854775779
Got:
-288230376151711715 On David Kirkby's OpenSolaris machine hawk, I get sage -t -long -force_lib "devel/sage/sage/rings/number_field/number_field_ideal.py"
**********************************************************************
File "/export/home/buildbot/build/sage/hawk-1/hawk_full/build/sage-4.6.alpha3/devel/sage/sage/rings/number_field/number_field_ideal.py", line 194:
sage: NumberField(x^2 + 1, 'a').ideal(7).__hash__()
Expected:
-2147483619
Got:
-67108835 I'm inclined to merge this into 4.6.alpha3. We can open a new ticket for the new error, unless it indicates a serious problem. I'd like to release 4.6.alpha3 in a day or so, so please let me know as soon as possible. |
Combined patch that replaces all of the others |
comment:124
Attachment: trac_4000-combined.patch.gz I've also attached a combined patch that replaces all of the others. |
comment:125
Replying to @qed777:
Personally, I think it would be best to fix it first. Otherwise it strikes me of this comment by Peter Jeremy. I am very concerned at this "release it now, we'll make it work later" mentality. If it is on the strict understanding it does not get into a release until fixed, then I'm OK with it. That is the purpose of alphas. But I thought the intension was to have a feature freeze after this alpha. Merging this could be dangerous thing to do. The ticket has been open two years - I would have thought those working on it would have had time to checked it! Dave |
comment:126
As a matter of interest, what is the rationale for making a ticket a blocker, when it has been open for two years? If we have lived without it for two years, I find the 'blocker' status a bit unnecessary. |
comment:127
On bsd.math, I get sage -t -long -force_lib devel/sage/sage/rings/number_field/number_field_ideal.py
**********************************************************************
File "/Users/buildbot/build/sage/bsd-1/bsd_full/build/sage-4.6.alpha3/devel/sage-main/sage/rings/number_field/number_field_ideal.py", line 194:
sage: NumberField(x^2 + 1, 'a').ideal(7).__hash__()
Expected:
-9223372036854775779
Got:
-288230376151711715 so it seems we can just update the example at line 194 in sage: NumberField(x^2 + 1, 'a').ideal(7).__hash__()
-9223372036854775779 # 64-bit
-2147483619 # 32-bit Is is OK? |
comment:128
For the record, here is a slightly longer quote of what Peter said: *I am very concerned at this "release it now, we'll make it work later" mentality. If Sage is going to be a viable alternative to the M's, it needs to be trustworthy - complaints of "feature X is missing" are easily rectified, claims of "Sage gave me wrong answers" can quickly turn into "you can't trust the output from Sage" and are far more difficult to refute. * |
Fix 32/64-bit number_field_ideal doctest. Apply only this patch. |
comment:129
Attachment: trac_4000-combined.2.patch.gz I made this ticket a 4.6 blocker three weeks ago. The most recent doctest error appeared because of a recent change, probably in 4.6.alpha2. Yes, I meant to say that I'd make the new ticket a 4.6 blocker. 4.6.alpha3 is not out yet and we are not yet in feature freeze. I've added V2 of the combined patch, which adjusts the This ticket still needs a final review, and if it's positively reviewed by the time #10097 is merged, I'll merge it into 4.6.alpha3. |
Changed author from Sebastian Pancratz, Martin Albrecht to Sebastian Pancratz, Martin Albrecht, William Stein, Jeroen Demeyer, Robert Beezer |
Changed reviewer from John Cremona, Martin Albrecht, Alex Ghitza, Harald Schilly to John Cremona, Martin Albrecht, Alex Ghitza, Harald Schilly, William Stein, Mitesh Patel |
Merged: sage-4.6.alpha3 |
comment:133
And there was much rejoicing. |
comment:134
For the record: There's a bug in See #11771 for details. (Unfortunately FLINT 2.2, which includes its own / a newer version of |
comment:135
Replying to @nexttime:
Patch is up there. It would be nice if one of the many reviewers here could review my patch there. He/she should IMHO also take a look at the sizes used in other memory (re)allocations / for other variables, in |
Changed author from Sebastian Pancratz, Martin Albrecht, William Stein, Jeroen Demeyer, Robert Beezer to Sebastian Pancratz, Martin Albrecht, William Stein, Jeroen Demeyer, Rob Beezer |
Bill Hart wrote on [sage-devel]:
"""
Almost everything over Q should probably be converted to a problem
over Z. I haven't seen any polynomial problems over Q which should not
be dealt with this way so far, but I suppose they may exist.
"""
Further justification:
CC: @burcin @sagetrac-drkirkby @sagetrac-spancratz @mwhansen @malb @jdemeyer @peterjeremy
Component: basic arithmetic
Author: Sebastian Pancratz, Martin Albrecht, William Stein, Jeroen Demeyer, Rob Beezer
Reviewer: John Cremona, Martin Albrecht, Alex Ghitza, Harald Schilly, William Stein, Mitesh Patel
Merged: sage-4.6.alpha3
Issue created by migration from https://trac.sagemath.org/ticket/4000
The text was updated successfully, but these errors were encountered: