]> gitweb.michael.orlitzky.com - sage.d.git/blob - mjo/cone/symmetric_pd.py
mjo/cone/symmetric_pd.py: drop inverse_symmetric_pd().
[sage.d.git] / mjo / cone / symmetric_pd.py
1 r"""
2 The symmetric positive definite cone `$S^{n}_{++}$` is the cone
3 consisting of all symmetric positive-definite matrices (as a subset of
4 $\mathbb{R}^{n \times n}$`. It is the interior of the symmetric positive
5 SEMI-definite cone.
6 """
7
8 from sage.all import *
9 from mjo.cone.symmetric_psd import random_symmetric_psd
10
11 def is_symmetric_pd(A):
12 """
13 Determine whether or not the matrix ``A`` is symmetric
14 positive-definite.
15
16 INPUT:
17
18 - ``A`` - The matrix in question.
19
20 OUTPUT:
21
22 Either ``True`` if ``A`` is symmetric positive-definite, or
23 ``False`` otherwise.
24
25 SETUP::
26
27 sage: from mjo.cone.symmetric_pd import (is_symmetric_pd,
28 ....: random_symmetric_pd)
29
30 EXAMPLES:
31
32 The identity matrix is obviously symmetric and positive-definite::
33
34 sage: A = identity_matrix(ZZ, ZZ.random_element(10))
35 sage: is_symmetric_pd(A)
36 True
37
38 The following matrix is symmetric but not positive definite::
39
40 sage: A = matrix(ZZ, [[1, 2], [2, 1]])
41 sage: is_symmetric_pd(A)
42 False
43
44 This matrix isn't even symmetric::
45
46 sage: A = matrix(ZZ, [[1, 2], [3, 4]])
47 sage: is_symmetric_pd(A)
48 False
49
50 The trivial matrix in a trivial space is trivially symmetric and
51 positive-definite::
52
53 sage: A = matrix(QQ, 0,0)
54 sage: is_symmetric_pd(A)
55 True
56
57 The implementation of "is_positive_definite" in Sage leaves a bit to
58 be desired. This matrix is technically positive definite over the
59 real numbers, but isn't symmetric::
60
61 sage: A = matrix(RR,[[1,1],[-1,1]])
62 sage: A.is_positive_definite()
63 Traceback (most recent call last):
64 ...
65 ValueError: Could not see Real Field with 53 bits of precision as a
66 subring of the real or complex numbers
67 sage: is_symmetric_pd(A)
68 False
69
70 TESTS:
71
72 Every gram matrix is positive-definite, and we can sum two
73 positive-definite matrices (``A`` and its transpose) to get a new
74 positive-definite matrix that happens to be symmetric::
75
76 sage: set_random_seed()
77 sage: V = VectorSpace(QQ, ZZ.random_element(5))
78 sage: A = random_symmetric_pd(V)
79 sage: is_symmetric_pd(A)
80 True
81
82 """
83
84 if A.base_ring() == SR:
85 msg = 'The matrix ``A`` cannot be symbolic.'
86 raise ValueError.new(msg)
87
88 # First make sure that ``A`` is symmetric.
89 if not A.is_symmetric():
90 return False
91
92 # If ``A`` is symmetric, we only need to check that it is positive
93 # definite. For that we can consult its minimum eigenvalue, which
94 # should be greater than zero. Since ``A`` is symmetric, its
95 # eigenvalues are guaranteed to be real.
96 if A.is_zero():
97 # A is trivial... so trivially positive-definite.
98 return True
99 else:
100 return min(A.eigenvalues()) > 0
101
102
103 def random_symmetric_pd(V):
104 r"""
105 Generate a random symmetric positive-definite matrix over the
106 vector space ``V``. That is, the returned matrix will be a linear
107 transformation on ``V``, with the same base ring as ``V``.
108
109 (We take a very loose interpretation of "random," here.)
110
111 INPUT:
112
113 - ``V`` -- The vector space on which the returned matrix will act.
114
115 OUTPUT:
116
117 A random symmetric positive-definite matrix, i.e. a linear
118 transformation from ``V`` to itself.
119
120 ALGORITHM:
121
122 We request a full-rank positive-semidefinite matrix from the
123 :func:`mjo.cone.symmetric_psd.random_symmetric_psd` function.
124
125 SETUP::
126
127 sage: from mjo.cone.symmetric_pd import random_symmetric_pd
128
129 EXAMPLES:
130
131 Well, it doesn't crash at least::
132
133 sage: set_random_seed()
134 sage: V = VectorSpace(QQ, 2)
135 sage: A = random_symmetric_pd(V)
136 sage: A.matrix_space()
137 Full MatrixSpace of 2 by 2 dense matrices over Rational Field
138
139 """
140 # We accept_zero because the trivial matrix is (trivially)
141 # symmetric and positive-definite, but it's also "zero." The rank
142 # condition ensures that we don't get the zero matrix in a
143 # nontrivial space.
144 return random_symmetric_psd(V, rank=V.dimension())