Lattice precision for padics
for details see https://trac.sagemath.org/ticket/23505.

changed target branch from
trac/develop
todevelop
Toggle commit list 
unmarked as a Work In Progress
Toggle commit list 
changed title from WIP: T/23505/lattice precision to Lattice precision for padics
Toggle commit list 
changed the description
Toggle commit list 
2472 2472 """ 2473 2473 return not (self == other) 2474 2474 2475 _real_types = ['Interval','Ball','MPFR','RDF','RLF'] 2476 _dvr_types = [None, 'fixedmod','floatingpoint','cappedabs','cappedrel','lazy','latticecap','latticefloat'] 
Master
Are these used anywhere?


1181 1248 """ 1182 1249 return Qp(p, prec, 'floatingpoint', *args, **kwds) 1183 1250 1251 #def QpL(p, prec = DEFAULT_PREC, print_mode = None, halt = DEFAULT_HALT, names = None, print_pos = None, 
Master
Why this code?


1229 1324  ``p``  integer: the `p` in `\mathbb{Z}_p` 1230 1325 1231 1326  ``prec``  integer (default: ``20``) the precision cap of the 1232 ring. Except for the fixed modulus case, individual elements 1327 ring. In the lattice capped case, ``prec`` can either be a 
Master
"either"…or?


1389 typically the set of all elements within the same parent. 1390 1391 sage: R = ZpLC(17) 1392 sage: x = R(1,10); y = R(1,5) 1393 sage: R.precision() 1394 Precision lattice on 2 objects 1395 sage: R.precision().precision_lattice() 1396 [2015993900449 0] 1397 [ 0 1419857] 1398 1399 We refer to the documentation of the function :func:`ZpLC` for 1400 more information about this precision model. 1401 1402 :: 1403 1404 There are seven types of `p`adic rings: capped relative rings 
Master
Maybe write "many" by now, so we don't have to think about fixing this number every time?


95 99 else: 96 100 return False 97 101 98 def get_key_base(p, prec, type, print_mode, names, ram_name, print_pos, print_sep, print_alphabet, print_max_terms, show_prec, check, valid_non_lazy_types): 102 def get_key_base(p, prec, type, print_mode, names, ram_name, print_pos, print_sep, print_alphabet, print_max_terms, show_prec, check, valid_non_lazy_types, label=None, absprec=None, relprec=None): 
Master
I don't see
label
explained anywhere in this file. What is it about? 
Master
How common is the case of passing
absprec
/relprec
for lattice precision? I find these arguments quite confusing because they are just ignored by the other precision types even though they make sense for some. Wouldn't it be Ok to tell people to pass in a tuple if they want to set these two?


2343 2483 """ 2344 2484 return Zq(q, prec, 'floatingpoint', *args, **kwds) 2345 2485 2486 def ZpLC(p, prec=None, *args, **kwds): 2487 """ 2488 A shortcut function to create `p`adic rings with lattice precision 2489 with cap. 2490 2491 DEMONSTRATION: 
Master
I think
EXAMPLES
is fine here.


2506 2507 sage: y = x+x 2508 sage: y 2509 2 + O(3^10) 2510 sage: x + y 2511 3 + O(3^11) 2512 2513 The same works for the multiplication:: 2514 2515 sage: z = x^2 2516 sage: z 2517 1 + O(3^10) 2518 sage: x*z 2519 1 + O(3^11) 2520 2521 This comes more funny when we are working with elements given 
Master
Maybe "this can appear more surprising"


2343 2483 """ 2344 2484 return Zq(q, prec, 'floatingpoint', *args, **kwds) 2345 2485 2486 def ZpLC(p, prec=None, *args, **kwds): 2487 """ 2488 A shortcut function to create `p`adic rings with lattice precision 2489 with cap. 2490 2491 DEMONSTRATION: 2492 2493 Below is a small demo of the features by this model of precision:: 2494 2495 sage: R = ZpLC(3, print_mode='terse') 2496 sage: x = R(1,10) 
Master
I think it's Sage's standard to add a space after each comma. Please fix this in all the other places as well.


2343 2483 """ 2344 2484 return Zq(q, prec, 'floatingpoint', *args, **kwds) 2345 2485 2486 def ZpLC(p, prec=None, *args, **kwds): 2487 """ 
Master
I think you need
r"""
here for the backslash in the math below to work.


2609 16953 + O(2^15) 2610 sage: a,b,c,d = b,c,d,(b*d+c*c)/a; print(d) 2611 16637 + O(2^15) 2612 2613 sage: for _ in range(100): 2614 ....: a,b,c,d = b,c,d,(b*d+c*c)/a 2615 sage: a 2616 15519 + O(2^15) 2617 sage: b 2618 32042 + O(2^15) 2619 sage: c 2620 17769 + O(2^15) 2621 sage: d 2622 20949 + O(2^15) 2623 2624 BEHIND THE SCENE: 
2630 Concretely, this precision datum is an instance of the class 2631 :class:`sage.rings.padic.lattice_precision.PrecisionLattice`. 2632 It is attached to the parent and is created at the same time 2633 as the parent. 2634 (It is actually a bit more subtle because two different parents 2635 may share the same instance; this happens for instance for a 2636 `p`adic ring and its field of fractions.) 2637 2638 This precision datum is accessible through the method :meth:`precision`:: 2639 2640 sage: R = ZpLC(5, print_mode='terse') 2641 sage: prec = R.precision() 2642 sage: prec 2643 Precision lattice on 0 object 2644 2645 This instance knows about all elements of the parent, it is 
Master
parent. It is


2655 sage: z = R.random_element() 2656 sage: prec 2657 Precision lattice on 3 objects 2658 2659 The method :meth:`tracked_elements` provides the list of all 2660 tracked elements:: 2661 2662 sage: prec.tracked_elements() 2663 [3513 + O(5^10), 176 + O(5^5), ...] 2664 2665 Similarly, when a variable is collected by the garbage collector, 2666 the precision lattice is updated. Note however that the update 2667 might be delayed. We can force it with the method :meth:`del_elements`:: 2668 2669 sage: z = 0 2670 sage: prec 
Master
I think this is technically
random output
. You can't know when the garbage collector runs, can you?


2695 The matrix we get is no longer diagonal, meaning that some digits 2696 of precision are diffused among the two new elements `x` and `y`. 2697 They nevertheless show up when we compute for instance `x+y`:: 2698 2699 sage: x 2700 1516 + O(5^5) 2701 sage: y 2702 424 + O(5^5) 2703 sage: x+y 2704 17565 + O(5^11) 2705 2706 These diffused digits of precision (which are tracked but 2707 do not appear on the printing) allow to be always sharp on 2708 precision. 2709 2710 PERFORMANCES: 
Master
PERFORMANCE
. MaybeNOTE::
?


2698 2699 sage: x 2700 1516 + O(5^5) 2701 sage: y 2702 424 + O(5^5) 2703 sage: x+y 2704 17565 + O(5^11) 2705 2706 These diffused digits of precision (which are tracked but 2707 do not appear on the printing) allow to be always sharp on 2708 precision. 2709 2710 PERFORMANCES: 2711 2712 Each elementary operation requires significant manipulations 2713 on the lattice precision and then is costly. Precisely: 
Master
precision lattice
instead oflattice precision
? And maybetherefore
instead ofthen
?


2704 17565 + O(5^11) 2705 2706 These diffused digits of precision (which are tracked but 2707 do not appear on the printing) allow to be always sharp on 2708 precision. 2709 2710 PERFORMANCES: 2711 2712 Each elementary operation requires significant manipulations 2713 on the lattice precision and then is costly. Precisely: 2714 2715  The creation of a new element has a cost `O(n)` where `n` 2716 is the number of tracked elements. 2717 2718  The destruction of one element has a cost `O(m^2)` where 2719 `m` is the distance between the destroyed element and 
Master
Should it be clear at this point what the "distance" is?


2711 2712 Each elementary operation requires significant manipulations 2713 on the lattice precision and then is costly. Precisely: 2714 2715  The creation of a new element has a cost `O(n)` where `n` 2716 is the number of tracked elements. 2717 2718  The destruction of one element has a cost `O(m^2)` where 2719 `m` is the distance between the destroyed element and 2720 the last one. Fortunately, it seems that `m` tends to 2721 be small in general (the dynamics of the list of tracked 2722 elements is rather close to that of a stack). 2723 2724 It is nevertheless still possible to manipulate several 2725 hundred variables (e.g. square matrices of size 5 or 2726 polynomials of degree 20 are accessible). 
Master
The "are accessible" here is confusing imho. I'd drop these two words.


2713 on the lattice precision and then is costly. Precisely: 2714 2715  The creation of a new element has a cost `O(n)` where `n` 2716 is the number of tracked elements. 2717 2718  The destruction of one element has a cost `O(m^2)` where 2719 `m` is the distance between the destroyed element and 2720 the last one. Fortunately, it seems that `m` tends to 2721 be small in general (the dynamics of the list of tracked 2722 elements is rather close to that of a stack). 2723 2724 It is nevertheless still possible to manipulate several 2725 hundred variables (e.g. square matrices of size 5 or 2726 polynomials of degree 20 are accessible). 2727 2728 The class :class:`PrecisionLattice` provides several 
Master
Wouldn't it be better to split this section between
history()
andtimings()
and just reference these two methods instead?


2715  The creation of a new element has a cost `O(n)` where `n` 2716 is the number of tracked elements. 2717 2718  The destruction of one element has a cost `O(m^2)` where 2719 `m` is the distance between the destroyed element and 2720 the last one. Fortunately, it seems that `m` tends to 2721 be small in general (the dynamics of the list of tracked 2722 elements is rather close to that of a stack). 2723 2724 It is nevertheless still possible to manipulate several 2725 hundred variables (e.g. square matrices of size 5 or 2726 polynomials of degree 20 are accessible). 2727 2728 The class :class:`PrecisionLattice` provides several 2729 features for introspection (especially concerning timings). 2730 If enabled, it maintains an history of all actions and stores 
Master
a history
.


2343 2483 """ 2344 2484 return Zq(q, prec, 'floatingpoint', *args, **kwds) 2345 2485 2486 def ZpLC(p, prec=None, *args, **kwds): 2487 """ 2488 A shortcut function to create `p`adic rings with lattice precision 2489 with cap. 
Master
You should reference
Zp
for an explanation of the input parameters.


2343 2483 """ 2344 2484 return Zq(q, prec, 'floatingpoint', *args, **kwds) 2345 2485 2486 def ZpLC(p, prec=None, *args, **kwds): 2487 """ 2488 A shortcut function to create `p`adic rings with lattice precision 2489 with cap. 
Master
You should reference
Zp
for an explanation of the input parameters.


2781 {'add': 0.25049376487731934, 2782 'del': 0.11911273002624512, 2783 'mark': 0.0004909038543701172, 2784 'partial reduce': 0.0917658805847168} 2785 2786 """ 2787 return Zp(p, prec, 'latticecap', *args, **kwds) 2788 2789 def ZpLF(p, prec=None, *args, **kwds): 2790 """ 2791 A shortcut function to create `p`adic rings with precision 2792 tracked through automatic differentiation. 2793 Floating point `p`adic numbers are used for the computation 2794 of the differential (which is then not exact). 2795 2796 See documentation for ``Zp`` for a description of the input parameters. 
Master
func:Zp
?


2779 2780 sage: prec.timings() # somewhat random 2781 {'add': 0.25049376487731934, 2782 'del': 0.11911273002624512, 2783 'mark': 0.0004909038543701172, 2784 'partial reduce': 0.0917658805847168} 2785 2786 """ 2787 return Zp(p, prec, 'latticecap', *args, **kwds) 2788 2789 def ZpLF(p, prec=None, *args, **kwds): 2790 """ 2791 A shortcut function to create `p`adic rings with precision 2792 tracked through automatic differentiation. 2793 Floating point `p`adic numbers are used for the computation 2794 of the differential (which is then not exact). 
2794 of the differential (which is then not exact). 2795 2796 See documentation for ``Zp`` for a description of the input parameters. 2797 2798 EXAMPLES:: 2799 2800 sage: ZpLF(5, 40) 2801 5adic Ring with latticefloat precision 2802 2803 .. SEEALSO:: 2804 2805 :func:`ZpLC` 2806 """ 2807 return Zp(p, prec, 'latticefloat', *args, **kwds) 2808 2809 #def ZpL(p, prec = DEFAULT_PREC, print_mode = None, halt = DEFAULT_HALT, names = None, print_pos = None, 
Master


