comparison sicm/bk/utils.clj @ 2:b4de894a1e2e

initial import
author Robert McIntyre <rlm@mit.edu>
date Fri, 28 Oct 2011 00:03:05 -0700
parents
children
comparison
equal deleted inserted replaced
1:8d8278e09888 2:b4de894a1e2e
1
2 (ns sicm.utils)
3
4 ;***** GENERIC ARITHMETIC
5 (ns sicm.utils)
6 (in-ns 'sicm.utils)
7
8 (defprotocol Arithmetic
9 (zero [this])
10 (one [this]))
11
12
13 (extend-protocol Arithmetic
14 java.lang.Number
15 (zero [this] 0)
16 (one [this] 1))
17
18 (extend-protocol Arithmetic
19 clojure.lang.Seqable
20 (zero [this] (map zero this))
21 (one [this] (map one this)))
22
23
24 ;***** TUPLES AND MATRICES
25 (in-ns 'sicm.utils)
26
27 (defprotocol Spinning
28 (up? [this])
29 (down? [this]))
30
31 (defn spin
32 "Returns the spin of the Spinning s, either :up or :down"
33 [#^Spinning s]
34 (cond (up? s) :up (down? s) :down))
35
36
37 (deftype Tuple
38 [spin coll]
39 clojure.lang.Seqable
40 (seq [this] (seq (.coll this)))
41 clojure.lang.Counted
42 (count [this] (count (.coll this))))
43
44 (extend-type Tuple
45 Spinning
46 (up? [this] (= ::up (.spin this)))
47 (down? [this] (= ::down (.spin this))))
48
49 (defmethod print-method Tuple
50 [o w]
51 (print-simple (str (if (up? o) 'u 'd) (.coll o)) w))
52
53
54
55 (defn up
56 "Create a new up-tuple containing the contents of coll."
57 [coll]
58 (Tuple. ::up coll))
59
60 (defn down
61 "Create a new down-tuple containing the contents of coll."
62 [coll]
63 (Tuple. ::down coll))
64
65
66 (in-ns 'sicm.utils)
67
68 (defn numbers?
69 "Returns true if all arguments are numbers, else false."
70 [& xs]
71 (every? number? xs))
72
73 (defn contractible?
74 "Returns true if the tuples a and b are compatible for contraction,
75 else false. Tuples are compatible if they have the same number of
76 components, they have opposite spins, and their elements are
77 pairwise-compatible."
78 [a b]
79 (and
80 (isa? (type a) Tuple)
81 (isa? (type b) Tuple)
82 (= (count a) (count b))
83 (not= (spin a) (spin b))
84
85 (not-any? false?
86 (map #(or
87 (numbers? %1 %2)
88 (contractible? %1 %2))
89 a b))))
90
91
92
93 (defn contract
94 "Contracts two tuples, returning the sum of the
95 products of the corresponding items. Contraction is recursive on
96 nested tuples."
97 [a b]
98 (if (not (contractible? a b))
99 (throw
100 (Exception. "Not compatible for contraction."))
101 (reduce +
102 (map
103 (fn [x y]
104 (if (numbers? x y)
105 (* x y)
106 (contract x y)))
107 a b))))
108
109 ;***** MATRICES
110 (in-ns 'sicm.utils)
111 (require 'incanter.core) ;; use incanter's fast matrices
112
113 (defprotocol Matrix
114 (rows [this])
115 (cols [this])
116 (diagonal [this])
117 (trace [this])
118 (determinant [this]))
119
120 (extend-protocol Matrix
121 incanter.Matrix
122 (rows [this] (map down this)))
123
124
125
126
127 (defn count-rows [matrix]
128 ((comp count rows) matrix))
129
130 (defn count-cols [matrix]
131 ((comp count cols) matrix))
132
133
134 (defn matrix-by-rows
135 "Define a matrix by giving its rows."
136 [& rows]
137 (cond
138 (not (all-equal? (map count rows)))
139 (throw (Exception. "All rows in a matrix must have the same number of elements."))
140 :else
141 (reify Matrix
142 (rows [this] (map down rows))
143 (cols [this] (map up (apply map vector rows)))
144 (diagonal [this] (map-indexed (fn [i row] (nth row i) rows)))
145 (trace [this]
146 (if (not= (count-rows this) (count-cols this))
147 (throw (Exception.
148 "Cannot take the trace of a non-square matrix."))
149 (reduce + (diagonal this))))
150
151 (determinant [this]
152 (if (not= (count-rows this) (count-cols this))
153 (throw (Exception.
154 "Cannot take the determinant of a non-square matrix."))
155 (reduce * (diagonal this))))
156 )))
157
158
159 (defn matrix-by-cols
160 "Define a matrix by giving its columns."
161 [& cols]
162 (cond
163 (not (all-equal? (map count cols)))
164 (throw (Exception. "All columns in a matrix must have the same number of elements."))
165 :else
166 (reify Matrix
167 (cols [this] (map up cols))
168 (rows [this] (map down (apply map vector cols)))
169 (diagonal [this] (map-indexed (fn [i col] (nth col i) cols)))
170 (trace [this]
171 (if (not= (count-cols this) (count-rows this))
172 (throw (Exception.
173 "Cannot take the trace of a non-square matrix."))
174 (reduce + (diagonal this))))
175
176 (determinant [this]
177 (if (not= (count-cols this) (count-rows this))
178 (throw (Exception.
179 "Cannot take the determinant of a non-square matrix."))
180 (reduce * (map-indexed (fn [i col] (nth col i)) cols))))
181 )))
182
183 (extend-protocol Matrix Tuple
184 (rows [this] (if (down? this)
185 (list this)
186 (map (comp up vector) this)))
187
188 (cols [this] (if (up? this)
189 (list this)
190 (map (comp down vector) this))))
191
192 (defn matrix-multiply [A B]
193 (apply matrix-by-rows
194 (for [a (rows A)]
195 (for [b (cols B)]
196 (contract a b)))))