rlm@2
|
1
|
rlm@2
|
2 (ns sicm.utils)
|
rlm@2
|
3
|
rlm@2
|
4 (in-ns 'sicm.utils)
|
rlm@2
|
5
|
rlm@2
|
6 ;; Let some objects have spin
|
rlm@2
|
7
|
rlm@2
|
8 (defprotocol Spinning
|
rlm@2
|
9 (up? [this])
|
rlm@2
|
10 (down? [this]))
|
rlm@2
|
11
|
rlm@2
|
12 (defn spin
|
rlm@2
|
13 "Returns the spin of the Spinning s, either :up or :down"
|
rlm@2
|
14 [#^Spinning s]
|
rlm@2
|
15 (cond (up? s) :up (down? s) :down))
|
rlm@2
|
16
|
rlm@2
|
17
|
rlm@2
|
18 ;; DEFINITION: A tuple is a sequence with spin
|
rlm@2
|
19
|
rlm@2
|
20 (deftype Tuple
|
rlm@2
|
21 [spin coll]
|
rlm@2
|
22
|
rlm@2
|
23 clojure.lang.Seqable
|
rlm@2
|
24 (seq [this] (seq (.coll this)))
|
rlm@2
|
25
|
rlm@2
|
26 clojure.lang.Counted
|
rlm@2
|
27 (count [this] (count (.coll this)))
|
rlm@2
|
28
|
rlm@2
|
29 Spinning
|
rlm@2
|
30 (up? [this] (= ::up (.spin this)))
|
rlm@2
|
31 (down? [this] (= ::down (.spin this))))
|
rlm@2
|
32
|
rlm@2
|
33 (defmethod print-method Tuple
|
rlm@2
|
34 [o w]
|
rlm@2
|
35 (print-simple
|
rlm@2
|
36 (if (up? o)
|
rlm@2
|
37 (str "u" (.coll o))
|
rlm@2
|
38 (str "d" (vec(.coll o))))
|
rlm@2
|
39 w))
|
rlm@2
|
40
|
rlm@2
|
41 (def tuple? #(= (type %) Tuple))
|
rlm@2
|
42
|
rlm@2
|
43 ;; CONSTRUCTORS
|
rlm@2
|
44
|
rlm@2
|
45 (defn up
|
rlm@2
|
46 "Create a new up-tuple containing the contents of coll."
|
rlm@2
|
47 [coll]
|
rlm@2
|
48 (Tuple. ::up coll))
|
rlm@2
|
49
|
rlm@2
|
50 (defn down
|
rlm@2
|
51 "Create a new down-tuple containing the contents of coll."
|
rlm@2
|
52 [coll]
|
rlm@2
|
53 (Tuple. ::down coll))
|
rlm@2
|
54
|
rlm@2
|
55 (defn same-spin
|
rlm@2
|
56 "Creates a tuple which has the same spin as tuple and which contains
|
rlm@2
|
57 the contents of coll."
|
rlm@2
|
58 [tuple coll]
|
rlm@2
|
59 (if (up? tuple)
|
rlm@2
|
60 (up coll)
|
rlm@2
|
61 (down coll)))
|
rlm@2
|
62
|
rlm@2
|
63 (defn opposite-spin
|
rlm@2
|
64 "Create a tuple which has opposite spin to tuple and which contains
|
rlm@2
|
65 the contents of coll."
|
rlm@2
|
66 [tuple coll]
|
rlm@2
|
67 (if (up? tuple)
|
rlm@2
|
68 (down coll)
|
rlm@2
|
69 (up coll)))
|
rlm@2
|
70 (in-ns 'sicm.utils)
|
rlm@2
|
71 (require 'incanter.core) ;; use incanter's fast matrices
|
rlm@2
|
72
|
rlm@2
|
73
|
rlm@2
|
74 (defn all-equal? [coll]
|
rlm@2
|
75 (if (empty? (rest coll)) true
|
rlm@2
|
76 (and (= (first coll) (second coll))
|
rlm@2
|
77 (recur (rest coll)))))
|
rlm@2
|
78
|
rlm@2
|
79
|
rlm@2
|
80 (defprotocol Matrix
|
rlm@2
|
81 (rows [matrix])
|
rlm@2
|
82 (cols [matrix])
|
rlm@2
|
83 (diagonal [matrix])
|
rlm@2
|
84 (trace [matrix])
|
rlm@2
|
85 (determinant [matrix])
|
rlm@2
|
86 (transpose [matrix])
|
rlm@2
|
87 (conjugate [matrix])
|
rlm@2
|
88 )
|
rlm@2
|
89
|
rlm@2
|
90 (extend-protocol Matrix incanter.Matrix
|
rlm@2
|
91 (rows [rs] (map down (apply map vector (apply map vector rs))))
|
rlm@2
|
92 (cols [rs] (map up (apply map vector rs)))
|
rlm@2
|
93 (diagonal [matrix] (incanter.core/diag matrix) )
|
rlm@2
|
94 (determinant [matrix] (incanter.core/det matrix))
|
rlm@2
|
95 (trace [matrix] (incanter.core/trace matrix))
|
rlm@2
|
96 (transpose [matrix] (incanter.core/trans matrix)))
|
rlm@2
|
97
|
rlm@2
|
98 (defn count-rows [matrix]
|
rlm@2
|
99 ((comp count rows) matrix))
|
rlm@2
|
100
|
rlm@2
|
101 (defn count-cols [matrix]
|
rlm@2
|
102 ((comp count cols) matrix))
|
rlm@2
|
103
|
rlm@2
|
104 (defn square? [matrix]
|
rlm@2
|
105 (= (count-rows matrix) (count-cols matrix)))
|
rlm@2
|
106
|
rlm@2
|
107 (defn identity-matrix
|
rlm@2
|
108 "Define a square matrix of size n-by-n with 1s along the diagonal and
|
rlm@2
|
109 0s everywhere else."
|
rlm@2
|
110 [n]
|
rlm@2
|
111 (incanter.core/identity-matrix n))
|
rlm@2
|
112
|
rlm@2
|
113
|
rlm@2
|
114 (defn matrix-by-rows
|
rlm@2
|
115 "Define a matrix by giving its rows."
|
rlm@2
|
116 [& rows]
|
rlm@2
|
117 (if
|
rlm@2
|
118 (not (all-equal? (map count rows)))
|
rlm@2
|
119 (throw (Exception. "All rows in a matrix must have the same number of elements."))
|
rlm@2
|
120 (incanter.core/matrix (vec rows))))
|
rlm@2
|
121
|
rlm@2
|
122 (defn matrix-by-cols
|
rlm@2
|
123 "Define a matrix by giving its columns"
|
rlm@2
|
124 [& cols]
|
rlm@2
|
125 (if (not (all-equal? (map count cols)))
|
rlm@2
|
126 (throw (Exception. "All columns in a matrix must have the same number of elements."))
|
rlm@2
|
127 (incanter.core/matrix (vec (apply map vector cols)))))
|
rlm@2
|
128
|
rlm@2
|
129 (defn identity-matrix
|
rlm@2
|
130 "Define a square matrix of size n-by-n with 1s along the diagonal and
|
rlm@2
|
131 0s everywhere else."
|
rlm@2
|
132 [n]
|
rlm@2
|
133 (incanter.core/identity-matrix n))
|
rlm@2
|
134
|
rlm@2
|
135 (in-ns 'sicm.utils)
|
rlm@2
|
136 (use 'clojure.contrib.generic.arithmetic
|
rlm@2
|
137 'clojure.contrib.generic.collection
|
rlm@2
|
138 'clojure.contrib.generic.functor
|
rlm@2
|
139 'clojure.contrib.generic.math-functions)
|
rlm@2
|
140
|
rlm@2
|
141 (defn numbers?
|
rlm@2
|
142 "Returns true if all arguments are numbers, else false."
|
rlm@2
|
143 [& xs]
|
rlm@2
|
144 (every? number? xs))
|
rlm@2
|
145
|
rlm@2
|
146 (defn tuple-surgery
|
rlm@2
|
147 "Applies the function f to the items of tuple and the additional
|
rlm@2
|
148 arguments, if any. Returns a Tuple of the same type as tuple."
|
rlm@2
|
149 [tuple f & xs]
|
rlm@2
|
150 ((if (up? tuple) up down)
|
rlm@2
|
151 (apply f (seq tuple) xs)))
|
rlm@2
|
152
|
rlm@2
|
153
|
rlm@2
|
154
|
rlm@2
|
155 ;;; CONTRACTION collapses two compatible tuples into a number.
|
rlm@2
|
156
|
rlm@2
|
157 (defn contractible?
|
rlm@2
|
158 "Returns true if the tuples a and b are compatible for contraction,
|
rlm@2
|
159 else false. Tuples are compatible if they have the same number of
|
rlm@2
|
160 components, they have opposite spins, and their elements are
|
rlm@2
|
161 pairwise-compatible."
|
rlm@2
|
162 [a b]
|
rlm@2
|
163 (and
|
rlm@2
|
164 (isa? (type a) Tuple)
|
rlm@2
|
165 (isa? (type b) Tuple)
|
rlm@2
|
166 (= (count a) (count b))
|
rlm@2
|
167 (not= (spin a) (spin b))
|
rlm@2
|
168
|
rlm@2
|
169 (not-any? false?
|
rlm@2
|
170 (map #(or
|
rlm@2
|
171 (numbers? %1 %2)
|
rlm@2
|
172 (contractible? %1 %2))
|
rlm@2
|
173 a b))))
|
rlm@2
|
174
|
rlm@2
|
175 (defn contract
|
rlm@2
|
176 "Contracts two tuples, returning the sum of the
|
rlm@2
|
177 products of the corresponding items. Contraction is recursive on
|
rlm@2
|
178 nested tuples."
|
rlm@2
|
179 [a b]
|
rlm@2
|
180 (if (not (contractible? a b))
|
rlm@2
|
181 (throw
|
rlm@2
|
182 (Exception. "Not compatible for contraction."))
|
rlm@2
|
183 (reduce +
|
rlm@2
|
184 (map
|
rlm@2
|
185 (fn [x y]
|
rlm@2
|
186 (if (numbers? x y)
|
rlm@2
|
187 (* x y)
|
rlm@2
|
188 (contract x y)))
|
rlm@2
|
189 a b))))
|
rlm@2
|
190
|
rlm@2
|
191
|
rlm@2
|
192
|
rlm@2
|
193
|
rlm@2
|
194
|
rlm@2
|
195 (defmethod conj Tuple
|
rlm@2
|
196 [tuple & xs]
|
rlm@2
|
197 (tuple-surgery tuple #(apply conj % xs)))
|
rlm@2
|
198
|
rlm@2
|
199 (defmethod fmap Tuple
|
rlm@2
|
200 [f tuple]
|
rlm@2
|
201 (tuple-surgery tuple (partial map f)))
|
rlm@2
|
202
|
rlm@2
|
203
|
rlm@2
|
204
|
rlm@2
|
205 ;; TODO: define Scalar, and add it to the hierarchy above Number and Complex
|
rlm@2
|
206
|
rlm@2
|
207
|
rlm@2
|
208 (defmethod * [Tuple Tuple] ; tuple*tuple
|
rlm@2
|
209 [a b]
|
rlm@2
|
210 (if (contractible? a b)
|
rlm@2
|
211 (contract a b)
|
rlm@2
|
212 (map (partial * a) b)))
|
rlm@2
|
213
|
rlm@2
|
214
|
rlm@2
|
215 (defmethod * [java.lang.Number Tuple] ;; scalar * tuple
|
rlm@2
|
216 [a x] (fmap (partial * a) x))
|
rlm@2
|
217
|
rlm@2
|
218 (defmethod * [Tuple java.lang.Number]
|
rlm@2
|
219 [x a] (* a x))
|
rlm@2
|
220
|
rlm@2
|
221 (defmethod * [java.lang.Number incanter.Matrix] ;; scalar * matrix
|
rlm@2
|
222 [x M] (incanter.core/mult x M))
|
rlm@2
|
223
|
rlm@2
|
224 (defmethod * [incanter.Matrix java.lang.Number]
|
rlm@2
|
225 [M x] (* x M))
|
rlm@2
|
226
|
rlm@2
|
227 (defmethod * [incanter.Matrix incanter.Matrix] ;; matrix * matrix
|
rlm@2
|
228 [M1 M2]
|
rlm@2
|
229 (incanter.core/mmult M1 M2))
|
rlm@2
|
230
|
rlm@2
|
231 (defmethod * [incanter.Matrix Tuple] ;; matrix * tuple
|
rlm@2
|
232 [M v]
|
rlm@2
|
233 (if (and (apply numbers? v) (up? v))
|
rlm@2
|
234 (* M (matrix-by-cols v))
|
rlm@2
|
235 (throw (Exception. "Currently, you can only multiply a matrix by a tuple of *numbers*"))
|
rlm@2
|
236 ))
|
rlm@2
|
237
|
rlm@2
|
238 (defmethod * [Tuple incanter.Matrix] ;; tuple * Matrix
|
rlm@2
|
239 [v M]
|
rlm@2
|
240 (if (and (apply numbers? v) (down? v))
|
rlm@2
|
241 (* (matrix-by-rows v) M)
|
rlm@2
|
242 (throw (Exception. "Currently, you can only multiply a matrix by a tuple of *numbers*"))
|
rlm@2
|
243 ))
|
rlm@2
|
244
|
rlm@2
|
245
|
rlm@2
|
246 (defmethod exp incanter.Matrix
|
rlm@2
|
247 [M]
|
rlm@2
|
248 (incanter.core/exp M))
|
rlm@2
|
249
|
rlm@2
|
250
|
rlm@2
|
251 (in-ns 'sicm.utils)
|
rlm@2
|
252 (use 'clojure.contrib.seq
|
rlm@2
|
253 'clojure.contrib.generic.arithmetic
|
rlm@2
|
254 'clojure.contrib.generic.collection
|
rlm@2
|
255 'clojure.contrib.generic.math-functions)
|
rlm@2
|
256
|
rlm@2
|
257 ;;∂
|
rlm@2
|
258
|
rlm@2
|
259 ;; DEFINITION : Differential Term
|
rlm@2
|
260
|
rlm@2
|
261 ;; A quantity with infinitesimal components, e.g. x, dxdy, 4dydz. The
|
rlm@2
|
262 ;; coefficient of the quantity is returned by the 'coefficient' method,
|
rlm@2
|
263 ;; while the sequence of differential parameters is returned by the
|
rlm@2
|
264 ;; method 'partials'.
|
rlm@2
|
265
|
rlm@2
|
266 ;; Instead of using (potentially ambiguous) letters to denote
|
rlm@2
|
267 ;; differential parameters (dx,dy,dz), we use integers. So, dxdz becomes [0 2].
|
rlm@2
|
268
|
rlm@2
|
269 ;; The coefficient can be any arithmetic object; the
|
rlm@2
|
270 ;; partials must be a nonrepeating sorted sequence of nonnegative
|
rlm@2
|
271 ;; integers.
|
rlm@2
|
272
|
rlm@2
|
273 (deftype DifferentialTerm [coefficient partials])
|
rlm@2
|
274
|
rlm@2
|
275 (defn differential-term
|
rlm@2
|
276 "Make a differential term from a coefficient and list of partials."
|
rlm@2
|
277 [coefficient partials]
|
rlm@2
|
278 (if (and (coll? partials) (every? #(and (integer? %) (not(neg? %))) partials))
|
rlm@2
|
279 (DifferentialTerm. coefficient (set partials))
|
rlm@2
|
280 (throw (java.lang.IllegalArgumentException. "Partials must be a collection of integers."))))
|
rlm@2
|
281
|
rlm@2
|
282
|
rlm@2
|
283 ;; DEFINITION : Differential Sequence
|
rlm@2
|
284 ;; A differential sequence is a sequence of differential terms, all with different partials.
|
rlm@2
|
285 ;; Internally, it is a map from the partials of each term to their coefficients.
|
rlm@2
|
286
|
rlm@2
|
287 (deftype DifferentialSeq
|
rlm@2
|
288 [terms]
|
rlm@2
|
289 ;;clojure.lang.IPersistentMap
|
rlm@2
|
290 clojure.lang.Associative
|
rlm@2
|
291 (assoc [this key val]
|
rlm@2
|
292 (DifferentialSeq.
|
rlm@2
|
293 (cons (differential-term val key) terms)))
|
rlm@2
|
294 (cons [this x]
|
rlm@2
|
295 (DifferentialSeq. (cons x terms)))
|
rlm@2
|
296 (containsKey [this key]
|
rlm@2
|
297 (not(nil? (find-first #(= (.partials %) key) terms))))
|
rlm@2
|
298 (count [this] (count (.terms this)))
|
rlm@2
|
299 (empty [this] (DifferentialSeq. []))
|
rlm@2
|
300 (entryAt [this key]
|
rlm@2
|
301 ((juxt #(.partials %) #(.coefficient %))
|
rlm@2
|
302 (find-first #(= (.partials %) key) terms)))
|
rlm@2
|
303 (seq [this] (seq (.terms this))))
|
rlm@2
|
304
|
rlm@2
|
305 (def differential? #(= (type %) DifferentialSeq))
|
rlm@2
|
306
|
rlm@2
|
307 (defn zeroth-order?
|
rlm@2
|
308 "Returns true if the differential sequence has at most a constant term."
|
rlm@2
|
309 [dseq]
|
rlm@2
|
310 (and
|
rlm@2
|
311 (differential? dseq)
|
rlm@2
|
312 (every?
|
rlm@2
|
313 #(= #{} %)
|
rlm@2
|
314 (keys (.terms dseq)))))
|
rlm@2
|
315
|
rlm@2
|
316 (defmethod fmap DifferentialSeq
|
rlm@2
|
317 [f dseq]
|
rlm@2
|
318 (DifferentialSeq.
|
rlm@2
|
319 (fmap f (.terms dseq))))
|
rlm@2
|
320
|
rlm@2
|
321
|
rlm@2
|
322
|
rlm@2
|
323
|
rlm@2
|
324 ;; BUILDING DIFFERENTIAL OBJECTS
|
rlm@2
|
325
|
rlm@2
|
326 (defn differential-seq
|
rlm@2
|
327 "Define a differential sequence by specifying an alternating
|
rlm@2
|
328 sequence of coefficients and lists of partials."
|
rlm@2
|
329 ([coefficient partials]
|
rlm@2
|
330 (DifferentialSeq. {(set partials) coefficient}))
|
rlm@2
|
331 ([coefficient partials & cps]
|
rlm@2
|
332 (if (odd? (count cps))
|
rlm@2
|
333 (throw (Exception. "differential-seq requires an even number of terms."))
|
rlm@2
|
334 (DifferentialSeq.
|
rlm@2
|
335 (reduce
|
rlm@2
|
336 #(assoc %1 (set (second %2)) (first %2))
|
rlm@2
|
337 {(set partials) coefficient}
|
rlm@2
|
338 (partition 2 cps))))))
|
rlm@2
|
339
|
rlm@2
|
340
|
rlm@2
|
341
|
rlm@2
|
342 (defn big-part
|
rlm@2
|
343 "Returns the part of the differential sequence that is finite,
|
rlm@2
|
344 i.e. not infinitely small. If the sequence is zeroth-order, returns
|
rlm@2
|
345 the coefficient of the zeroth-order term instead. "
|
rlm@2
|
346 [dseq]
|
rlm@2
|
347 (if (zeroth-order? dseq) (get (.terms dseq) #{})
|
rlm@2
|
348 (let [m (.terms dseq)
|
rlm@2
|
349 keys (sort-by count (keys m))
|
rlm@2
|
350 smallest-var (last (last keys))]
|
rlm@2
|
351 (DifferentialSeq.
|
rlm@2
|
352 (reduce
|
rlm@2
|
353 #(assoc %1 (first %2) (second %2))
|
rlm@2
|
354 {}
|
rlm@2
|
355 (remove #((first %) smallest-var) m))))))
|
rlm@2
|
356
|
rlm@2
|
357
|
rlm@2
|
358 (defn small-part
|
rlm@2
|
359 "Returns the part of the differential sequence that infinitely
|
rlm@2
|
360 small. If the sequence is zeroth-order, returns zero."
|
rlm@2
|
361 [dseq]
|
rlm@2
|
362 (if (zeroth-order? dseq) 0
|
rlm@2
|
363 (let [m (.terms dseq)
|
rlm@2
|
364 keys (sort-by count (keys m))
|
rlm@2
|
365 smallest-var (last (last keys))]
|
rlm@2
|
366 (DifferentialSeq.
|
rlm@2
|
367 (reduce
|
rlm@2
|
368 #(assoc %1 (first %2) (second %2)) {}
|
rlm@2
|
369 (filter #((first %) smallest-var) m))))))
|
rlm@2
|
370
|
rlm@2
|
371
|
rlm@2
|
372
|
rlm@2
|
373 (defn cartesian-product [set1 set2]
|
rlm@2
|
374 (reduce concat
|
rlm@2
|
375 (for [x set1]
|
rlm@2
|
376 (for [y set2]
|
rlm@2
|
377 [x y]))))
|
rlm@2
|
378
|
rlm@2
|
379 (defn nth-subset [n]
|
rlm@2
|
380 (if (zero? n) []
|
rlm@2
|
381 (let [lg2 #(/ (log %) (log 2))
|
rlm@2
|
382 k (int(java.lang.Math/floor (lg2 n)))
|
rlm@2
|
383 ]
|
rlm@2
|
384 (cons k
|
rlm@2
|
385 (nth-subset (- n (pow 2 k)))))))
|
rlm@2
|
386
|
rlm@2
|
387 (def all-partials
|
rlm@2
|
388 (lazy-seq (map nth-subset (range))))
|
rlm@2
|
389
|
rlm@2
|
390
|
rlm@2
|
391 (defn differential-multiply
|
rlm@2
|
392 "Multiply two differential sequences. The square of any differential
|
rlm@2
|
393 variable is zero since differential variables are infinitesimally
|
rlm@2
|
394 small."
|
rlm@2
|
395 [dseq1 dseq2]
|
rlm@2
|
396 (DifferentialSeq.
|
rlm@2
|
397 (reduce
|
rlm@2
|
398 (fn [m [[vars1 coeff1] [vars2 coeff2]]]
|
rlm@2
|
399 (if (not (empty? (clojure.set/intersection vars1 vars2)))
|
rlm@2
|
400 m
|
rlm@2
|
401 (assoc m (clojure.set/union vars1 vars2) (* coeff1 coeff2))))
|
rlm@2
|
402 {}
|
rlm@2
|
403 (cartesian-product (.terms dseq1) (.terms dseq2)))))
|
rlm@2
|
404
|
rlm@2
|
405
|
rlm@2
|
406
|
rlm@2
|
407 (defmethod * [DifferentialSeq DifferentialSeq]
|
rlm@2
|
408 [dseq1 dseq2]
|
rlm@2
|
409 (differential-multiply dseq1 dseq2))
|
rlm@2
|
410
|
rlm@2
|
411 (defmethod + [DifferentialSeq DifferentialSeq]
|
rlm@2
|
412 [dseq1 dseq2]
|
rlm@2
|
413 (DifferentialSeq.
|
rlm@2
|
414 (merge-with + (.terms dseq1) (.terms dseq2))))
|
rlm@2
|
415
|
rlm@2
|
416 (defmethod * [java.lang.Number DifferentialSeq]
|
rlm@2
|
417 [x dseq]
|
rlm@2
|
418 (fmap (partial * x) dseq))
|
rlm@2
|
419
|
rlm@2
|
420 (defmethod * [DifferentialSeq java.lang.Number]
|
rlm@2
|
421 [dseq x]
|
rlm@2
|
422 (fmap (partial * x) dseq))
|
rlm@2
|
423
|
rlm@2
|
424 (defmethod + [java.lang.Number DifferentialSeq]
|
rlm@2
|
425 [x dseq]
|
rlm@2
|
426 (+ (differential-seq x []) dseq))
|
rlm@2
|
427 (defmethod + [DifferentialSeq java.lang.Number]
|
rlm@2
|
428 [dseq x]
|
rlm@2
|
429 (+ dseq (differential-seq x [])))
|
rlm@2
|
430
|
rlm@2
|
431 (defmethod - DifferentialSeq
|
rlm@2
|
432 [x]
|
rlm@2
|
433 (fmap - x))
|
rlm@2
|
434
|
rlm@2
|
435
|
rlm@2
|
436 ;; DERIVATIVES
|
rlm@2
|
437
|
rlm@2
|
438
|
rlm@2
|
439
|
rlm@2
|
440 (defn linear-approximator
|
rlm@2
|
441 "Returns an operator that linearly approximates the given function."
|
rlm@2
|
442 ([f df|dx]
|
rlm@2
|
443 (fn [x]
|
rlm@2
|
444 (let [big-part (big-part x)
|
rlm@2
|
445 small-part (small-part x)]
|
rlm@2
|
446 ;; f(x+dx) ~= f(x) + f'(x)dx
|
rlm@2
|
447 (+ (f big-part)
|
rlm@2
|
448 (* (df|dx big-part) small-part)
|
rlm@2
|
449 ))))
|
rlm@2
|
450
|
rlm@2
|
451 ([f df|dx df|dy]
|
rlm@2
|
452 (fn [x y]
|
rlm@2
|
453 (let [X (big-part x)
|
rlm@2
|
454 Y (big-part y)
|
rlm@2
|
455 DX (small-part x)
|
rlm@2
|
456 DY (small-part y)]
|
rlm@2
|
457 (+ (f X Y)
|
rlm@2
|
458 (* DX (f df|dx X Y))
|
rlm@2
|
459 (* DY (f df|dy X Y)))))))
|
rlm@2
|
460
|
rlm@2
|
461
|
rlm@2
|
462
|
rlm@2
|
463
|
rlm@2
|
464
|
rlm@2
|
465 (defn D[f]
|
rlm@2
|
466 (fn[x] (f (+ x (differential-seq 1 [0] 1 [1] 1 [2])))))
|
rlm@2
|
467
|
rlm@2
|
468 (defn d[partials f]
|
rlm@2
|
469 (fn [x]
|
rlm@2
|
470 (get
|
rlm@2
|
471 (.terms ((D f)x))
|
rlm@2
|
472 (set partials)
|
rlm@2
|
473 0
|
rlm@2
|
474 )))
|
rlm@2
|
475
|
rlm@2
|
476 (defmethod exp DifferentialSeq [x]
|
rlm@2
|
477 ((linear-approximator exp exp) x))
|
rlm@2
|
478
|
rlm@2
|
479 (defmethod sin DifferentialSeq
|
rlm@2
|
480 [x]
|
rlm@2
|
481 ((linear-approximator sin cos) x))
|
rlm@2
|
482
|
rlm@2
|
483 (defmethod cos DifferentialSeq
|
rlm@2
|
484 [x]
|
rlm@2
|
485 ((linear-approximator cos #(- (sin %))) x))
|
rlm@2
|
486
|
rlm@2
|
487 (defmethod log DifferentialSeq
|
rlm@2
|
488 [x]
|
rlm@2
|
489 ((linear-approximator log (fn [x] (/ x)) ) x))
|
rlm@2
|
490
|
rlm@2
|
491 (defmethod / [DifferentialSeq DifferentialSeq]
|
rlm@2
|
492 [x y]
|
rlm@2
|
493 ((linear-approximator /
|
rlm@2
|
494 (fn [x y] (/ 1 y))
|
rlm@2
|
495 (fn [x y] (- (/ x (* y y)))))
|
rlm@2
|
496 x y))
|