2770 0.000022s ooooooooooooooooooooooooooooo~~~~~~~~~~~~~~~~~~~~~~oooo~o~o 2771 0.014705s ooooooooooooooooooooooooooooooooooo 2772 0.001292s ooooooooooooooooooooooooooooooooooooo 2773 0.000002s ooooooooooooooooooooooooooooooooooo~o 2774 2775 The symbol `o` symbolized a tracked element. 2776 The symbol `~` means that the element is marked for deletion. 2777 2778 The global timings are also accessible as follows:: 2779 2780 sage: prec.timings() # somewhat random 2781 {'add': 0.25049376487731934, 2782 'del': 0.11911273002624512, 2783 'mark': 0.0004909038543701172, 2784 'partial reduce': 0.0917658805847168} 2785 
Master
See also
ZpLF
?


2343 2483 """ 2344 2484 return Zq(q, prec, 'floatingpoint', *args, **kwds) 2345 2485 2486 def ZpLC(p, prec=None, *args, **kwds): 2487 """ 2488 A shortcut function to create `p`adic rings with lattice precision 
Master
Is it clear what's the meaning of "with cap"?


src/sage/rings/padics/lattice_precision.py 0 → 100644
1 import _weakref as weakref 
Master
This file is lacking headers: http://doc.sagemath.org/html/en/developer/coding_basics.html#headingsofsagelibrarycodefiles


