]> gitweb.michael.orlitzky.com - sage.d.git/blob - mjo/matrix_vector.py
Add a note about the nonstandard name "Motzkin decomposition."
[sage.d.git] / mjo / matrix_vector.py
1 """
2 There is an explicit isomorphism between all finite-dimensional vector
3 spaces. In particular, there is an isomorphism between the m-by-n
4 matrices and `$R^(m \times n)$`. Since most vector operations are not
5 available on Sage matrices, we have to go back and forth between these
6 two vector spaces often.
7 """
8
9 from sage.all import *
10
11 def isomorphism(matrix_space):
12 """
13 Create isomorphism (i.e. the function) that converts elements
14 of a matrix space into those of the corresponding finite-dimensional
15 vector space.
16
17 INPUT:
18
19 - matrix_space: A finite-dimensional ``MatrixSpace`` object.
20
21 OUTPUT:
22
23 - (phi, phi_inverse): If ``matrix_space`` has dimension m*n, then
24 ``phi`` will map m-by-n matrices to R^(m*n).
25 The inverse mapping ``phi_inverse`` will go
26 the other way.
27
28 EXAMPLES:
29
30 sage: M = MatrixSpace(QQ,4,4)
31 sage: (p, p_inv) = isomorphism(M)
32 sage: m = M(range(0,16))
33 sage: p_inv(p(m)) == m
34 True
35
36 """
37 from sage.matrix.matrix_space import is_MatrixSpace
38 if not is_MatrixSpace(matrix_space):
39 raise TypeError('argument must be a matrix space')
40
41 base_ring = matrix_space.base_ring()
42 vector_space = VectorSpace(base_ring, matrix_space.dimension())
43
44 def phi(m):
45 return vector_space(m.list())
46
47 def phi_inverse(v):
48 return matrix_space(v.list())
49
50 return (phi, phi_inverse)
51
52
53
54 def matrix_of_transformation(T, V):
55 """
56 Compute the matrix of a linear transformation ``T``, `$T : V
57 \rightarrow V$` with domain/range ``V``. This essentially uses the
58 Riesz representation theorem to represent the entries of the matrix
59 of ``T`` in terms of inner products.
60
61 INPUT:
62
63 - ``T`` -- The linear transformation whose matrix we should
64 compute. This should be a callable function that
65 takes as its single argument an element of ``V``.
66
67 - ``V`` -- The vector or matrix space on which ``T`` is defined.
68
69 OUTPUT:
70
71 If the dimension of ``V`` is `$n$`, we return an `$n \times n$`
72 matrix that represents ``T`` with respect to the standard basis of
73 ``V``.
74
75 EXAMPLES:
76
77 The matrix of a transformation on a simple vector space should be
78 the expected matrix::
79
80 sage: V = VectorSpace(QQ, 3)
81 sage: def f(x):
82 ....: return 3*x
83 ....:
84 sage: matrix_of_transformation(f, V)
85 [3 0 0]
86 [0 3 0]
87 [0 0 3]
88
89 A more complicated example confirms that we get a matrix consistent
90 with our ``matrix_to_vector`` function::
91
92 sage: M = MatrixSpace(QQ,3,3)
93 sage: Q = M([[0,1,0],[1,0,0],[0,0,1]])
94 sage: def f(x):
95 ....: return Q*x*Q.inverse()
96 ....:
97 sage: F = matrix_of_transformation(f, M)
98 sage: F
99 [0 0 0 0 1 0 0 0 0]
100 [0 0 0 1 0 0 0 0 0]
101 [0 0 0 0 0 1 0 0 0]
102 [0 1 0 0 0 0 0 0 0]
103 [1 0 0 0 0 0 0 0 0]
104 [0 0 1 0 0 0 0 0 0]
105 [0 0 0 0 0 0 0 1 0]
106 [0 0 0 0 0 0 1 0 0]
107 [0 0 0 0 0 0 0 0 1]
108 sage: phi, phi_inv = isomorphism(M)
109 sage: X = M([[1,2,3],[4,5,6],[7,8,9]])
110 sage: F*phi(X)
111 (5, 4, 6, 2, 1, 3, 8, 7, 9)
112 sage: phi(f(X))
113 (5, 4, 6, 2, 1, 3, 8, 7, 9)
114 sage: F*phi(X) == phi(f(X))
115 True
116
117 """
118 n = V.dimension()
119 B = V.basis()
120
121 def inner_product(v, w):
122 # An inner product function that works for both matrices and
123 # vectors.
124 if callable(getattr(v, 'inner_product', None)):
125 return v.inner_product(w)
126 elif callable(getattr(v, 'matrix_space', None)):
127 # V must be a matrix space?
128 return (v*w.transpose()).trace()
129 else:
130 raise ValueError('inner_product only works on vectors and matrices')
131
132 def apply(L, x):
133 # A "call" that works for both matrices and functions.
134 if callable(getattr(L, 'matrix_space', None)):
135 # L is a matrix, and we need to use "multiply" to call it.
136 return L*x
137 else:
138 # If L isn't a matrix, try this. It works for python
139 # functions at least.
140 return L(x)
141
142 entries = []
143 for j in range(0,n):
144 for i in range(0,n):
145 entry = inner_product(apply(T,B[i]), B[j])
146 entries.append(entry)
147
148 # Construct the matrix space in which our return value will lie.
149 W = MatrixSpace(V.base_ring(), n, n)
150
151 # And make a matrix out of our list of entries.
152 A = W(entries)
153
154 return A