/
matrix.jl
250 lines (203 loc) · 4.63 KB
/
matrix.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
"""
sympy_matrix_to_sj(spmat::[ a sympy matrix object ])
convert spmat to a Symata `List` of `Lists`.
"""
function sympy_matrix_to_sj(spmat)
jlist = pytosj(spmat[:tolist]())
for i in 1:length(jlist)
jlist[i] = pytosj(jlist[i])
end
mat = newargs()
(nx,ny) = size(jlist)
for i in 1:nx
push!(mat, MList(jlist[i,:]))
end
MList(mat)
end
### Inverse
@mkapprule Inverse :nargs => 1
## FIXME: something changed somewhere.
## so that sympy_matrix_to_sj(pyres) does not return a Symata expression. Maybe in PyCall ?
@sjdoc Inverse """
Inverse(m)
compute the matrix inverse of `m`.
"""
@doap function Inverse(expr)
arg1 = _sjtopy(mx[1])
mat = sympy[:Matrix](arg1)
pyres = mat[:inv]()
sympy_matrix_to_sj(pyres)
end
### Dot
@mkapprule Dot
@sjdoc Dot """
Dot(a,b)
a ⋅ b
⋅(a,b)
Compute the matrix product or inner product for `a` and `b` matrices or vectors.
The complex conjugate is applied to neither `a` nor `b`.
The infix operator `⋅` can usually be entered by typing `\\cdot` followed by `TAB`
"""
@doap function Dot(u::ListT,v::ListT)
symlength(u) == 0 || symlength(v) == 0 && return mx
vv = vectorq(v)
if vectorq(u) && vv
# Using MPlus is much faster than mplus. This means mplus should be implemented differently
return MPlus( [mmul(x[1], x[2]) for x in zip(margs(u), (margs(v)))]...)
# return mplus( [mmul(x[1], x[2]) for x in zip(margs(u), (margs(v)))]...)
end
mqu = matrixq(u)
if mqu && vv && symlength(u[1]) == symlength(v)
return matmulvec(u,v)
end
mqv = matrixq(v)
if mqu && mqv
(nu,mu) = matrixdims(u)
(nv,mv) = matrixdims(v)
mu != nv && return mx
return matmulmat(u,v)
end
mx
end
"""
matmulvec(m,v)
Matrix multiply matrix `m` and vector `v`.
"""
function matmulvec(m,v)
n1 = symlength(m)
n2 = symlength(m[1])
a = newargs(n1)
for i=1:n1
c = 0
r = m[i]
for j=1:n2
c += mmul(r[j], v[j])
end
a[i] = c
end
MList(a)
end
function matmulmat(a,b)
(ma,n) = matrixdims(a)
(n,mb) = matrixdims(b)
c = zeromatrix(ma,mb)
for i in 1:ma
for j in 1:mb
acc = 0 # much faster
for k in 1:n
acc += a[i,k]*b[k,j]
end
c[i,j] = acc
end
end
c
end
### IdentityMatrix
@mkapprule IdentityMatrix
@sjdoc IdentityMatrix """
IdentityMatrix(n)
return the `n x n` identity matrix.
"""
@doap function IdentityMatrix(n::Integer)
r = newargs(n)
for i=1:n
c = newargs(n)
fill!(c,0)
r[i] = MList(c)
end
mr = MList(r)
for i=1:n
mr[i,i] = 1
end
mr
end
### DiagonalMatrix
### ZeroMatrix
@mkapprule ZeroMatrix
@sjdoc ZeroMatrix """
ZeroMatrix(n1,n2)
return an `n1 x n2` matrix of zeros.
"""
@doap ZeroMatrix(n1,n2) = zeromatrix(n1,n2)
function zeromatrix(n2,n1)
m = newargs(n2)
for i=1:n2
r = newargs(n1)
fill!(r,0)
m[i] = MList(r)
end
MList(m)
end
### Transpose
@mkapprule Transpose
@sjdoc Transpose """
Transpose(m)
return the transpose of the matrix `m`.
"""
@doap function Transpose(x::Mxpr{:List})
matrixq(x) || return mx
a = margs(x)
n = length(a)
m = symlength(a[1])
a0 = newargs(m)
for i in 1:m
a1 = newargs(n)
for j in 1:n
# a1[j] = margs(margs(x)[j])[i]
a1[j] = x[j,i] # is there a more efficient way ?
end
a0[i] = MList(a1)
end
MList(a0)
end
### Outer
### Tr
# assumes we have a matrix
matrixdims(m::ListT) = (length(m), length(m[1]))
@mkapprule Tr
@sjdoc Tr """
Tr(m)
Compute the trace of matrix `m`.
"""
@doap function Tr(m::ListT)
matrixq(m) || return mx
n = min(matrixdims(m)...)
a = newargs(n)
for i=1:n
a[i] = m[i,i]
end
MPlus(a)
end
### Eigenvalues
@mkapprule Eigenvalues :nargs => 1
@sjdoc Eigenvalues """
Eigenvalues(m)
Compute the eigenvalues of matrix `m`.
"""
@doap function Eigenvalues(expr)
arg1 = _sjtopy(mx[1])
mat = sympy[:Matrix](arg1)
pyres = mat[:eigenvals]()
eigdict = pyres |> pytosj
a = newargs()
for (k,v) in eigdict
push!(a, MList(k,v))
end
MList(a)
end
### Eigenvectors
@mkapprule Eigenvectors :nargs => 1
@sjdoc Eigenvectors """
Eigenvectors(m)
Compute the eigenvectors of matrix `m`.
"""
@doap function Eigenvectors(expr)
arg1 = _sjtopy(mx[1])
mat = sympy[:Matrix](arg1)
pyres = mat[:eigenvects]()
args = newargs()
for x in pyres
push!(args, sympy_matrix_to_sj(x[3][1]))
end
MList(args)
end