src/sage/rings/padics/lattice_precision.py 0 → 100644
1 import _weakref as weakref 2 from sage.misc.misc import walltime 3 4 from sage.structure.sage_object import SageObject 5 from sage.structure.unique_representation import UniqueRepresentation 6 7 from sage.rings.integer_ring import ZZ 8 from sage.rings.rational_field import QQ 9 from sage.rings.infinity import Infinity 10 11 from sage.rings.padics.precision_error import PrecisionError 12 13 14 # Global variables 15 16 DEFAULT_THRESOLD_DELETION = 50 
Master
Please explain comments explaining what these variables are about. Are they used in more than one place? Maybe they should be moved to the place where they are used then?


src/sage/rings/padics/lattice_precision.py 0 → 100644
12 13 14 # Global variables 15 16 DEFAULT_THRESOLD_DELETION = 50 17 STARTING_ADDITIONAL_PREC = 5 18 19 20 21 # Class pRational 22 ################# 23 24 class pRational: 25 """ 26 This class implements rational numbers as approximations 27 of `p`adic numbers. 
Master
I don't understand what this means. Could you write some more on what this class is about here?


src/sage/rings/padics/lattice_precision.py 0 → 100644
20 21 # Class pRational 22 ################# 23 24 class pRational: 25 """ 26 This class implements rational numbers as approximations 27 of `p`adic numbers. 28 29 Only for internal use. 30 """ 31 def __init__(self, p, x, exponent=0, valuation=None): 32 """ 33 Construct the element ``x * p^exponent`` 34 35 INPUT: 
Master
You can move the INPUT sections to the class, so they become visible when somebody tries to create an instance of this (which they shouldn't but anyway.)


src/sage/rings/padics/lattice_precision.py 0 → 100644
14 # Global variables 15 16 DEFAULT_THRESOLD_DELETION = 50 17 STARTING_ADDITIONAL_PREC = 5 18 19 20 21 # Class pRational 22 ################# 23 24 class pRational: 25 """ 26 This class implements rational numbers as approximations 27 of `p`adic numbers. 28 29 Only for internal use. 
Master
I think you need a doctest here.


src/sage/rings/padics/lattice_precision.py 0 → 100644
26 This class implements rational numbers as approximations 27 of `p`adic numbers. 28 29 Only for internal use. 30 """ 31 def __init__(self, p, x, exponent=0, valuation=None): 32 """ 33 Construct the element ``x * p^exponent`` 34 35 INPUT: 36 37  ``p``  a prime number 38 39  ``x``  a rational number 40 41  ``exponent``  a relative integer (default: 0) 
Master
What's a "relative" integer?


src/sage/rings/padics/lattice_precision.py 0 → 100644
31 def __init__(self, p, x, exponent=0, valuation=None): 32 """ 33 Construct the element ``x * p^exponent`` 34 35 INPUT: 36 37  ``p``  a prime number 38 39  ``x``  a rational number 40 41  ``exponent``  a relative integer (default: 0) 42 43  ``valuation``  an integer or None (default: ``None``), 44 the ``p``adic valuation of this element 45 46 If not ``None``, this method trusts the given value to the 
Master
I don't understand this comment. Probably we can do without it? Or maybe it should be next to a doctest that shows what the problem could be here?


src/sage/rings/padics/lattice_precision.py 0 → 100644
71 sage: from sage.rings.padics.lattice_precision import pRational 72 sage: pRational(2, 5, 2) # indirect doctest 73 2^2 * 5 74 """ 75 if self.exponent == 0: 76 return str(self.x) 77 else: 78 return "%s^%s * %s" % (self.p, self.exponent, self.x) 79 80 def reduce(self, prec): 81 """ 82 Return this element reduced modulo ``p^prec`` 83 84 INPUT: 85 86  ``prec``  a relative integer 
Master
What is a relative integer?


src/sage/rings/padics/lattice_precision.py 0 → 100644
18 19 20 21 # Class pRational 22 ################# 23 24 class pRational: 25 """ 26 This class implements rational numbers as approximations 27 of `p`adic numbers. 28 29 Only for internal use. 30 """ 31 def __init__(self, p, x, exponent=0, valuation=None): 32 """ 33 Construct the element ``x * p^exponent`` 
Master
I think all your sentences should end in a
.
, here and everywhere else. That seems to be the standard.


src/sage/rings/padics/lattice_precision.py 0 → 100644
61 self.x = x 62 self.exponent = exponent 63 self._valuation = valuation 64 65 def __repr__(self): 66 """ 67 Return a string representation of this element 68 69 TESTS:: 70 71 sage: from sage.rings.padics.lattice_precision import pRational 72 sage: pRational(2, 5, 2) # indirect doctest 73 2^2 * 5 74 """ 75 if self.exponent == 0: 76 return str(self.x) 
Master
Technically we should call
repr
instead ofstr
here?


src/sage/rings/padics/lattice_precision.py 0 → 100644
99 190 100 """ 101 if prec is Infinity: 102 return self 103 x = self.x 104 exp = self.exponent 105 if x.parent() is ZZ: 106 if prec > exp: 107 x = x % (self.p ** (precexp)) 108 else: 109 x = 0 110 elif x.parent() is QQ: 111 num = x.numerator() 112 denom = x.denominator() 113 valdenom = denom.valuation(self.p) 114 denom /= self.p ** valdenom 
Master
Maybe
//=
so that we get an element of ZZ?


src/sage/rings/padics/lattice_precision.py 0 → 100644
9 from sage.rings.infinity import Infinity 10 11 from sage.rings.padics.precision_error import PrecisionError 12 13 14 # Global variables 15 16 DEFAULT_THRESOLD_DELETION = 50 17 STARTING_ADDITIONAL_PREC = 5 18 19 20 21 # Class pRational 22 ################# 23 24 class pRational: 
Master
I know you only use these internally, but I think that this should be a regular Sage element with a parent and all the category foo.


src/sage/rings/padics/lattice_precision.py 0 → 100644
110 elif x.parent() is QQ: 111 num = x.numerator() 112 denom = x.denominator() 113 valdenom = denom.valuation(self.p) 114 denom /= self.p ** valdenom 115 exp = valdenom 116 modulo = self.p ** (prec  exp) 117 # probably we should use Newton iteration instead 118 # (but it is actually slower for now  Python implementation) 119 _, inv, _ = denom.xgcd(modulo) 120 x = (num*inv) % modulo 121 if self.x == 0: 122 val = Infinity 123 else: 124 val = self._valuation 125 return self.__class__(self.p, x, exp, valuation=val) 
Master
This should probably be
self.parent()(…)
but this element has no parent yet.


src/sage/rings/padics/lattice_precision.py 0 → 100644
101 if prec is Infinity: 102 return self 103 x = self.x 104 exp = self.exponent 105 if x.parent() is ZZ: 106 if prec > exp: 107 x = x % (self.p ** (precexp)) 108 else: 109 x = 0 110 elif x.parent() is QQ: 111 num = x.numerator() 112 denom = x.denominator() 113 valdenom = denom.valuation(self.p) 114 denom /= self.p ** valdenom 115 exp = valdenom 116 modulo = self.p ** (prec  exp) 
Master
Could
exp > prec
here?


src/sage/rings/padics/lattice_precision.py 0 → 100644
245 sexp = self.exponent 246 oexp = other.exponent 247 if self._valuation is None or other._valuation is None: 248 val = None 249 elif self._valuation < other._valuation: 250 val = self._valuation 251 elif self._valuation > other._valuation: 252 val = other._valuation 253 else: 254 val = None 255 if sexp < oexp: 256 return self.__class__(p, self.x + other.x * p**(oexpsexp), sexp, valuation=val) 257 else: 258 return self.__class__(p, self.x * p**(sexpoexp) + other.x, oexp, valuation=val) 259 260 def __sub__(self, other): 
Master
Do you really need the speed or could we just write
return self+(other)
?


src/sage/rings/padics/lattice_precision.py 0 → 100644
434 exp = sexp 435 else: 436 a = ZZ(self.x * (p ** (sexpoexp))) 437 b = ZZ(other.x) 438 exp = oexp 439 d, u, v = a.xgcd(b) 440 if self._valuation is None or other._valuation is None: 441 val = None 442 else: 443 val = min(self._valuation, other._valuation) 444 d = self.__class__(p, d, exp, valuation=val) 445 u = self.__class__(p, u) 446 v = self.__class__(p, v) 447 return d, u, v 448 449 def value(self): 
Master
If this were a proper element, then this could be a coercion to
QQ
?


src/sage/rings/padics/lattice_precision.py 0 → 100644
474 123456 475 sage: x.list(5) 476 [] 477 sage: x.list(20) 478 [1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0] 479 480 sage: y = pRational(2, 123/456); y 481 41/152 482 sage: y.list(10) 483 [1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1] 484 """ 485 if self.x not in ZZ: 486 self = self.reduce(prec) 487 val = self.valuation() 488 p = self.p 489 x = ZZ(self.x * p**(self.exponent  val)) 
Master
Does this work for
x=0
?


src/sage/rings/padics/lattice_precision.py 0 → 100644
476 [] 477 sage: x.list(20) 478 [1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0] 479 480 sage: y = pRational(2, 123/456); y 481 41/152 482 sage: y.list(10) 483 [1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1] 484 """ 485 if self.x not in ZZ: 486 self = self.reduce(prec) 487 val = self.valuation() 488 p = self.p 489 x = ZZ(self.x * p**(self.exponent  val)) 490 l = [ ]; i = val 491 while i < prec: 
Master
Why not
for i in range(val,prec)
?


src/sage/rings/padics/lattice_precision.py 0 → 100644
488 p = self.p 489 x = ZZ(self.x * p**(self.exponent  val)) 490 l = [ ]; i = val 491 while i < prec: 492 x, digit = x.quo_rem(p) 493 l.append(digit) 494 i += 1 495 return l 496 497 498 # Helper function 499 ################# 500 501 def list_of_padics(elements): 502 """ 503 Convert a list of padic composed elements (as polynomials, matrices) 
Master
"such as"?


src/sage/rings/padics/lattice_precision.py 0 → 100644
491 while i < prec: 492 x, digit = x.quo_rem(p) 493 l.append(digit) 494 i += 1 495 return l 496 497 498 # Helper function 499 ################# 500 501 def list_of_padics(elements): 502 """ 503 Convert a list of padic composed elements (as polynomials, matrices) 504 to a list of weak refererences of their padic coefficients. 505 506 This is an helper function for the methods :meth:`precision_lattice` 
Master
"This is a helper function for the method"?


src/sage/rings/padics/lattice_precision.py 0 → 100644
516 <weakref at 0x...; to 'pAdicLatticeCapElement' at 0x...>, 517 <weakref at 0x...; to 'pAdicLatticeCapElement' at 0x...>] 518 """ 519 from sage.rings.padics.padic_lattice_element import pAdicLatticeElement 520 if isinstance(elements, pAdicLatticeElement): 521 return [ weakref.ref(elements) ] 522 if not isinstance(elements, list): 523 elements = list(elements) 524 ans = [ ] 525 for x in elements: 526 ans += list_of_padics(x) 527 return ans 528 529 def format_history(tme, status, timings): 530 """ 531 Return a formated output for the history. 
src/sage/rings/padics/lattice_precision.py 0 → 100644
518 """ 519 from sage.rings.padics.padic_lattice_element import pAdicLatticeElement 520 if isinstance(elements, pAdicLatticeElement): 521 return [ weakref.ref(elements) ] 522 if not isinstance(elements, list): 523 elements = list(elements) 524 ans = [ ] 525 for x in elements: 526 ans += list_of_padics(x) 527 return ans 528 529 def format_history(tme, status, timings): 530 """ 531 Return a formated output for the history. 532 533 This is an helper function for the methods :meth:`history`. 
Master
"This is a helper function for the method"?


