-
-
Notifications
You must be signed in to change notification settings - Fork 641
Add functions for computation of krylov rank profile and linear interpolation basis #40508
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
base: develop
Are you sure you want to change the base?
Conversation
…dn_dense, add aliases for pivots and pivot_rows, optimisation for krylov_rank_profile by minimising index conversion and full permutation calculation
…ial creation in basis calculation
Some benchmarks are provided here (done in a branch with #40423 and #40435 merged):
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a few comments on the doctests to start with.
@@ -19103,6 +19119,499 @@ cdef class Matrix(Matrix1): | |||
U.rescale_col(n - 1, -1) | |||
return U | |||
|
|||
def krylov_rank_profile(self, J, degree=None, shift=None, output_pairs=False): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it really a method we want to expose to the user? (It's really a question, I don't know.)
If you choose to keep it, you probably need to explain briefly what it is and why it is important (with references).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It gives some information (monomial basis, vector space dimension...) but this information can also be found from the output of the main function (currently called linear interpolation basis). And calling that main function should rarely be slower than calling this one, so my vote would go against exposing it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, I would suggest permuting the order of arguments: J, shift, degree, output_pairs
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It took 1 hour to change my mind :-) . This function is computing not only the row rank profile but also the corresponding rows of the Krylov matrix (output pivot_matrix
). As such, it is computing what is sometimes referred to as a Krylov basis for the row vectors of self
and the multiplication by J
, with order of vectors defined by the shift. This is instrumental in computations for various matrix transformations and properties (see e.g. Chapter 9 of this PhD thesis and this paper ). We could keep this available to the user, but name it more explicitly such as krylov_basis
, and possibly slightly rework the interface (input/output/options).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds like a good solution!
@@ -19103,6 +19103,509 @@ cdef class Matrix(Matrix1): | |||
U.rescale_col(n - 1, -1) | |||
return U | |||
|
|||
def krylov_rank_profile(self, J, degree=None, shift=None, output_pairs=False): | |||
r""" | |||
Compute the rank profile (row and column) of the striped Krylov matrix |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"striped Krylov matrix" is not so classical. Suggestion:
"the striped Krylov matrix built from the rows of self
and the matrix J
, with rows ordered according to a priority defined by shift
. See [Beckermann and Labahn, 2000, https://doi.org/10.1137/S0895479897326912] and [Jeannerod, Neiger, Schost, Villard, 2017, https://doi.org/10.1016/j.jsc.2016.11.015]."
Note that we might add these to the SageMath list of references that go into the documentation, but I don't know if that is necessary here (assuming this becomes an auxiliary function hidden from the user).
|
||
INPUT: | ||
|
||
- ``J`` -- square matrix used in the Krylov construction. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: using (here and everywhere) a more transparent name for this matrix J
. E.g. M
or mulmat
, shorthand for "multiplication matrix".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I vote for M
.
|
||
- ``J`` -- square matrix used in the Krylov construction. | ||
- ``degree`` -- maximum power of J in Krylov matrix. | ||
- ``shift`` -- list of integers (optional): priority row shift. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indicate that the number of integers should equal the number of rows of self
.
INPUT: | ||
|
||
- ``J`` -- square matrix used in the Krylov construction. | ||
- ``degree`` -- maximum power of J in Krylov matrix. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indicate that this is optional, and if not provided, a suitable maximum degree will be taken, namely the number of columns c
of J
(higher powers of J
are known not to be needed since there exists an annihilating polynomial of degree c
for J
).
- ``J`` -- square matrix used in the Krylov construction. | ||
- ``degree`` -- maximum power of J in Krylov matrix. | ||
- ``shift`` -- list of integers (optional): priority row shift. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add some note about the input output_pairs
. Since in the main function this optional argument is set to True
, maybe this could be the default? Or, maybe better (?), the optional argument could be output_row_indices
, set to False by default (which would correspond to the current output_pairs=True), and when set to True this would correspond to the current output_pairs=False.
I've removed the modifications to
Both return
The first row with a non-zero entry in the first column is index 0. So
The first remaining row with a non-zero entry in the second column is index 3. So
The first remaining row with a non-zero entry in the third column is index 2. So
|
``self.nrows()`` in K[x] that form a basis for solutions to the | ||
equation ``p_1 e_1 + ... + p_n e_n = 0``. | ||
|
||
See https://arxiv.org/abs/1512.03503 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here this reference is maybe not the most relevant, however it could be cited for the algorithm itself, or for the specific definition of striped Krylov matrix with a priority given by shift (the number of the relevant section should be indicated). See this about the ALGORITHM block and also about adding references to the master bibliography file.
For, more generally, the relevant notion of basis of such modules I would rather cite Kailath's book Linear Systems, Section 6.7 (the book is already in Sage's biblio as [Kai1980]) and also Section 16.6 of the book Algebraic Complexity Theory (which is not yet in Sage's biblio).
|
||
INPUT: | ||
|
||
- ``J`` -- square matrix for Krylov construction. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same remark as above concerning notation (changing J
into e.g. M
or mulmat
).
|
||
return tuple(row_profile_K), M, col_profile | ||
|
||
def linear_interpolation_basis(self, J, var_name, degree=None, shift=None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This name comes from the reference that was used for the algorithm, where interpolation came naturally from its main contribution (which is on a particular case of this problem). Here, in the general case, it is not very clear why this should be seen as an interpolation problem. The method name could be for example krylov_kernel_basis
(open to discussion!).
In terms of efficiency, since this has been dropped (it should be if it is not correct, thanks for checking carefully), I assume this means that an additional RREF is computed on the transpose? LinBox/FFLAS-FFPACK does incorporate echelonization procedures which preserve the row rank profile as well as the column rank profile. We could try to include this in Sage. This would avoid wasting a factor of 2 by calling the echelonization twice when both are needed. Would you mind opening an issue for this? (and you could link to your above message or copy it there, to show the observation that a trivial deduction from P does not always work) |
- ``row_profile``: list of the first r row indices in the striped | ||
Krylov matrix ``K`` corresponding to | ||
independent rows. If ``output_pairs`` is True, | ||
then the output is the list of pairs (c_i, d_i) | ||
where c_i is the corresponding row in the | ||
original matrix and d_i the corresponding power | ||
of ``J``. | ||
- ``pivot_matrix``: the submatrix of ``K`` given by ``row_profile`` | ||
- ``column_profile``: the first r independent column indices in | ||
``pivot_matrix`` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not 100% sure but I think that indentation is still incorrect.
The classical format is
A tuple:
- ``row_profile``: list of the first r row indices in the striped
Krylov matrix ``K`` corresponding to independants rows.
[...]
- ``pivot_matrix``: the submatrix of ``K`` given by ``row_profile``
- ``column_profile``: the first r independent column indices in
``pivot_matrix``
[0 0 1] | ||
[0 0 0] | ||
sage: degree = 3 | ||
sage: striped_krylov_matrix = matrix.block([[E*J^i] for i in range(degree+1)],subdivide=False) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe, it could be a good idea to have a method krylov_matrix
for constructing this matrix.
I think it makes sense if we also have krylov_basis
and krylov_kernel_basis
.
By the way, what "striped" means here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After inspection (web search), "striped" is used when describing matrices with particular structures, but usually that revolve around constant (anti)diagonals including some that are zero. Which is not really the case here.
Here the term was taken from a less common occurrence: it was used in Beckermann & Labahn (SIAM, 2000) to describe the matrices we have here, and just in a few other documents that mention this B&L's work. "Block Krylov" would probably have been a more classical terminology (maybe this was not chosen due to confusion with the existing block-Krylov / block-Wiedemann method?).
In any case, I think we could avoid this unclear terminology and just talk about a Krylov matrix (it is just a usual Krylov matrix, with several initial vectors; and the presence of several vectors gives rise to several row orderings that we describe through the shift).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 for a method krylov_matrix
which builds the matrix. It should take some bound as input: it could be the maximum exponent of the multiplication matrix that is used, this for each of the input rows of self
.
This PR implements the following functions, adds aliases
row_rank_profile
forpivot_rows
andcolumn_rank_profile
forpivots
, and caches the row rank profile that is calculated as part oflinbox_echelonize
inmatrix_modn_dense_template.pxi
.Given a$\mathbb{K}[x]$ -module $V$ with multiplication matrix $J \in \mathbb{K}^{\sigma\times\sigma}$ , a set of $m$ elements of $V$ expressed in matrix form $E \in \mathbb{K}^{m\times\sigma}$ , a priority shift $s = (s_1,\dots,s_m) \in \mathbb{Z}^m$ , and an upper bound $d$ on the degree of the minimal polynomial of $J$ , $P(E_{c,*} J^d) = s_c + d$ :
krylov_rank_profile
finds the lexicographical first maximal linearly independent set of rows from the matrix, with rows ordered according to the priorityIt returns the positions of these rows in the permuted matrix, the submatrix formed by these rows, and the lexicographical first maximal linearly independent set of columns of the submatrix.
Given the same arguments and a variable name,$s$ -minimal interpolation basis for $(E,J)$ , i.e. an $s$ -reduced basis for the space of polynomials satisfying $p_1 E_{1,*}+\dots+p_mE_{m,*}=0$ .
linear_interpolation_basis
calculates an📝 Checklist