]> gitweb.michael.orlitzky.com - sage.d.git/blob - mjo/matrix_vector.py
eja: use from_vector() instead of relying on call magic in one spot.
[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 SETUP::
29
30 sage: from mjo.matrix_vector import isomorphism
31
32 EXAMPLES::
33
34 sage: M = MatrixSpace(QQ,4,4)
35 sage: (p, p_inv) = isomorphism(M)
36 sage: m = M(xrange(16))
37 sage: p_inv(p(m)) == m
38 True
39
40 """
41 from sage.matrix.matrix_space import is_MatrixSpace
42 if not is_MatrixSpace(matrix_space):
43 raise TypeError('argument must be a matrix space')
44
45 base_ring = matrix_space.base_ring()
46 vector_space = VectorSpace(base_ring, matrix_space.dimension())
47
48 def phi(m):
49 return vector_space(m.list())
50
51 def phi_inverse(v):
52 return matrix_space(v.list())
53
54 return (phi, phi_inverse)
55
56
57
58 def matrix_of_transformation(T, V):
59 """
60 Compute the matrix of a linear transformation ``T``, `$T : V
61 \rightarrow V$` with domain/range ``V``. This essentially uses the
62 Riesz representation theorem to represent the entries of the matrix
63 of ``T`` in terms of inner products.
64
65 INPUT:
66
67 - ``T`` -- The linear transformation whose matrix we should
68 compute. This should be a callable function that
69 takes as its single argument an element of ``V``.
70
71 - ``V`` -- The vector or matrix space on which ``T`` is defined.
72
73 OUTPUT:
74
75 If the dimension of ``V`` is `$n$`, we return an `$n \times n$`
76 matrix that represents ``T`` with respect to the standard basis of
77 ``V``.
78
79 SETUP::
80
81 sage: from mjo.matrix_vector import isomorphism, matrix_of_transformation
82
83 EXAMPLES:
84
85 The matrix of a transformation on a simple vector space should be
86 the expected matrix::
87
88 sage: V = VectorSpace(QQ, 3)
89 sage: def f(x):
90 ....: return 3*x
91 ....:
92 sage: matrix_of_transformation(f, V)
93 [3 0 0]
94 [0 3 0]
95 [0 0 3]
96
97 A more complicated example confirms that we get a matrix consistent
98 with our ``matrix_to_vector`` function::
99
100 sage: M = MatrixSpace(QQ,3,3)
101 sage: Q = M([[0,1,0],[1,0,0],[0,0,1]])
102 sage: def f(x):
103 ....: return Q*x*Q.inverse()
104 ....:
105 sage: F = matrix_of_transformation(f, M)
106 sage: F
107 [0 0 0 0 1 0 0 0 0]
108 [0 0 0 1 0 0 0 0 0]
109 [0 0 0 0 0 1 0 0 0]
110 [0 1 0 0 0 0 0 0 0]
111 [1 0 0 0 0 0 0 0 0]
112 [0 0 1 0 0 0 0 0 0]
113 [0 0 0 0 0 0 0 1 0]
114 [0 0 0 0 0 0 1 0 0]
115 [0 0 0 0 0 0 0 0 1]
116 sage: phi, phi_inv = isomorphism(M)
117 sage: X = M([[1,2,3],[4,5,6],[7,8,9]])
118 sage: F*phi(X)
119 (5, 4, 6, 2, 1, 3, 8, 7, 9)
120 sage: phi(f(X))
121 (5, 4, 6, 2, 1, 3, 8, 7, 9)
122 sage: F*phi(X) == phi(f(X))
123 True
124
125 """
126 n = V.dimension()
127 B = list(V.basis())
128
129 def inner_product(v, w):
130 # An inner product function that works for both matrices and
131 # vectors.
132 if callable(getattr(v, 'inner_product', None)):
133 return v.inner_product(w)
134 elif callable(getattr(v, 'matrix_space', None)):
135 # V must be a matrix space?
136 return (v*w.transpose()).trace()
137 else:
138 raise ValueError('inner_product only works on vectors and matrices')
139
140 def apply(L, x):
141 # A "call" that works for both matrices and functions.
142 if callable(getattr(L, 'matrix_space', None)):
143 # L is a matrix, and we need to use "multiply" to call it.
144 return L*x
145 else:
146 # If L isn't a matrix, try this. It works for python
147 # functions at least.
148 return L(x)
149
150 entries = []
151 for j in xrange(n):
152 for i in xrange(n):
153 entry = inner_product(apply(T,B[i]), B[j])
154 entries.append(entry)
155
156 # Construct the matrix space in which our return value will lie.
157 W = MatrixSpace(V.base_ring(), n, n)
158
159 # And make a matrix out of our list of entries.
160 A = W(entries)
161
162 return A