src/sage/rings/padics/lattice_precision.py 0 → 100644
563 564 565 class DifferentialPrecisionGeneric(UniqueRepresentation, SageObject): 566 """ 567 A generic class for precision objects obtained by automatic 568 differentiation 569 """ 570 def __init__(self, p, type, label): 571 """ 572 Initialize this precision module 573 574 INPUT: 575 576  ``p``  a prime number 577 578  ``type``  either ``lattice`` or ``module`` 
Master
I think this should be:
either ``"lattice"`` or ``"module"``


src/sage/rings/padics/lattice_precision.py 0 → 100644
553 s = " Timings " 554 elif tme < 0.000001: 555 s = "  " 556 elif tme >= 10: 557 s = " >= 10s " 558 else: 559 s = "%.6fs" % tme 560 return s + " " + status 561 else: 562 return status 563 564 565 class DifferentialPrecisionGeneric(UniqueRepresentation, SageObject): 566 """ 567 A generic class for precision objects obtained by automatic 568 differentiation 
Master
I believe that you need tests here to make the patchbot happy. Also, it would be nice if you could move up the
INPUT
section from__init__
to here.


src/sage/rings/padics/lattice_precision.py 0 → 100644
553 s = " Timings " 554 elif tme < 0.000001: 555 s = "  " 556 elif tme >= 10: 557 s = " >= 10s " 558 else: 559 s = "%.6fs" % tme 560 return s + " " + status 561 else: 562 return status 563 564 565 class DifferentialPrecisionGeneric(UniqueRepresentation, SageObject): 566 """ 567 A generic class for precision objects obtained by automatic 568 differentiation 
Master
I believe that you need tests here to make the patchbot happy. Also, it would be nice if you could move up the
INPUT
section from__init__
to here.


src/sage/rings/padics/lattice_precision.py 0 → 100644
587 588 TESTS:: 589 590 sage: R = ZpLC(2, label='init') # indirect doctest 591 sage: prec = R.precision() 592 sage: prec 593 Precision lattice on 0 object (label: init) 594 sage: prec._type 595 'lattice' 596 sage: prec.label() 597 'init' 598 """ 599 self._p = p 600 self._label = label 601 self._type = type 602 self._elements = [ ] # Probably better to use a double chained list 
Master
What is the meaning of this comment? I think you should either elaborate or drop it.


