Closed xcaruso closed 3 years ago
Branch: u/caruso/relaxed
Description changed:
---
+++
@@ -95,13 +95,14 @@
(this is due to the factor `5`).
As a comparison, the following produces an error::
+
sage: y = R()
sage: y == 1 + 3*y^2
Traceback (most recent call last):
...
RecursionError: definition looks circular
-Previous self-referrent definitions also work with system of equations::
+Previous self-referent definitions also work with system of equations::
sage: u = R(); v = R(); w = R()
Branch pushed to git repo; I updated commit sha1. New commits:
1fb0d59 | rough implementation of square roots |
Branch pushed to git repo; I updated commit sha1. New commits:
b69ba5a | method selfref |
Description changed:
---
+++
@@ -1,4 +1,4 @@
-We propose an implement of lazy p-adic numbers relaying on relaxed arithmetics proposed by van der Hoeven and al.
+We propose an implementation of lazy p-adic numbers relaying on relaxed arithmetics proposed by van der Hoeven and al.
Here is a small demo:
@@ -104,7 +104,9 @@
Previous self-referent definitions also work with system of equations::
- sage: u = R(); v = R(); w = R()
+ sage: u = R.selfref()
+ sage: v = R.selfref()
+ sage: w = R.selfref()
sage: u == 1 + 2*v + 3*w^2 + 5*u*v*w
True
Branch pushed to git repo; I updated commit sha1. New commits:
4044cad | rewrite in cython+flint (not finished) |
Branch pushed to git repo; I updated commit sha1. New commits:
707287b | c helper file |
Branch pushed to git repo; I updated commit sha1. New commits:
b130f14 | fix bugs in element_constructor |
Branch pushed to git repo; I updated commit sha1. New commits:
4f2f8e6 | explicit error codes |
Branch pushed to git repo; I updated commit sha1. New commits:
e23dccf | better with files added |
Description changed:
---
+++
@@ -5,9 +5,9 @@
This module provides basic support for lazy p-adic integers.
5-adic Ring with lazy precision
One creates elements as usual::
@@ -18,20 +18,17 @@ sage: R.random_element() # random ...21013213133412431402
-Alternatively, one can increase the precision using the method meth:jump
::
+By default, 20 digits of precision are printed.
+If more digits are needed, one can increase the precision by using the
+meth:jump
::
sage: a.jump(30) sage: a ...244200244200244200244200244201
Standard operations are implemented::
sage: b = R(42/17)
sage: a + b ...03232011214322140002 @@ -43,8 +40,18 @@ sage: a / b ...12442142113021233401
-We observe again that only 20 digits are computed. -If we need more, we have to create a new variable:: +We observe again that only 20 digits are printed, even if the precision +on the operands is higher:: +
+If more digits are needed, we have to create a new variable::
sage: c = a / b sage: c.jump(40) @@ -58,27 +65,15 @@ sage: b ...2134024323104201213402432310420121340301
sage: c == R(289/1764, prec=100)
True
sage: c == R(289/1764 + 5^50, prec=100)
True
sage: c.jump(100)
sage: c == R(289/1764 + 5^50, prec=100)
False
sage: c == R(289/1764 + 5^50)
True +::
A quite interesting feature with lazy p-adics is the possibility to -create (in somes cases) self-referrent numbers. Here is an example. +create (in somes cases) self-referent numbers. Here is an example. We first declare a new variable as follows::
sage: x = R()
sage: x = R.selfref() sage: x
O(1)
...?.0
We then write down an equation satisfied by x
::
@@ -96,13 +91,13 @@
As a comparison, the following produces an error::
-Previous self-referent definitions also work with system of equations:: +Self-referent definitions also work with systems of equations::
sage: u = R.selfref()
sage: v = R.selfref()
@@ -110,15 +105,15 @@
sage: u == 1 + 2*v + 3*w^2 + 5*u*v*w
True
sage: v == 2 + 4w + sqrt(1 + 5u + 10v + 15w) True sage: w == 3 + 25(uv + vw + uw) True
sage: u
Branch pushed to git repo; I updated commit sha1. New commits:
202e160 | square roots when p=2 |
Branch pushed to git repo; I updated commit sha1. New commits:
1799646 | write templates |
Branch pushed to git repo; I updated commit sha1. New commits:
56001b4 | slices |
4818fef | init jump |
30d36da | bounded and unbounded elements |
b692710 | replace jump_* by at_precision_* |
6ea0a8c | change behaviour of `_repr_`, precision_absolute and precision_absolute |
bca6f7b | do not jump at initialization for unbounded elements |
2f51842 | fix some bugs |
Description changed:
---
+++
@@ -3,11 +3,27 @@
Here is a small demo:
-This module provides basic support for lazy p-adic integers.
+The model for lazy elements is quite different from any of the
+other types of p
-adics. In addition to storing a finite
+approximation, one also stores a method for increasing the
+precision.
+
+Lazy p-adic rings are created by the constructor :func:ZpL
::
sage: R = ZpL(5, print_mode="digits")
sage: R
5-adic Ring with lazy precision
+
+Observe that the precision is not capped on R
::
+
+However, a default precision is settled. This is the precision +at which the element will be printed::
20
One creates elements as usual::
@@ -18,52 +34,79 @@ sage: R.random_element() # random ...21013213133412431402
-By default, 20 digits of precision are printed.
-If more digits are needed, one can increase the precision by using the
-meth:jump
::
+Here we notice that 20 digits (that is the default precision) are printed.
+However, the computation model is designed in order to guarantee that more
+digits of a
are available on demand.
+This feature is reflected by the fact that, when we ask for the precision
+of a
, the software answers \infty
::
-Standard operations are implemented::
+Asking for more digits is achieved by the methods :meth:at_precision_absolute
+and :meth:at_precision_relative
::
+
+As a shortcut, one can use the operator @
::
+Of course, standard operations are supported::
sage: b = R(42/17)
sage: a + b ...03232011214322140002 sage: a - b ...42311334324023403400
sage: a * b ...00000000000000000001 sage: a / b ...12442142113021233401
-We observe again that only 20 digits are printed, even if the precision -on the operands is higher:: +We observe again that only 20 digits are printed but, as before, +more digits are available on demand::
-If more digits are needed, we have to create a new variable:: +Checking equalities between lazy p-adics is a bit subtle can could +sometimes be puzzling at first glance. +Actually, when it is obvious (from the previous computations) that +the two sides of the equality are different, everything works well::
-Note that this automatically increases the precision on a
and b
::
+On the contrary, when the two numbers we want to compare are indeed
+equal, it is not possible to conclude after a finite amount of
+computations. In this case, an error is raised::
+and we are forced to check equality at some given finite precision +as follows::
+Finally, note that checking equality may fail even when the two +operands are different but when the first different digit is beyond +the default precision::
PrecisionError: unable to decide equality; try to bound precision
::
@@ -75,12 +118,13 @@ sage: x ...?.0
-We then write down an equation satisfied by x
::
+We then use the method :meth:set
to define x
by writing down an equation
+it satisfies::
-The variable x
now contains the unique solution of the above equation::
+The variable x
now contains the unique solution of the equation
+x = 1 + 5 x^2
::
sage: x
...04222412141121000211
@@ -89,10 +133,13 @@
defining equation only involves the i
-th digits of x
with i < n
(this is due to the factor 5
).
-As a comparison, the following produces an error:: +As a comparison, the following does not work::
sage: y = R.selfref()
sage: y == 1 + 3*y^2
sage: y.set(1 + 3*y^2)
sage: y
...?.0
sage: y@20 Traceback (most recent call last): ... RecursionError: definition looks circular @@ -103,12 +150,9 @@ sage: v = R.selfref() sage: w = R.selfref()
sage: u == 1 + 2v + 3w^2 + 5uv*w
True
sage: v == 2 + 4w + sqrt(1 + 5u + 10v + 15w)
True
sage: w == 3 + 25(uv + vw + uw)
True
sage: u.set(1 + 2v + 3w^2 + 5uv*w)
sage: v.set(2 + 4w + sqrt(1 + 5u + 10v + 15w))
sage: w.set(3 + 25(uv + vw + uw))
sage: u ...31203130103131131433
A note about operator choice: While the @
notation is definite informative and cute when considered stand-alone, it doesn't fit very well with other places where the operator is used in python. Specifically, the operator was introduced upon request of the numpy people, to signify matrix multiplication. With that in mind @
has a rather strong association with (function) composition (which, in a specific way, is also how you could read @
decorators to function definitions).
There's a reasonable chance that @
will at some point be integrated in the coercion framework. The use for @
proposed here will cause problems. I'd suggest just using a named method to cap precision.
Otherwise, this package looks really cool! It would be great to see some performance specs at some point.
I'm a bit disappointed but I note your argument for @
and will probably disallow this construction.
About performances, it's of course not as fast as other types of p-adics but I would say that it's already reasonable (although optimizations are still possible):
sage: R = ZpL(5)
sage: a = R.random_element()
sage: b = R.random_element()
sage: c = 1 + 5*R.random_element()
sage: %timeit _ = (a + b)@10000
848 µs ± 614 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)
sage: %timeit _ = (a * b)@10000
9.59 ms ± 116 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
sage: %timeit _ = (a / b)@10000
11.7 ms ± 215 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
sage: %timeit _ = c.sqrt()@10000
13.7 ms ± 240 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Compare with:
sage: R = Zp(5, prec=10000)
sage: a = R.random_element()
sage: b = R.random_element()
sage: c = 1 + 5*R.random_element()
sage: %timeit _ = a + b
1.21 µs ± 9.2 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
sage: %timeit _ = a * b
87.8 µs ± 130 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
sage: %timeit _ = a / b
667 µs ± 4.08 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
sage: %timeit _ = c.sqrt()
27.4 ms ± 125 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
EDIT: use %timeit
instead of %time
Maybe some comments on the timings. The "bad" performances of lazy p-adic come from two different sources:
Although I cannot do much to get rid of the first problem, I can certainly do something for the second one: instead of working with digits, I can work with blocks of digits (limbs) of the correct size. Actually, I want to do this but this requires many changes in my current code and I planned to delay this for another ticket.
In any case, when p becomes larger, the differences of performances between lazy p-adics and classical p-adics tend to get smaller.
sage: p = next_prime(2^63)
sage: R = ZpL(p)
sage: a = R.random_element()
sage: b = R.random_element()
sage: c = 1 + p*R.random_element()
sage: %timeit _ = (a + b)@10000
3.51 ms ± 407 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
sage: %timeit _ = (a * b)@10000
73.7 ms ± 189 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
sage: %timeit _ = (a / b)@10000
83.4 ms ± 471 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
sage: %timeit _ = c.sqrt()@10000
160 ms ± 3.31 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
and:
sage: p = next_prime(2^63)
sage: R = Zp(p, prec=10000)
sage: a = R.random_element()
sage: b = R.random_element()
sage: c = 1 + p*R.random_element()
sage: %timeit _ = a + b
86.4 µs ± 578 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
sage: %timeit _ = a * b
9.04 ms ± 63.9 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
sage: %timeit _ = a / b
78.8 ms ± 415 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
sage: %timeit _ = c.sqrt()
672 ms ± 1.23 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Branch pushed to git repo; I updated commit sha1. New commits:
72f2f70 | documentation in linkage files |
a632ec9 | move tutorial to the documentation of ZpL |
3199f73 | printer is always defined |
5aa0af9 | try to accelerate addition and subtraction |
baeeb10 | documentation in generic_nodes |
5316bee | fix doctest |
7fc3fb3 | make TestSuite pass (except pickling) |
We propose an implementation of exact p-adic numbers relaying on relaxed arithmetics proposed by van der Hoeven and al.
Here is a small demo:
CC: @sagetrac-TristanVaccon @ThibautVerron @roed314 @saraedum
Component: padics
Author: Xavier Caruso
Branch:
ad06299
Reviewer: David Roe
Issue created by migration from https://trac.sagemath.org/ticket/31108