The 'algorithm' option to `random_matrix` is very useful for producing 
examples of matrices.

The algorithm='diagonalizable' option allows one to generate a 
diagonalizable matrix with prescribed eigenvalues with given algebraic 
multiplicities. For instance,

A = random_matrix(ZZ, 6, algorithm='diagonalizable', eigenvalues=(1, 2, 3), 
dimensions=(1, 2, 3))

produces a diagonalizable matrix A with eigenvalues {1, 2, 3} with 
corresponding geometric multiplicities {1, 2, 3}.

I think it would be useful to have a similar algorithm that produces a 
random "nice" matrix with prescribed eigenvalues, geometric multiplicities, 
and algebraic multiplicities.  The syntax would be something like

A = random_matrix(ZZ, algorithm='jordanizable', eigenvalues=(1, 2, 3), 
geo_mults=(1, 2, 3), alg_mults=(2, 3, 4))

This would produce a 9x9 nondiagonalizable matrix A whose eigenvalues are 
{1, 2, 3} with geometric multiplicities are {1, 2, 3}.

The following code accomplishes this.

from functools import partial
from sage.all import Partitions, PositiveIntegers, ZZ, jordan_block, 
matrix, random_matrix


def random_jordanizable(eigenvals, geo_mults, alg_mults=None, P_bound=5):
    if alg_mults is None:
        alg_mults = geo_mults
    if not len(eigenvals) == len(geo_mults) == len(alg_mults):
        raise ValueError('Each eval must have a geo and alg mult.')
    if any(map(lambda x: x not in PositiveIntegers(), geo_mults + 
alg_mults)):
        raise ValueError('Each mult must be a positive integer.')
    if any(map(lambda g, a: g > a, zip(geo_mults, alg_mults))):
        raise ValueError('Mults must satisfy geo_mult <= alg_mult.')
    n = sum(alg_mults)
    J = matrix([])
    for eigenval, geo_mult, alg_mult in zip(eigenvals, geo_mults, 
alg_mults):
        jordan_sector = partial(jordan_block, eigenval)
        block_sizes = Partitions(alg_mult, length=geo_mult).random_element()
        blocks = map(jordan_sector, block_sizes)
        J = reduce(lambda X, Y: X.block_sum(Y), [J] + blocks)
    P = random_matrix(ZZ, n, algorithm='unimodular', upper_bound=P_bound)
    return P*J*P.inverse()


I'm not sure how to go about trying to incorporate this into the 
random_matrix function, but this is at least a start.

-- 
You received this message because you are subscribed to the Google Groups 
"sage-devel" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sage-devel+unsubscr...@googlegroups.com.
To post to this group, send email to sage-devel@googlegroups.com.
Visit this group at https://groups.google.com/group/sage-devel.
For more options, visit https://groups.google.com/d/optout.

Reply via email to