src/sage/rings/padics/lattice_precision.py 0 → 100644
626 Return a string representation of this precision lattice 627 628 EXAMPLES:: 629 630 sage: R = ZpLC(2) 631 sage: R.precision() 632 Precision lattice on ... objects 633 634 If a label has been specified, it is included in the representation 635 636 sage: R = ZpLC(2, label="mylabel") 637 sage: R.precision() 638 Precision lattice on 0 object (label: mylabel) 639 """ 640 n = len(self._elements) 641 if self._label is None: 
Master
Isn't
f"Precision {self._type} on {n} object{'' if n==1 else 's'}" + (f" (label: {self._label})" if self._label else "")
more readable/maintainable?


src/sage/rings/padics/lattice_precision.py 0 → 100644
641 if self._label is None: 642 if n > 1: 643 return "Precision %s on %s objects" % (self._type, len(self._elements)) 644 else: 645 return "Precision %s on %s object" % (self._type, len(self._elements)) 646 else: 647 if n > 1: 648 return "Precision %s on %s objects (label: %s)" % (self._type, len(self._elements), self._label) 649 else: 650 return "Precision %s on %s object (label: %s)" % (self._type, len(self._elements), self._label) 651 652 def thresold_deletion(self, thresold=None): 653 """ 654 Return or set the thresold for column deletion 655 656 When a variable dies, the ambiant space in which the precision 
Master
ambient?


src/sage/rings/padics/lattice_precision.py 0 → 100644
637 sage: R.precision() 638 Precision lattice on 0 object (label: mylabel) 639 """ 640 n = len(self._elements) 641 if self._label is None: 642 if n > 1: 643 return "Precision %s on %s objects" % (self._type, len(self._elements)) 644 else: 645 return "Precision %s on %s object" % (self._type, len(self._elements)) 646 else: 647 if n > 1: 648 return "Precision %s on %s objects (label: %s)" % (self._type, len(self._elements), self._label) 649 else: 650 return "Precision %s on %s object (label: %s)" % (self._type, len(self._elements), self._label) 651 652 def thresold_deletion(self, thresold=None): 
Master


src/sage/rings/padics/lattice_precision.py 0 → 100644
644 else: 645 return "Precision %s on %s object" % (self._type, len(self._elements)) 646 else: 647 if n > 1: 648 return "Precision %s on %s objects (label: %s)" % (self._type, len(self._elements), self._label) 649 else: 650 return "Precision %s on %s object (label: %s)" % (self._type, len(self._elements), self._label) 651 652 def thresold_deletion(self, thresold=None): 653 """ 654 Return or set the thresold for column deletion 655 656 When a variable dies, the ambiant space in which the precision 657 module lives can be reduced (by projection onto the hyperplane 658 defined by the dead variable). 659 However this reduction has a cost because it leads to reechonize 
Master
echelonize?


src/sage/rings/padics/lattice_precision.py 0 → 100644
646 else: 647 if n > 1: 648 return "Precision %s on %s objects (label: %s)" % (self._type, len(self._elements), self._label) 649 else: 650 return "Precision %s on %s object (label: %s)" % (self._type, len(self._elements), self._label) 651 652 def thresold_deletion(self, thresold=None): 653 """ 654 Return or set the thresold for column deletion 655 656 When a variable dies, the ambiant space in which the precision 657 module lives can be reduced (by projection onto the hyperplane 658 defined by the dead variable). 659 However this reduction has a cost because it leads to reechonize 660 a part of the matrix that encodes the precision. The size of this 661 part is roughly the distance between the last column and the one 
Master
What is the meaning of "distance" here?


src/sage/rings/padics/lattice_precision.py 0 → 100644
664 The thresold deletion is the maximal distance until which the 665 above reduction is performed. After the thresold, the column of 666 the dead variable is kept in this matrix as if the variable were 667 not destroyed. 668 669 INPUT: 670 671  ``thresold``  a non negative integer, ``Infinity`` or ``None`` 672 (default: ``None``): if ``None``, return the current thresold; 673 otherwise set the thresold to the given value 674 675 NOTE:: 676 677 Setting the thresold to ``0`` disables the dimension reduction. 678 679 Setting the thresold to ``Infinity`` 
Master
does what?


src/sage/rings/padics/lattice_precision.py 0 → 100644
639 """ 640 n = len(self._elements) 641 if self._label is None: 642 if n > 1: 643 return "Precision %s on %s objects" % (self._type, len(self._elements)) 644 else: 645 return "Precision %s on %s object" % (self._type, len(self._elements)) 646 else: 647 if n > 1: 648 return "Precision %s on %s objects (label: %s)" % (self._type, len(self._elements), self._label) 649 else: 650 return "Precision %s on %s object (label: %s)" % (self._type, len(self._elements), self._label) 651 652 def thresold_deletion(self, thresold=None): 653 """ 654 Return or set the thresold for column deletion 
Master
I think this is easier to understand if it always returns the new value. So "Return (and set) the threshold for column deletion."?


src/sage/rings/padics/lattice_precision.py 0 → 100644
721 """ 722 Return the underlying prime number attached to this precision lattice. 723 724 EXAMPLE:: 725 726 sage: R = ZpLC(2, label="mylabel") 727 sage: R.precision().prime() 728 2 729 """ 730 return self._p 731 732 def _index(self, ref): 733 """ 734 Return the index of the element whose reference is ``ref`` 735 736 Only for internal use! 
Master
Unfortunately this needs a doctest nevertheless to make the patchbot happy.


