From 47ffe4449b5e6a514818854eae67850bf81213f8 Mon Sep 17 00:00:00 2001 From: Noel Roemmele Date: Fri, 24 Jan 2025 00:30:01 -0700 Subject: [PATCH 1/5] 24801 Fixed error causing the function random_diagonalizable_matrix to only return a matrix over the rational field. --- src/sage/matrix/special.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/sage/matrix/special.py b/src/sage/matrix/special.py index dbb0214994e..f9ff9be8b0c 100644 --- a/src/sage/matrix/special.py +++ b/src/sage/matrix/special.py @@ -3126,7 +3126,7 @@ def random_diagonalizable_matrix(parent, eigenvalues=None, dimensions=None): ....: eigenvalues=[2+I, 2-I, 2], dimensions=[1,1,1]) Traceback (most recent call last): ... - TypeError: eigenvalues must be integers. + TypeError: eigenvalues must be elements of the corresponding ring. Diagonal matrices must be square. :: @@ -3177,6 +3177,11 @@ def random_diagonalizable_matrix(parent, eigenvalues=None, dimensions=None): ... ValueError: each eigenvalue must have a corresponding dimension and each dimension a corresponding eigenvalue. + The elements of the random matrix must be a member of the correct corresponding ring. :: + sage: K = GF(3) + sage: random_matrix(K, 3,3,algorithm="diagonalizable").parent() + Full MatrixSpace of 3 by 3 dense matrices over Finite Field of size 3 + .. TODO:: Modify the routine to allow for complex eigenvalues. @@ -3189,6 +3194,9 @@ def random_diagonalizable_matrix(parent, eigenvalues=None, dimensions=None): from sage.misc.prandom import randint size = parent.nrows() + ring = parent.base_ring() + if ring == QQ: + ring = ZZ if parent.nrows() != parent.ncols(): raise TypeError("a diagonalizable matrix must be square.") if eigenvalues is not None and dimensions is None: @@ -3199,7 +3207,7 @@ def random_diagonalizable_matrix(parent, eigenvalues=None, dimensions=None): values = [] # create a list with "size" number of entries for eigen_index in range(size): - eigenvalue = randint(-10, 10) + eigenvalue = ring(randint(-10, 10)) values.append(eigenvalue) values.sort() dimensions = [] @@ -3214,8 +3222,8 @@ def random_diagonalizable_matrix(parent, eigenvalues=None, dimensions=None): size_check = 0 for check in range(len(dimensions)): size_check = size_check + dimensions[check] - if not all(x in ZZ for x in eigenvalues): - raise TypeError("eigenvalues must be integers.") + if not all(x in ring for x in eigenvalues): + raise TypeError("eigenvalues must be elements of the corresponding ring.") if size != size_check: raise ValueError("the size of the matrix must equal the sum of the dimensions.") if min(dimensions) < 1: @@ -3227,7 +3235,7 @@ def random_diagonalizable_matrix(parent, eigenvalues=None, dimensions=None): dimensions = [x[0] for x in dimensions_sort] eigenvalues = [x[1] for x in dimensions_sort] # Create the matrix of eigenvalues on the diagonal. Use a lower limit and upper limit determined by the eigenvalue dimensions. - diagonal_matrix = matrix(QQ, size) + diagonal_matrix = matrix(ring, size) up_bound = 0 low_bound = 0 for row_index in range(len(dimensions)): @@ -3237,7 +3245,7 @@ def random_diagonalizable_matrix(parent, eigenvalues=None, dimensions=None): low_bound = low_bound+dimensions[row_index] # Create a matrix to hold each of the eigenvectors as its columns, begin with an identity matrix so that after row and column # operations the resulting matrix will be unimodular. - eigenvector_matrix = matrix(QQ, size, size, 1) + eigenvector_matrix = matrix(ring, size, size, 1) upper_limit = 0 lower_limit = 0 # run the routine over the necessary number of columns corresponding eigenvalue dimension. From 13d74a31b13471ceacc3a16b7206ca25e83339c5 Mon Sep 17 00:00:00 2001 From: Noel Roemmele Date: Fri, 24 Jan 2025 01:14:40 -0700 Subject: [PATCH 2/5] 24801 Updated documentation of random_diagonalizable_matrix. --- src/sage/matrix/special.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/sage/matrix/special.py b/src/sage/matrix/special.py index f9ff9be8b0c..8a486772bdb 100644 --- a/src/sage/matrix/special.py +++ b/src/sage/matrix/special.py @@ -3054,15 +3054,15 @@ def random_diagonalizable_matrix(parent, eigenvalues=None, dimensions=None): """ Create a random matrix that diagonalizes nicely. - To be used as a teaching tool. Return matrices have only real - eigenvalues. + To be used as a teaching tool. If the ring used is QQ then return matrices + have real eigenvalues. Otherwise eignevalues are elements of the ring. INPUT: If eigenvalues and dimensions are not specified in a list, they will be assigned randomly. - - ``parent`` -- the desired size of the square matrix + - ``parent`` -- the matrix space required - ``eigenvalues`` -- the list of desired eigenvalues (default=None) @@ -3071,9 +3071,10 @@ def random_diagonalizable_matrix(parent, eigenvalues=None, dimensions=None): OUTPUT: - A square, diagonalizable, matrix with only integer entries. The - eigenspaces of this matrix, if computed by hand, give basis - vectors with only integer entries. + A square, diagonalizable, matrix. If the ring used is QQ then we have + integer entries. Otherwise entries are elements of the ring. If the + ring used is QQ the eigenspaces of this matrix, if computed by hand, + give basis vectors with only integer entries. .. NOTE:: @@ -3120,7 +3121,7 @@ def random_diagonalizable_matrix(parent, eigenvalues=None, dimensions=None): TESTS: - Eigenvalues must all be integers. :: + Eigenvalues must all be elements of the ring. :: sage: random_matrix(QQ, 3, algorithm='diagonalizable', # needs sage.symbolic ....: eigenvalues=[2+I, 2-I, 2], dimensions=[1,1,1]) From 39e2465638c35d79ec81daf03bd05aa4b7306963 Mon Sep 17 00:00:00 2001 From: Noel Roemmele Date: Mon, 27 Jan 2025 17:42:21 -0700 Subject: [PATCH 3/5] Fix documentation of random_diagonalizable_matrix. Updated documentation of random_matrix. Removed redundant check to see if the base ring provided was teh rationals. Moved doctest from tests to examples. Use the matrix.identity function for the eigenvector_matrix instead. --- src/sage/matrix/special.py | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/sage/matrix/special.py b/src/sage/matrix/special.py index 8a486772bdb..11d5c563340 100644 --- a/src/sage/matrix/special.py +++ b/src/sage/matrix/special.py @@ -241,8 +241,11 @@ def random_matrix(ring, nrows, ncols=None, algorithm='randomize', implementation - ``'unimodular'`` -- creates a matrix of determinant 1 - - ``'diagonalizable'`` -- creates a diagonalizable matrix whose - eigenvectors, if computed by hand, will have only integer entries + - ``'diagonalizable'`` -- if the base ring is ``QQ`` creates a + diagonalizable matrix whose eigenvectors, if computed by hand, + will have only integer entries. See the documentation of + :meth:`~sage.matrix.special.random_diagonalizable_matrix` + for more information - ``implementation`` -- (``None`` or string or a matrix class) a possible implementation. See the documentation of the constructor of @@ -3054,15 +3057,16 @@ def random_diagonalizable_matrix(parent, eigenvalues=None, dimensions=None): """ Create a random matrix that diagonalizes nicely. - To be used as a teaching tool. If the ring used is QQ then return matrices - have real eigenvalues. Otherwise eignevalues are elements of the ring. + To be used as a teaching tool. The eigenvalues will be elements of the + base ring. If the base ring used is ``QQ`` then the returned matrix will + have integer eigenvalues. INPUT: If eigenvalues and dimensions are not specified in a list, they will be assigned randomly. - - ``parent`` -- the matrix space required + - ``parent`` -- the corresponding matrix space of the base ring - ``eigenvalues`` -- the list of desired eigenvalues (default=None) @@ -3071,10 +3075,10 @@ def random_diagonalizable_matrix(parent, eigenvalues=None, dimensions=None): OUTPUT: - A square, diagonalizable, matrix. If the ring used is QQ then we have - integer entries. Otherwise entries are elements of the ring. If the - ring used is QQ the eigenspaces of this matrix, if computed by hand, - give basis vectors with only integer entries. + A square, diagonalizable, matrix. Elements of the matrix are elements + of the base ring. If the ring used is ``QQ`` then we have integer entries. + If the base ring used is ``QQ`` the eigenspaces of this matrix, if computed + by hand, gives basis vectors with only integer entries. .. NOTE:: @@ -3119,6 +3123,12 @@ def random_diagonalizable_matrix(parent, eigenvalues=None, dimensions=None): sage: all(e in eigenvalues for e in eigenvalues2) True + Matrices over finite fields are also supported:: + + sage: K = GF(3) + sage: random_matrix(K, 3, 3, algorithm="diagonalizable").parent() + Full MatrixSpace of 3 by 3 dense matrices over Finite Field of size 3 + TESTS: Eigenvalues must all be elements of the ring. :: @@ -3178,11 +3188,6 @@ def random_diagonalizable_matrix(parent, eigenvalues=None, dimensions=None): ... ValueError: each eigenvalue must have a corresponding dimension and each dimension a corresponding eigenvalue. - The elements of the random matrix must be a member of the correct corresponding ring. :: - sage: K = GF(3) - sage: random_matrix(K, 3,3,algorithm="diagonalizable").parent() - Full MatrixSpace of 3 by 3 dense matrices over Finite Field of size 3 - .. TODO:: Modify the routine to allow for complex eigenvalues. @@ -3196,8 +3201,6 @@ def random_diagonalizable_matrix(parent, eigenvalues=None, dimensions=None): size = parent.nrows() ring = parent.base_ring() - if ring == QQ: - ring = ZZ if parent.nrows() != parent.ncols(): raise TypeError("a diagonalizable matrix must be square.") if eigenvalues is not None and dimensions is None: @@ -3246,7 +3249,7 @@ def random_diagonalizable_matrix(parent, eigenvalues=None, dimensions=None): low_bound = low_bound+dimensions[row_index] # Create a matrix to hold each of the eigenvectors as its columns, begin with an identity matrix so that after row and column # operations the resulting matrix will be unimodular. - eigenvector_matrix = matrix(ring, size, size, 1) + eigenvector_matrix = matrix.identity(ring, size, size) upper_limit = 0 lower_limit = 0 # run the routine over the necessary number of columns corresponding eigenvalue dimension. From ecfee63d1a7188774b18b99d937c4c3151b67b3a Mon Sep 17 00:00:00 2001 From: Noel Roemmele Date: Mon, 27 Jan 2025 20:32:19 -0700 Subject: [PATCH 4/5] Added changes recommened to the documentation by Dave Morris. Change the matrix.identity call also suggested by Dave Morris. --- src/sage/matrix/special.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/sage/matrix/special.py b/src/sage/matrix/special.py index 11d5c563340..ccb39b334c0 100644 --- a/src/sage/matrix/special.py +++ b/src/sage/matrix/special.py @@ -241,10 +241,10 @@ def random_matrix(ring, nrows, ncols=None, algorithm='randomize', implementation - ``'unimodular'`` -- creates a matrix of determinant 1 - - ``'diagonalizable'`` -- if the base ring is ``QQ`` creates a - diagonalizable matrix whose eigenvectors, if computed by hand, - will have only integer entries. See the documentation of - :meth:`~sage.matrix.special.random_diagonalizable_matrix` + - ``'diagonalizable'`` -- creates a diagonalizable matrix. if the + base ring is ``QQ`` creates a diagonalizable matrix whose eigenvectors, + if computed by hand, will have only integer entries. See the + documentation of :meth:`~sage.matrix.special.random_diagonalizable_matrix` for more information - ``implementation`` -- (``None`` or string or a matrix class) a possible @@ -3066,7 +3066,7 @@ def random_diagonalizable_matrix(parent, eigenvalues=None, dimensions=None): If eigenvalues and dimensions are not specified in a list, they will be assigned randomly. - - ``parent`` -- the corresponding matrix space of the base ring + - ``parent`` -- the desired parent of the square matrix (a matrix space) - ``eigenvalues`` -- the list of desired eigenvalues (default=None) @@ -3076,9 +3076,9 @@ def random_diagonalizable_matrix(parent, eigenvalues=None, dimensions=None): OUTPUT: A square, diagonalizable, matrix. Elements of the matrix are elements - of the base ring. If the ring used is ``QQ`` then we have integer entries. - If the base ring used is ``QQ`` the eigenspaces of this matrix, if computed - by hand, gives basis vectors with only integer entries. + of the base ring. If the ring used is ``QQ`` then we have integer entries, + and the eigenspaces of this matrix, if computed by hand, gives basis + vectors with only integer entries. .. NOTE:: @@ -3249,7 +3249,7 @@ def random_diagonalizable_matrix(parent, eigenvalues=None, dimensions=None): low_bound = low_bound+dimensions[row_index] # Create a matrix to hold each of the eigenvectors as its columns, begin with an identity matrix so that after row and column # operations the resulting matrix will be unimodular. - eigenvector_matrix = matrix.identity(ring, size, size) + eigenvector_matrix = matrix.identity(ring, size) upper_limit = 0 lower_limit = 0 # run the routine over the necessary number of columns corresponding eigenvalue dimension. From f998c1fc429646f5edd56fc98f22ffc27d94af64 Mon Sep 17 00:00:00 2001 From: Noel Roemmele Date: Wed, 29 Jan 2025 09:40:23 -0700 Subject: [PATCH 5/5] Added spaces that were forgotten to the documentation of the diagonalizable algorihtm of random_matrix. Added verification of diagonalizability to the doctest for a random diagonal matrix of GF(3). --- src/sage/matrix/special.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/sage/matrix/special.py b/src/sage/matrix/special.py index ccb39b334c0..851fb623ddd 100644 --- a/src/sage/matrix/special.py +++ b/src/sage/matrix/special.py @@ -242,10 +242,10 @@ def random_matrix(ring, nrows, ncols=None, algorithm='randomize', implementation - ``'unimodular'`` -- creates a matrix of determinant 1 - ``'diagonalizable'`` -- creates a diagonalizable matrix. if the - base ring is ``QQ`` creates a diagonalizable matrix whose eigenvectors, - if computed by hand, will have only integer entries. See the - documentation of :meth:`~sage.matrix.special.random_diagonalizable_matrix` - for more information + base ring is ``QQ`` creates a diagonalizable matrix whose eigenvectors, + if computed by hand, will have only integer entries. See the + documentation of :meth:`~sage.matrix.special.random_diagonalizable_matrix` + for more information - ``implementation`` -- (``None`` or string or a matrix class) a possible implementation. See the documentation of the constructor of @@ -3126,8 +3126,15 @@ def random_diagonalizable_matrix(parent, eigenvalues=None, dimensions=None): Matrices over finite fields are also supported:: sage: K = GF(3) - sage: random_matrix(K, 3, 3, algorithm="diagonalizable").parent() + sage: M = random_matrix(K, 3, 3, algorithm="diagonalizable") + sage: M.parent() Full MatrixSpace of 3 by 3 dense matrices over Finite Field of size 3 + sage: M.is_diagonalizable() + True + sage: M # random + [0 0 1] + [2 1 1] + [1 0 0] TESTS: