r""" Generate random things. """ from sage.matrix.constructor import matrix from sage.rings.real_lazy import ComplexLazyField from sage.rings.all import ZZ def random_unitary_matrix(F,n): r""" Generate a random unitary matrix of size ``n`` with entries in the field ``F``. INPUT: - ``F`` -- a field; specifically, a subfield of the complex numbers having characteristic zero. - ``n`` -- integer; the size of the random matrix you want. OUTPUT: A random ``n``-by-``n`` unitary matrix with entries in ``F``. A ``ValueError`` is raised if ``F`` is not an appropriate field. REFERENCES: - Hans Liebeck and Anthony Osborne. The Generation of All Rational Orthogonal Matrices. The American Mathematical Monthly, Vol. 98, No. 2. (February, 1991), pp. 131-133. SETUP:: sage: from mjo.random import random_unitary_matrix TESTS:: sage: n = ZZ.random_element(10) sage: U = random_unitary_matrix(QQ,n) sage: U.is_unitary() True sage: U.base_ring() is QQ True :: sage: n = ZZ.random_element(10) sage: K = QuadraticField(-1,'i') sage: U = random_unitary_matrix(K,n) sage: U.is_unitary() True sage: U.base_ring() is K True """ if not F.is_field(): raise ValueError("F must be a field") elif not F.is_subring(ComplexLazyField()): raise ValueError("F must be a subfield of the complex numbers") elif not F.characteristic().is_zero(): raise ValueError("F must have characteristic zero") I = matrix.identity(F,n) A = matrix.random(F,n) S = A - A.conjugate_transpose() U = (S-I).inverse()*(S+I) D = matrix.identity(F,n) for i in range(n): if ZZ.random_element(2).is_zero(): D[i,i] *= F(-1) return D*U