src/sage/rings/padics/lattice_precision.py 0 → 100644
725 726 sage: R = ZpLC(2, label="mylabel") 727 sage: R.precision().prime() 728 2 729 """ 730 return self._p 731 732 def _index(self, ref): 733 """ 734 Return the index of the element whose reference is ``ref`` 735 736 Only for internal use! 737 """ 738 return self._elements.index(ref) 739 740 def ambiant_dimension(self): 
Master
Isn't it "ambient"?


src/sage/rings/padics/lattice_precision.py 0 → 100644
775 sage: prec.dimension() 776 2 777 778 sage: u = x + y 779 sage: prec.ambiant_dimension() 780 3 781 sage: prec.dimension() 782 2 783 """ 784 return len(self._matrix) 785 786 def dimension(self): 787 """ 788 Return the dimension of this precision module 789 790 This method must be implemented in subclasses 
Master
This needs a doctest.

Master
I think it's better to explain what this method does and give some concrete examples of how it works (in subclasses) instead of telling people explicitly to implement it. It's clear that this needs to be implemented and people probably want to see examples to understand what this should be doing?

Master
(same for the following methods.)


src/sage/rings/padics/lattice_precision.py 0 → 100644
777 778 sage: u = x + y 779 sage: prec.ambiant_dimension() 780 3 781 sage: prec.dimension() 782 2 783 """ 784 return len(self._matrix) 785 786 def dimension(self): 787 """ 788 Return the dimension of this precision module 789 790 This method must be implemented in subclasses 791 """ 792 raise NotImplementedError("implement this function is subclasses") 
src/sage/rings/padics/lattice_precision.py 0 → 100644
779 sage: prec.ambiant_dimension() 780 3 781 sage: prec.dimension() 782 2 783 """ 784 return len(self._matrix) 785 786 def dimension(self): 787 """ 788 Return the dimension of this precision module 789 790 This method must be implemented in subclasses 791 """ 792 raise NotImplementedError("implement this function is subclasses") 793 794 def new_element(self, *args): 
Master


src/sage/rings/padics/lattice_precision.py 0 → 100644
829 or, if not given, on the whole set of elements tracked by the precision 830 module 831 832 This method must be implemented in subclasses 833 """ 834 raise NotImplementedError("implement this function in subclasses") 835 836 def number_of_diffused_digits(self, elements=None): 837 """ 838 Return the number of diffused digits of precision within a 839 subset of elements. 840 841 NOTE: 842 843 A diffused digit of precision is a known digit which is not 844 located on a single variable but only atppears on a suitable 
Master
"appears".


src/sage/rings/padics/lattice_precision.py 0 → 100644
830 module 831 832 This method must be implemented in subclasses 833 """ 834 raise NotImplementedError("implement this function in subclasses") 835 836 def number_of_diffused_digits(self, elements=None): 837 """ 838 Return the number of diffused digits of precision within a 839 subset of elements. 840 841 NOTE: 842 843 A diffused digit of precision is a known digit which is not 844 located on a single variable but only atppears on a suitable 845 linear combinaison of variables. 
Master
"combination"


src/sage/rings/padics/lattice_precision.py 0 → 100644
837 """ 838 Return the number of diffused digits of precision within a 839 subset of elements. 840 841 NOTE: 842 843 A diffused digit of precision is a known digit which is not 844 located on a single variable but only atppears on a suitable 845 linear combinaison of variables. 846 847 The number of diffused digits of precision quantifies the 848 quality of the approximation of the lattice precision by a 849 jagged precision (that is a precision which is split over 850 all variables). 851 852 We refer to [] for a detail exposition of the notion of 
Master
A reference is missing here.


src/sage/rings/padics/lattice_precision.py 0 → 100644
873 Here is another example with matrices:: 874 875 sage: M = matrix(R, 2, 2, [R(3,5),R(7,5),R(1,5),R(11,1)]) 876 sage: N = M^10 877 878 The next syntax provides as easy way to select an interesting 879 subset of variables (the selected subset consists of the four 880 entries of the matrix ``N``):: 881 882 sage: prec.number_of_diffused_digits(N) 883 17 884 """ 885 M = self.precision_lattice(elements) 886 n = M.nrows() 887 if M.ncols() > n: 888 return Infinity 
Master
What's the meaning of an infinite number of diffused digits? Maybe there should be an example?
