Lattice precision for the parents ZpLC/QpLC and ZpLF/QpLF¶
AUTHOR:
Xavier Caruso (2018-02): initial version
- class sage.rings.padics.lattice_precision.DifferentialPrecisionGeneric(p, label)[source]¶
Bases:
SageObjectA generic class for precision objects obtained by automatic differentiation.
INPUT:
p– a prime numberlabel– string; the label of the parents to which the elements belong that are tracked by this precision module
Note
This object is used internally by the parent ring. You should not create instances of this class on your own.
EXAMPLES:
sage: R = ZpLC(2, label='init') sage: R.precision() Precision lattice on 0 objects (label: init)
>>> from sage.all import * >>> R = ZpLC(Integer(2), label='init') >>> R.precision() Precision lattice on 0 objects (label: init)
- ambient_dimension()[source]¶
Return the dimension of the vector space in which the precision module/lattice lives.
EXAMPLES:
sage: R = ZpLC(2, label='ambient_dim') sage: prec = R.precision() sage: x, y = R(1, 10), R(1, 5) sage: prec.ambient_dimension() 2 sage: prec.dimension() 2 sage: u = x + y sage: prec.ambient_dimension() 3 sage: prec.dimension() 3
>>> from sage.all import * >>> R = ZpLC(Integer(2), label='ambient_dim') >>> prec = R.precision() >>> x, y = R(Integer(1), Integer(10)), R(Integer(1), Integer(5)) >>> prec.ambient_dimension() 2 >>> prec.dimension() 2 >>> u = x + y >>> prec.ambient_dimension() 3 >>> prec.dimension() 3
In the case of
ZpLC(lattice-cap precision), it is always equal to the dimension of the lattice.In the case of
ZpLF(lattice-float precision), the precision object is not necessarily a lattice and then may have smaller dimension:sage: R = ZpLF(2, label='ambient_dim') sage: prec = R.precision() sage: x, y = R(1, 10), R(1, 5) sage: prec.ambient_dimension() 2 sage: prec.dimension() 2 sage: u = x + y sage: prec.ambient_dimension() 3 sage: prec.dimension() 2
[Python]>>> from sage.all import * >>> R = ZpLF(Integer(2), label='ambient_dim') >>> prec = R.precision() >>> x, y = R(Integer(1), Integer(10)), R(Integer(1), Integer(5)) >>> prec.ambient_dimension() 2 >>> prec.dimension() 2 >>> u = x + y >>> prec.ambient_dimension() 3 >>> prec.dimension() 2
- del_elements(threshold=None)[source]¶
Delete (or mark for future deletion) the columns of precision matrix corresponding to elements that were collected by the garbage collector.
INPUT:
threshold– integer orNone(default:None); a column whose distance to the right is greater than the threshold is not erased but marked for deletion. IfNone, always erase (never mark for deletion).
EXAMPLES:
sage: R = ZpLC(2, label='del_elements') sage: prec = R.precision() sage: x = R(1, 10) sage: prec Precision lattice on 1 object (label: del_elements) sage: prec.precision_lattice() # needs sage.geometry.polyhedron [1024] sage: del x sage: prec Precision lattice on 1 object (label: del_elements) sage: prec.precision_lattice() # needs sage.geometry.polyhedron [1024] sage: prec.del_elements() sage: prec Precision lattice on 0 objects (label: del_elements) sage: prec.precision_lattice() # needs sage.geometry.polyhedron []
>>> from sage.all import * >>> R = ZpLC(Integer(2), label='del_elements') >>> prec = R.precision() >>> x = R(Integer(1), Integer(10)) >>> prec Precision lattice on 1 object (label: del_elements) >>> prec.precision_lattice() # needs sage.geometry.polyhedron [1024] >>> del x >>> prec Precision lattice on 1 object (label: del_elements) >>> prec.precision_lattice() # needs sage.geometry.polyhedron [1024] >>> prec.del_elements() >>> prec Precision lattice on 0 objects (label: del_elements) >>> prec.precision_lattice() # needs sage.geometry.polyhedron []
- diffused_digits(elements=None)[source]¶
Return the number of diffused digits of precision within a subset of elements.
A diffused digit of precision is a known digit which is not located on a single variable but only appears on a suitable linear combination of variables.
The number of diffused digits of precision quantifies the quality of the approximation of the lattice precision by a jagged precision (that is a precision which is split over all variables).
We refer to [CRV2018] for a detail exposition of the notion of diffused digits.
EXAMPLES:
sage: R = ZpLC(2) sage: prec = R.precision() sage: x = R(1, 10); y = R(1, 5) sage: u = x + y sage: v = x - y sage: prec.diffused_digits([x, y]) # needs sage.geometry.polyhedron 0 sage: prec.diffused_digits([u, v]) # needs sage.geometry.polyhedron 6
>>> from sage.all import * >>> R = ZpLC(Integer(2)) >>> prec = R.precision() >>> x = R(Integer(1), Integer(10)); y = R(Integer(1), Integer(5)) >>> u = x + y >>> v = x - y >>> prec.diffused_digits([x, y]) # needs sage.geometry.polyhedron 0 >>> prec.diffused_digits([u, v]) # needs sage.geometry.polyhedron 6
The elements \(u\) and \(v\) are known at absolute precision \(O(2^5)\). However, the sum \(u + v = 2x\) is known at precision \(O(2^11)\), that is with \(6\) more digits. That is where the \(6\) diffused digits of precision comes from.
Here is another example with matrices:
sage: M = matrix(R, 2, 2, [R(3, 5), R(7, 5), R(1, 5), R(11, 1)]) # needs sage.modules sage: N = M^10 # needs sage.modules
[Python]>>> from sage.all import * >>> M = matrix(R, Integer(2), Integer(2), [R(Integer(3), Integer(5)), R(Integer(7), Integer(5)), R(Integer(1), Integer(5)), R(Integer(11), Integer(1))]) # needs sage.modules >>> N = M**Integer(10) # needs sage.modules
The next syntax provides as easy way to select an interesting subset of variables (the selected subset consists of the four entries of the matrix
N):sage: prec.diffused_digits(N) # needs sage.geometry.polyhedron sage.modules 17
>>> from sage.all import * >>> prec.diffused_digits(N) # needs sage.geometry.polyhedron sage.modules 17
Note that, in some cases, the number of diffused digits can be infinite:
sage: R = ZpLF(2) sage: prec = R.precision() sage: x = R(1, 10) sage: y = x sage: prec.diffused_digits([x, y]) # needs sage.geometry.polyhedron +Infinity
[Python]>>> from sage.all import * >>> R = ZpLF(Integer(2)) >>> prec = R.precision() >>> x = R(Integer(1), Integer(10)) >>> y = x >>> prec.diffused_digits([x, y]) # needs sage.geometry.polyhedron +Infinity
- dimension()[source]¶
Return the dimension of this precision module.
EXAMPLES:
sage: R = ZpLC(5, label='dim') sage: prec = R.precision() sage: prec.dimension() 0 sage: x = R(1, 10) sage: prec.dimension() 1
>>> from sage.all import * >>> R = ZpLC(Integer(5), label='dim') >>> prec = R.precision() >>> prec.dimension() 0 >>> x = R(Integer(1), Integer(10)) >>> prec.dimension() 1
- history(compact=True, separate_reduce=False, timings=True, output_type='asciiart')[source]¶
Show history.
The history records creations and deletions of elements attached to this precision lattice, together with many timings.
INPUT:
compact– boolean (default:True); ifTrue, all consecutive operations of the same type appear on a single rowseparate_reduce– boolean (default:False); specify whether partial/full Hermite reduction should be displayed separatelytimings– boolean (default:True); specify whether timings should be displayedoutput_type– onlyasciiartis implemented for now
IMPORTANT NOTE:
History is disabled by default. It should then be enabled (through a call to the method
history_enable()) before use.EXAMPLES:
sage: R = ZpLC(2, label='history_en') sage: prec = R.precision()
>>> from sage.all import * >>> R = ZpLC(Integer(2), label='history_en') >>> prec = R.precision()
We first enable history:
sage: prec.history_enable()
[Python]>>> from sage.all import * >>> prec.history_enable()
At the beginning, the history is of course empty:
sage: print(prec.history()) Timings ---
>>> from sage.all import * >>> print(prec.history()) Timings ---
Now we start creating and deleting elements:
sage: L = [R.random_element() for _ in range(20)] sage: for p in range(20): ....: if is_prime(p): L[p] = None sage: prec.del_elements() sage: print(prec.history()) # somewhat random Timings 0.001108s oooooooooooooooooooo 0.000009s oo~~o~o~ooo~o~ooo~o~ 0.014250s oooooooooooo
[Python]>>> from sage.all import * >>> L = [R.random_element() for _ in range(Integer(20))] >>> for p in range(Integer(20)): ... if is_prime(p): L[p] = None >>> prec.del_elements() >>> print(prec.history()) # somewhat random Timings 0.001108s oooooooooooooooooooo 0.000009s oo~~o~o~ooo~o~ooo~o~ 0.014250s oooooooooooo
The legend is the following:
the symbol
orepresents a tracked element,the symbol
~represents an element which is marked for deletion.
On the history, we see:
1st line: twenty new elements were created (this corresponds to the affectation of the list
L);2nd line: elements at prime positions were marked for deletion (this corresponds to the
forloop);3rd line: the above elements are indeed deleted (this corresponds to the call of the method
del_elements().
Here are some variants:
sage: print(prec.history(timings=False)) oooooooooooooooooooo oo~~o~o~ooo~o~ooo~o~ oooooooooooo sage: print(prec.history(separate_reduce=True)) # somewhat random Timings 0.001063s oooooooooooooooooooo 0.000014s oo~~o~o~ooo~o~ooo~o~ 0.000798s oo~~o~o~ooo~ooooo 0.000233s oo~~o~o~ooo~orrrr 0.000824s oo~~o~o~oooooooo 0.000375s oo~~o~o~ooorrrrr 0.001724s oo~~o~ooooooooo 0.001020s oo~~o~orrrrrrrr 0.001989s oo~~oooooooooo 0.001303s oo~~orrrrrrrrr 0.002352s oo~oooooooooo 0.001632s oo~rrrrrrrrrr 0.002265s oooooooooooo 0.001630s oorrrrrrrrrr --- oooooooooooo
>>> from sage.all import * >>> print(prec.history(timings=False)) oooooooooooooooooooo oo~~o~o~ooo~o~ooo~o~ oooooooooooo >>> print(prec.history(separate_reduce=True)) # somewhat random Timings 0.001063s oooooooooooooooooooo 0.000014s oo~~o~o~ooo~o~ooo~o~ 0.000798s oo~~o~o~ooo~ooooo 0.000233s oo~~o~o~ooo~orrrr 0.000824s oo~~o~o~oooooooo 0.000375s oo~~o~o~ooorrrrr 0.001724s oo~~o~ooooooooo 0.001020s oo~~o~orrrrrrrr 0.001989s oo~~oooooooooo 0.001303s oo~~orrrrrrrrr 0.002352s oo~oooooooooo 0.001632s oo~rrrrrrrrrr 0.002265s oooooooooooo 0.001630s oorrrrrrrrrr --- oooooooooooo
The symbol
rrepresents a column of the precision matrix which is currently under partial Hermite reduction.Timings for automatic reduction do not appear because they are included in the timings for deletion.
The symbol
Ris used to symbolize a column which is under full Hermite reduction. Note that full Hermite reduction are never performed automatically but needs to be called by hand:sage: prec.reduce() sage: print(prec.history(separate_reduce=True)) # somewhat random Timings 0.001063s oooooooooooooooooooo 0.000014s oo~~o~o~ooo~o~ooo~o~ 0.000798s oo~~o~o~ooo~ooooo 0.000233s oo~~o~o~ooo~orrrr 0.000824s oo~~o~o~oooooooo 0.000375s oo~~o~o~ooorrrrr 0.001724s oo~~o~ooooooooo 0.001020s oo~~o~orrrrrrrr 0.001989s oo~~oooooooooo 0.001303s oo~~orrrrrrrrr 0.002352s oo~oooooooooo 0.001632s oo~rrrrrrrrrr 0.002265s oooooooooooo 0.001630s oorrrrrrrrrr 0.001486s RRRRRRRRRRRR --- oooooooooooo
[Python]>>> from sage.all import * >>> prec.reduce() >>> print(prec.history(separate_reduce=True)) # somewhat random Timings 0.001063s oooooooooooooooooooo 0.000014s oo~~o~o~ooo~o~ooo~o~ 0.000798s oo~~o~o~ooo~ooooo 0.000233s oo~~o~o~ooo~orrrr 0.000824s oo~~o~o~oooooooo 0.000375s oo~~o~o~ooorrrrr 0.001724s oo~~o~ooooooooo 0.001020s oo~~o~orrrrrrrr 0.001989s oo~~oooooooooo 0.001303s oo~~orrrrrrrrr 0.002352s oo~oooooooooo 0.001632s oo~rrrrrrrrrr 0.002265s oooooooooooo 0.001630s oorrrrrrrrrr 0.001486s RRRRRRRRRRRR --- oooooooooooo
Here is a more common example with matrices:
sage: R = ZpLC(3) sage: prec = R.precision() sage: prec.history_enable() sage: M = random_matrix(R, 5) # needs sage.geometry.polyhedron sage: d = M.determinant() # needs sage.geometry.polyhedron sage: print(prec.history()) # somewhat random --- 0.004212s oooooooooooooooooooooooooooooooooooo 0.000003s oooooooooooooooooooooooooooooooooo~~ 0.000010s oooooooooooooooooooooooooooooooooo 0.001560s ooooooooooooooooooooooooooooooooooooooooo 0.000004s ooooooooooooooooooooooooooooo~oooo~oooo~o 0.002168s oooooooooooooooooooooooooooooooooooooo 0.001787s ooooooooooooooooooooooooooooooooooooooooo 0.000004s oooooooooooooooooooooooooooooooooooooo~~o 0.000198s ooooooooooooooooooooooooooooooooooooooo 0.001152s ooooooooooooooooooooooooooooooooooooooooo 0.000005s ooooooooooooooooooooooooooooooooo~oooo~~o 0.000853s oooooooooooooooooooooooooooooooooooooo 0.000610s ooooooooooooooooooooooooooooooooooooooo [...] 0.003879s ooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 0.000006s oooooooooooooooooooooooooooooooooooooooooooooooooooo~~~~~ 0.000036s oooooooooooooooooooooooooooooooooooooooooooooooooooo 0.006737s oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 0.000005s oooooooooooooooooooooooooooooooooooooooooooooooooooo~~~~~ooooo 0.002637s ooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 0.007118s ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 0.000008s oooooooooooooooooooooooooooooooooooooooooooooooooooo~~~~o~~~~oooo 0.003504s ooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 0.005371s ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 0.000006s ooooooooooooooooooooooooooooooooooooooooooooooooooooo~~~o~~~ooo 0.001858s ooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 0.003584s ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 0.000004s oooooooooooooooooooooooooooooooooooooooooooooooooooooo~~o~~oo 0.000801s ooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 0.001916s ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 0.000022s ooooooooooooooooooooooooooooo~~~~~~~~~~~~~~~~~~~~~~oooo~o~o 0.014705s ooooooooooooooooooooooooooooooooooo 0.001292s ooooooooooooooooooooooooooooooooooooo
>>> from sage.all import * >>> R = ZpLC(Integer(3)) >>> prec = R.precision() >>> prec.history_enable() >>> M = random_matrix(R, Integer(5)) # needs sage.geometry.polyhedron >>> d = M.determinant() # needs sage.geometry.polyhedron >>> print(prec.history()) # somewhat random --- 0.004212s oooooooooooooooooooooooooooooooooooo 0.000003s oooooooooooooooooooooooooooooooooo~~ 0.000010s oooooooooooooooooooooooooooooooooo 0.001560s ooooooooooooooooooooooooooooooooooooooooo 0.000004s ooooooooooooooooooooooooooooo~oooo~oooo~o 0.002168s oooooooooooooooooooooooooooooooooooooo 0.001787s ooooooooooooooooooooooooooooooooooooooooo 0.000004s oooooooooooooooooooooooooooooooooooooo~~o 0.000198s ooooooooooooooooooooooooooooooooooooooo 0.001152s ooooooooooooooooooooooooooooooooooooooooo 0.000005s ooooooooooooooooooooooooooooooooo~oooo~~o 0.000853s oooooooooooooooooooooooooooooooooooooo 0.000610s ooooooooooooooooooooooooooooooooooooooo [...] 0.003879s ooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 0.000006s oooooooooooooooooooooooooooooooooooooooooooooooooooo~~~~~ 0.000036s oooooooooooooooooooooooooooooooooooooooooooooooooooo 0.006737s oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 0.000005s oooooooooooooooooooooooooooooooooooooooooooooooooooo~~~~~ooooo 0.002637s ooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 0.007118s ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 0.000008s oooooooooooooooooooooooooooooooooooooooooooooooooooo~~~~o~~~~oooo 0.003504s ooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 0.005371s ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 0.000006s ooooooooooooooooooooooooooooooooooooooooooooooooooooo~~~o~~~ooo 0.001858s ooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 0.003584s ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 0.000004s oooooooooooooooooooooooooooooooooooooooooooooooooooooo~~o~~oo 0.000801s ooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 0.001916s ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 0.000022s ooooooooooooooooooooooooooooo~~~~~~~~~~~~~~~~~~~~~~oooo~o~o 0.014705s ooooooooooooooooooooooooooooooooooo 0.001292s ooooooooooooooooooooooooooooooooooooo
We observe that deleted variables appear mostly on the right. This is the so-called principal of temporal locality.
See also
- history_clear()[source]¶
Clear history.
We refer to the documentation of the method
history()for a complete documentation (including examples) about history.See also
- history_disable()[source]¶
Disable history.
We refer to the documentation of the method
history()for a complete documentation (including examples) about history.See also
- history_enable()[source]¶
Enable history.
We refer to the documentation of the method
history()for a complete documentation (including examples) about history.See also
- precision_lattice(elements=None)[source]¶
Return a lattice modeling the precision on the given set of elements or, if not given, on the whole set of elements tracked by the precision module.
INPUT:
elements– list of elements orNone(default:None)
EXAMPLES:
sage: R = ZpLC(2, label='precision_lattice') sage: prec = R.precision() sage: x = R(1, 10); y = R(1, 5) sage: u = x + y sage: v = x - y sage: prec.precision_lattice() # needs sage.geometry.polyhedron [ 1024 0 1024 1024] [ 0 32 32 1099511627744] [ 0 0 2097152 0] [ 0 0 0 1099511627776] sage: prec.precision_lattice([u, v]) # needs sage.geometry.polyhedron [ 32 2016] [ 0 2048]
>>> from sage.all import * >>> R = ZpLC(Integer(2), label='precision_lattice') >>> prec = R.precision() >>> x = R(Integer(1), Integer(10)); y = R(Integer(1), Integer(5)) >>> u = x + y >>> v = x - y >>> prec.precision_lattice() # needs sage.geometry.polyhedron [ 1024 0 1024 1024] [ 0 32 32 1099511627744] [ 0 0 2097152 0] [ 0 0 0 1099511627776] >>> prec.precision_lattice([u, v]) # needs sage.geometry.polyhedron [ 32 2016] [ 0 2048]
If the precision module does not project to a lattice, an error is raised.
sage: R = ZpLF(2, label='precision_lattice') sage: prec = R.precision() sage: x = R(1, 10); y = R(1, 5) sage: u = x + y sage: v = x - y sage: prec.precision_lattice([x,y,u,v]) # needs sage.geometry.polyhedron Traceback (most recent call last): ... PrecisionError: the differential is not surjective
[Python]>>> from sage.all import * >>> R = ZpLF(Integer(2), label='precision_lattice') >>> prec = R.precision() >>> x = R(Integer(1), Integer(10)); y = R(Integer(1), Integer(5)) >>> u = x + y >>> v = x - y >>> prec.precision_lattice([x,y,u,v]) # needs sage.geometry.polyhedron Traceback (most recent call last): ... PrecisionError: the differential is not surjective
- prime()[source]¶
Return the underlying prime number attached to this precision lattice.
EXAMPLES:
sage: R = ZpLC(2, label='mylabel') sage: R.precision().prime() 2
>>> from sage.all import * >>> R = ZpLC(Integer(2), label='mylabel') >>> R.precision().prime() 2
- threshold_deletion(threshold=None)[source]¶
Return (and set) the threshold for column deletion.
When a variable dies, i.e., goes out of scope, the ambient space in which the precision module lives can be reduced (by projection onto the hyperplane defined by the dead variable). This reduction has a cost because it leads to re-echelonization of a part of the matrix that encodes the precision. The size of this part is roughly measured by the number of columns between the last column and the one corresponding to the dead variable.
This threshold returned by this method is the maximal distance until which a column of a dead variable is removed and the matrix re-echelonized. Beyond the threshold, the column of the dead variable is kept in this matrix as if the variable were not destroyed.
INPUT:
threshold– nonnegative integer,InfinityorNone(default:None); if notNoneset the threshold to the given value.
Note
Setting the threshold to
0disables the dimension reduction.Setting the threshold to
Infinityforces the dimension reduction after each deletion.EXAMPLES:
sage: R = ZpLC(2, label='threshold_deletion') sage: prec = R.precision() sage: prec.threshold_deletion() 50 sage: prec.threshold_deletion(20) 20 sage: prec.threshold_deletion() 20 sage: prec.threshold_deletion(-2) Traceback (most recent call last): ... ValueError: The threshold must be a nonnegative integer or Infinity
>>> from sage.all import * >>> R = ZpLC(Integer(2), label='threshold_deletion') >>> prec = R.precision() >>> prec.threshold_deletion() 50 >>> prec.threshold_deletion(Integer(20)) 20 >>> prec.threshold_deletion() 20 >>> prec.threshold_deletion(-Integer(2)) Traceback (most recent call last): ... ValueError: The threshold must be a nonnegative integer or Infinity
- timings(action=None)[source]¶
Return cumulated timings (grouped by actions) since the last time history has been cleared.
INPUT:
action–None(default),'add','mark','del','partial reduce'or'full reduce'; if notNone, return the cumulated timing corresponding to this action; otherwise, return a dictionary
Here are the meanings of the keywords above:
'add': time spent in adding new columns to the precision matrix (corresponding to the creation of new elements)'mark': time spent in marking elements for deletion'del': time spent in deleting columns of the precision matrix and re-echelonizing the matrix'partial reduce': time spent in partial Hermite reduction'full reduce': time spent in full Hermite reduction.
EXAMPLES:
sage: R = ZpLC(2, label='timings') sage: prec = R.precision() sage: prec.history_enable() sage: M = random_matrix(R, 5, 5) # needs sage.geometry.polyhedron sage: N = M^10 # needs sage.geometry.polyhedron sage: prec.timings() # somewhat random {'add': 1.0530245304107666, 'del': 0.24358701705932617, 'mark': 0.0013289451599121094, 'partial reduce': 0.21604204177856445 'full reduce': 0}
>>> from sage.all import * >>> R = ZpLC(Integer(2), label='timings') >>> prec = R.precision() >>> prec.history_enable() >>> M = random_matrix(R, Integer(5), Integer(5)) # needs sage.geometry.polyhedron >>> N = M**Integer(10) # needs sage.geometry.polyhedron >>> prec.timings() # somewhat random {'add': 1.0530245304107666, 'del': 0.24358701705932617, 'mark': 0.0013289451599121094, 'partial reduce': 0.21604204177856445 'full reduce': 0}
- tracked_elements(values=True, dead=True)[source]¶
Return the list of tracked elements.
INPUT:
values– boolean (default:True); ifFalse, the method returns a list of weak references on tracked elements insteaddead– boolean (default:True); whether dead elements for which the corresponding column is still not erased should be listed or not
EXAMPLES:
sage: R = ZpLC(2, label='tracked') sage: prec = R.precision() sage: x = R(1, 10); y = R(1, 5) sage: prec.tracked_elements() [1 + O(2^10), 1 + O(2^5)] sage: prec.tracked_elements(values=False) [WeakProxy#..., WeakProxy#..., WeakProxy#...] sage: prec.tracked_elements(values=False, dead=False) [WeakProxy#..., WeakProxy#...] sage: u = x + y sage: v = x - y sage: prec.tracked_elements() [1 + O(2^10), 1 + O(2^5), 2 + O(2^5), O(2^5)] sage: prec.tracked_elements(values=False) [WeakProxy#..., WeakProxy#..., WeakProxy#..., WeakProxy#..., WeakProxy#...] sage: del x; del y sage: prec.tracked_elements() [None, None, 2 + O(2^5), O(2^5), None] sage: prec.tracked_elements(values=False) [WeakProxy#..., WeakProxy#..., WeakProxy#...]
>>> from sage.all import * >>> R = ZpLC(Integer(2), label='tracked') >>> prec = R.precision() >>> x = R(Integer(1), Integer(10)); y = R(Integer(1), Integer(5)) >>> prec.tracked_elements() [1 + O(2^10), 1 + O(2^5)] >>> prec.tracked_elements(values=False) [WeakProxy#..., WeakProxy#..., WeakProxy#...] >>> prec.tracked_elements(values=False, dead=False) [WeakProxy#..., WeakProxy#...] >>> u = x + y >>> v = x - y >>> prec.tracked_elements() [1 + O(2^10), 1 + O(2^5), 2 + O(2^5), O(2^5)] >>> prec.tracked_elements(values=False) [WeakProxy#..., WeakProxy#..., WeakProxy#..., WeakProxy#..., WeakProxy#...] >>> del x; del y >>> prec.tracked_elements() [None, None, 2 + O(2^5), O(2^5), None] >>> prec.tracked_elements(values=False) [WeakProxy#..., WeakProxy#..., WeakProxy#...]
- class sage.rings.padics.lattice_precision.PrecisionLattice(p, label)[source]¶
Bases:
UniqueRepresentation,DifferentialPrecisionGenericA class for handling precision lattices which are used to track precision in the ZpLC model.
The precision lattice is stored as a triangular matrix whose rows are generators of the lattice.
INPUT:
p– a prime numberlabel– string; the label of the parents to which the elements tracked by this lattice belong
Note
You should not create instances of this class directly. The precision lattice is automatically initialized at the creation of the parent.
EXAMPLES:
sage: R = ZpLC(2, label='init') sage: R.precision() Precision lattice on 0 objects (label: init)
>>> from sage.all import * >>> R = ZpLC(Integer(2), label='init') >>> R.precision() Precision lattice on 0 objects (label: init)
- del_elements(threshold=None)[source]¶
Erase columns of the lattice precision matrix corresponding to elements which are marked for deletion and echelonize the matrix in order to keep it upper triangular.
INPUT:
threshold– integer orNone(default:None); a column whose distance to the right is greater than the threshold is not erased
EXAMPLES:
sage: R = ZpLC(2, label='delelts') sage: prec = R.precision() sage: x = R(1, 10) sage: prec Precision lattice on 1 object (label: delelts) sage: prec.precision_lattice() # needs sage.geometry.polyhedron [1024] sage: del x sage: prec Precision lattice on 1 object (label: delelts) sage: prec.precision_lattice() # needs sage.geometry.polyhedron [1024] sage: prec.del_elements() sage: prec Precision lattice on 0 objects (label: delelts) sage: prec.precision_lattice() # needs sage.geometry.polyhedron []
>>> from sage.all import * >>> R = ZpLC(Integer(2), label='delelts') >>> prec = R.precision() >>> x = R(Integer(1), Integer(10)) >>> prec Precision lattice on 1 object (label: delelts) >>> prec.precision_lattice() # needs sage.geometry.polyhedron [1024] >>> del x >>> prec Precision lattice on 1 object (label: delelts) >>> prec.precision_lattice() # needs sage.geometry.polyhedron [1024] >>> prec.del_elements() >>> prec Precision lattice on 0 objects (label: delelts) >>> prec.precision_lattice() # needs sage.geometry.polyhedron []
- dimension()[source]¶
Return the dimension of this lattice.
EXAMPLES:
sage: R = ZpLC(5, label='dimension') sage: prec = R.precision() sage: prec.dimension() 0 sage: x = R(1, 10) sage: prec.dimension() 1
>>> from sage.all import * >>> R = ZpLC(Integer(5), label='dimension') >>> prec = R.precision() >>> prec.dimension() 0 >>> x = R(Integer(1), Integer(10)) >>> prec.dimension() 1
- precision_lattice(elements=None)[source]¶
Return a matrix representing the precision lattice on a subset of elements.
INPUT:
elements– list of elements orNone(default:None)echelon– boolean (default:True); whether the result should be in echelon form
EXAMPLES:
sage: R = ZpLC(2, label='preclattice') sage: prec = R.precision() sage: x = R(1, 10); y = R(1, 5) sage: u = x + y sage: v = x - y sage: prec.precision_lattice() # needs sage.geometry.polyhedron [ 1024 0 1024 1024] [ 0 32 32 1099511627744] [ 0 0 2097152 0] [ 0 0 0 1099511627776] sage: prec.precision_lattice([u, v]) # needs sage.geometry.polyhedron [ 32 2016] [ 0 2048]
>>> from sage.all import * >>> R = ZpLC(Integer(2), label='preclattice') >>> prec = R.precision() >>> x = R(Integer(1), Integer(10)); y = R(Integer(1), Integer(5)) >>> u = x + y >>> v = x - y >>> prec.precision_lattice() # needs sage.geometry.polyhedron [ 1024 0 1024 1024] [ 0 32 32 1099511627744] [ 0 0 2097152 0] [ 0 0 0 1099511627776] >>> prec.precision_lattice([u, v]) # needs sage.geometry.polyhedron [ 32 2016] [ 0 2048]
Here is another example with matrices:
sage: M = matrix(R, 2, 2, [R(3, 5), R(7, 5), R(1, 5), R(11, 1)]) # needs sage.modules sage: N = M^10 # needs sage.modules sage: prec.precision_lattice() # needs sage.geometry.polyhedron sage.modules 23 x 23 dense matrix over Integer Ring (use the '.str()' method to see the entries)
[Python]>>> from sage.all import * >>> M = matrix(R, Integer(2), Integer(2), [R(Integer(3), Integer(5)), R(Integer(7), Integer(5)), R(Integer(1), Integer(5)), R(Integer(11), Integer(1))]) # needs sage.modules >>> N = M**Integer(10) # needs sage.modules >>> prec.precision_lattice() # needs sage.geometry.polyhedron sage.modules 23 x 23 dense matrix over Integer Ring (use the '.str()' method to see the entries)
The next syntax provides as easy way to select an interesting subset of variables (the selected subset consists of the four entries of the matrix
N):sage: prec.precision_lattice(N) # needs sage.modules [ 2048 512 28160 230400] [ 0 2048 14336 258048] [ 0 0 65536 65536] [ 0 0 0 262144]
>>> from sage.all import * >>> prec.precision_lattice(N) # needs sage.modules [ 2048 512 28160 230400] [ 0 2048 14336 258048] [ 0 0 65536 65536] [ 0 0 0 262144]
We can give a list of matrices as well:
sage: prec.precision_lattice([M, N]) # needs sage.modules [ 32 0 0 0 226115584 96788480 52174848 82804736] [ 0 32 0 0 52174848 121765888 11829248 28516352] [ 0 0 32 0 96788480 42762240 121765888 199614464] [ 0 0 0 2 5175296 12475904 1782272 4045824] [ 0 0 0 0 268435456 0 0 0] [ 0 0 0 0 0 268435456 0 0] [ 0 0 0 0 0 0 268435456 0] [ 0 0 0 0 0 0 0 268435456]
[Python]>>> from sage.all import * >>> prec.precision_lattice([M, N]) # needs sage.modules [ 32 0 0 0 226115584 96788480 52174848 82804736] [ 0 32 0 0 52174848 121765888 11829248 28516352] [ 0 0 32 0 96788480 42762240 121765888 199614464] [ 0 0 0 2 5175296 12475904 1782272 4045824] [ 0 0 0 0 268435456 0 0 0] [ 0 0 0 0 0 268435456 0 0] [ 0 0 0 0 0 0 268435456 0] [ 0 0 0 0 0 0 0 268435456]
- reduce(index=0, partial=False)[source]¶
Reduce the size of the entries above the diagonal of the precision matrix.
INPUT:
index– integer; the starting row for which the reduction is performedpartial– boolean (default:False); specifying whether a partial or a full Hermite reduction should be performed
NOTE:
The partial reduction has cost \(O(m^2)\) where \(m\) is the number of rows that need to be reduced (that is the difference between the total number of rows and
index).The full Hermite reduction has cost \(O(m^3)\).
Note
The software ensures that the precision lattice is always partially reduced. Calling the function manually with the argument
partial=Trueshould then just do nothing.
- class sage.rings.padics.lattice_precision.PrecisionModule(p, label, prec)[source]¶
Bases:
UniqueRepresentation,DifferentialPrecisionGenericA class for handling precision modules which are used to track precision in the ZpLF model.
The precision module (which is not necessarily a lattice) is stored as a matrix whose rows are generators.
- del_elements(threshold=None)[source]¶
Erase columns of the lattice precision matrix corresponding to elements which were collected by the garbage collector. Then reduce the matrix in order to keep it in echelon form.
INPUT:
threshold– integer orNone(default:None); a non-pivot column whose distance to the right is greater than the threshold is not erased but only marked for future deletion
EXAMPLES:
sage: R = ZpLF(2, label='delelts') sage: prec = R.precision() sage: x = R(1, 10) sage: prec Precision module on 1 object (label: delelts) sage: prec.precision_lattice() # needs sage.geometry.polyhedron [1024] sage: del x sage: prec Precision module on 1 object (label: delelts) sage: prec.precision_lattice() # needs sage.geometry.polyhedron [1024] sage: prec.del_elements() sage: prec Precision module on 0 objects (label: delelts) sage: prec.precision_lattice() # needs sage.geometry.polyhedron []
>>> from sage.all import * >>> R = ZpLF(Integer(2), label='delelts') >>> prec = R.precision() >>> x = R(Integer(1), Integer(10)) >>> prec Precision module on 1 object (label: delelts) >>> prec.precision_lattice() # needs sage.geometry.polyhedron [1024] >>> del x >>> prec Precision module on 1 object (label: delelts) >>> prec.precision_lattice() # needs sage.geometry.polyhedron [1024] >>> prec.del_elements() >>> prec Precision module on 0 objects (label: delelts) >>> prec.precision_lattice() # needs sage.geometry.polyhedron []
- dimension()[source]¶
Return the dimension of this precision module.
EXAMPLES:
In general, the dimension increases by 1 when a new element with a given precision is created:
sage: R = ZpLF(2, label='dimension') sage: prec = R.precision() sage: prec.dimension() 0 sage: x = R.random_element(prec=10) sage: prec.dimension() 1 sage: y = R.random_element(prec=10) sage: prec.dimension() 2
>>> from sage.all import * >>> R = ZpLF(Integer(2), label='dimension') >>> prec = R.precision() >>> prec.dimension() 0 >>> x = R.random_element(prec=Integer(10)) >>> prec.dimension() 1 >>> y = R.random_element(prec=Integer(10)) >>> prec.dimension() 2
However in general it does not increase while doing computations:
sage: u = x + y sage: v = x^2 + 3*y + x*y + y^3 sage: prec.dimension() 2
[Python]>>> from sage.all import * >>> u = x + y >>> v = x**Integer(2) + Integer(3)*y + x*y + y**Integer(3) >>> prec.dimension() 2
Of course, it may also decrease when a sufficient number of variables are collected:
sage: del x, y, u sage: prec.del_elements() sage: prec.dimension() 1 sage: del v sage: prec.del_elements() sage: prec.dimension() 0
>>> from sage.all import * >>> del x, y, u >>> prec.del_elements() >>> prec.dimension() 1 >>> del v >>> prec.del_elements() >>> prec.dimension() 0
- internal_prec()[source]¶
Return the relative precision at which computations is handled internally.
It is slightly greater than the actual precision and increases a bit (at a logarithmic rate) when new elements are created and/or computed.
EXAMPLES:
sage: R = ZpLF(5, prec=20, label='internal_prec') sage: prec = R.precision() sage: prec.internal_prec() 25 sage: L = [R.random_element() for _ in range(50)] sage: prec.internal_prec() 28
>>> from sage.all import * >>> R = ZpLF(Integer(5), prec=Integer(20), label='internal_prec') >>> prec = R.precision() >>> prec.internal_prec() 25 >>> L = [R.random_element() for _ in range(Integer(50))] >>> prec.internal_prec() 28
- is_lattice()[source]¶
Return
Trueif this precision module is a lattice (i.e. has maximal dimension).EXAMPLES:
sage: R = ZpLF(2, label='is_lattice') sage: prec = R.precision() sage: x = R(1, 10) sage: y = R(1, 5) sage: prec.is_lattice() True sage: u = x + y sage: prec.is_lattice() False
>>> from sage.all import * >>> R = ZpLF(Integer(2), label='is_lattice') >>> prec = R.precision() >>> x = R(Integer(1), Integer(10)) >>> y = R(Integer(1), Integer(5)) >>> prec.is_lattice() True >>> u = x + y >>> prec.is_lattice() False
See also
- precision_lattice(elements=None)[source]¶
Return a matrix representing the precision lattice on a subset of elements.
INPUT:
elements– list of elements orNone(default:None)
EXAMPLES:
sage: R = ZpLF(2, label='preclattice') sage: prec = R.precision() sage: x = R(1, 10); y = R(1, 5) sage: prec.precision_lattice() # needs sage.geometry.polyhedron [1024 0] [ 0 32] sage: u = x + y sage: v = x - y sage: prec.precision_lattice([u, v]) # needs sage.geometry.polyhedron [ 32 2016] [ 0 2048]
>>> from sage.all import * >>> R = ZpLF(Integer(2), label='preclattice') >>> prec = R.precision() >>> x = R(Integer(1), Integer(10)); y = R(Integer(1), Integer(5)) >>> prec.precision_lattice() # needs sage.geometry.polyhedron [1024 0] [ 0 32] >>> u = x + y >>> v = x - y >>> prec.precision_lattice([u, v]) # needs sage.geometry.polyhedron [ 32 2016] [ 0 2048]
If the precision module does not project to a lattice, an error is raised.
sage: prec.precision_lattice([x, y, u, v]) # needs sage.geometry.polyhedron Traceback (most recent call last): ... PrecisionError: the differential is not surjective
[Python]>>> from sage.all import * >>> prec.precision_lattice([x, y, u, v]) # needs sage.geometry.polyhedron Traceback (most recent call last): ... PrecisionError: the differential is not surjective
Here is another example with matrices:
sage: M = matrix(R, 2, 2, [R(3, 5), R(7, 5), R(1, 5), R(11, 1)]) # needs sage.modules sage: N = M^10 # needs sage.modules
>>> from sage.all import * >>> M = matrix(R, Integer(2), Integer(2), [R(Integer(3), Integer(5)), R(Integer(7), Integer(5)), R(Integer(1), Integer(5)), R(Integer(11), Integer(1))]) # needs sage.modules >>> N = M**Integer(10) # needs sage.modules
The next syntax provides as easy way to select an interesting subset of variables (the selected subset consists of the four entries of the matrix
N):sage: prec.precision_lattice(N) # needs sage.geometry.polyhedron sage.modules [ 2048 512 28160 230400] [ 0 2048 14336 258048] [ 0 0 65536 65536] [ 0 0 0 262144]
[Python]>>> from sage.all import * >>> prec.precision_lattice(N) # needs sage.geometry.polyhedron sage.modules [ 2048 512 28160 230400] [ 0 2048 14336 258048] [ 0 0 65536 65536] [ 0 0 0 262144]
- sage.rings.padics.lattice_precision.list_of_padics(elements)[source]¶
Convert a list of \(p\)-adic composed elements (such as polynomials, matrices) to a list of weak references of their \(p\)-adic coefficients.
This is a helper function for the method
precision_lattice().
- class sage.rings.padics.lattice_precision.pAdicLatticeElementWeakProxy(element, callback=None)[source]¶
Bases:
objectThe implementations of
DifferentialPrecisionGenerichold weak references topAdicLatticeElement. They are stored in dictionaries, e.g., a dictionary that maps an element to the corresponding column in the precision lattice matrix. However, weak references as implemented by Python are tricky to use as dictionary keys. Their equality depends on the equality of the element they point to (as long as that element is alive) and then on the equality byid. This means that statements such as:ref in D == ref in Dcould be false if the garbage collector kicks in between the two invocations. To prevent very subtle and hardly reproducible bugs, we wrap weak references in a proxy that gives every lattice element a unique increasing id and uses that id for comparisons.EXAMPLES:
Proxy elements exist only internally and are not usually exposed to the user:
sage: from sage.rings.padics.lattice_precision import pAdicLatticeElementWeakProxy sage: R = ZpLF(2, label='proxy') sage: p = R(2) sage: prec = R.precision() sage: proxy = prec._elements[0] sage: isinstance(proxy, pAdicLatticeElementWeakProxy) True
>>> from sage.all import * >>> from sage.rings.padics.lattice_precision import pAdicLatticeElementWeakProxy >>> R = ZpLF(Integer(2), label='proxy') >>> p = R(Integer(2)) >>> prec = R.precision() >>> proxy = prec._elements[Integer(0)] >>> isinstance(proxy, pAdicLatticeElementWeakProxy) True
- class sage.rings.padics.lattice_precision.pRational(p, x, exponent=0, valuation=None)[source]¶
Bases:
objectThis class implements rational numbers viewed as elements of
Qp. In particular, it provides additional methods which are specific to \(p\)-adics (as \(p\)-adic valuation).Only for internal use.
INPUT:
p– a prime numberx– a rational numberexponent– integer (default: 0)valuation– integer orNone(default:None); the \(p\)-adic valuation of this element
If not
None, this method trusts the given value to the attributevaluation.- list(prec)[source]¶
Return the list of the digits of this element (written in radix \(p\)) up to position
prec.The first zeros are omitted.
- reduce_relative(prec)[source]¶
Return this element reduced modulo
p^nwheren = prec + val(x).INPUT:
prec– nonnegative integer