d@33
|
1 ;; CSR's gamma functions. I don't really know what's happening here,
|
d@33
|
2 ;; but it seems to work... Called from within harmonic_analysis.lisp
|
d@33
|
3
|
d@33
|
4 (in-package #:amuse-harmony)
|
d@33
|
5
|
d@33
|
6 (let ((p (make-array
|
d@33
|
7 9 :element-type 'double-float
|
d@33
|
8 :initial-contents ; cf. Lanczos' Approximation on Wikipedia.
|
d@33
|
9 '(0.99999999999980993d0 676.5203681218851d0 -1259.1392167224028d0
|
d@33
|
10 771.32342877765313d0 -176.61502916214059d0 12.507343278686905d0
|
d@33
|
11 -0.13857109526572012d0 9.9843695780195716d-6
|
d@33
|
12 1.5056327351493116d-7)))
|
d@33
|
13 (c (make-array 8 :element-type 'double-float
|
d@33
|
14 :initial-contents
|
d@33
|
15 (mapcar (lambda (x) (float x 1d0))
|
d@33
|
16 '(1/12 -1/360 1/1260 -1/1680 1/1188 -691/360360
|
d@33
|
17 1/156 -3617/122400)))))
|
d@33
|
18 (defun gamma/posreal (x)
|
d@33
|
19 (declare (type (double-float (0d0)) x))
|
d@33
|
20 (locally
|
d@33
|
21 (declare (optimize speed))
|
d@33
|
22 (labels ((corr (x)
|
d@33
|
23 (declare (type double-float x))
|
d@33
|
24 (let ((y (/ 1.0 (* x x))))
|
d@33
|
25 (do* ((i 7 (1- i))
|
d@33
|
26 (r (aref c i) (+ (* r y) (aref c i))))
|
d@33
|
27 ((<= i 0) (the (double-float (0d0)) (exp (/ r x))))
|
d@33
|
28 (declare (type double-float r)))))
|
d@33
|
29 (lngamma/lanczos (x)
|
d@33
|
30 (declare (type (double-float 0.5d0) x))
|
d@33
|
31 (let ((x (1- x)))
|
d@33
|
32 (do* ((i 0 (1+ i))
|
d@33
|
33 (ag (aref p 0) (+ ag (/ (aref p i) (+ x i)))))
|
d@33
|
34 ((>= i 8)
|
d@33
|
35 (let ((term1 (* (+ x 0.5d0) (log (/ (+ x 7.5d0) #.(exp 1d0)))))
|
d@33
|
36 (term2 (+ #.(log (sqrt (* 2 pi))) (log ag))))
|
d@33
|
37 (+ term1 (- term2 7.0d0))))
|
d@33
|
38 (declare (type (double-float (0d0)) ag)))))
|
d@33
|
39 (gamma/xgthalf (x)
|
d@33
|
40 (declare (type (double-float 0.5d0) x))
|
d@33
|
41 (cond
|
d@33
|
42 ((= x 0.5d0) 1.77245385090551602729817d0)
|
d@33
|
43 ((< x 5d0) (exp (lngamma/lanczos x)))
|
d@33
|
44 ;; the GNU scientific library suggests a third branch
|
d@33
|
45 ;; for x < 10, but in fact for our purposes the
|
d@33
|
46 ;; errors are under control.
|
d@33
|
47 (t
|
d@33
|
48 (let* ((p (expt x (* x 0.5)))
|
d@33
|
49 (e (exp (- x)))
|
d@33
|
50 (q (* (* p e) p))
|
d@33
|
51 (pre (* #.(sqrt 2) #.(sqrt pi) q (/ (sqrt x)))))
|
d@33
|
52 (* pre (corr x)))))))
|
d@33
|
53 (if (> x 0.5d0)
|
d@33
|
54 (gamma/xgthalf x)
|
d@33
|
55 (let ((g (gamma/xgthalf (- 1d0 x))))
|
d@33
|
56 (declare (type double-float g))
|
d@33
|
57 (/ pi g (sin (* pi x)))))))))
|
d@33
|
58
|
d@33
|
59 (defun beta (alpha)
|
d@33
|
60 (let ((sum 0)
|
d@33
|
61 (product 1))
|
d@33
|
62 (dotimes (i (length alpha) (/ product (gamma/posreal (float sum 1d0))))
|
d@33
|
63 (let ((alpha_i (aref alpha i)))
|
d@33
|
64 (setq product (* product (gamma/posreal (float alpha_i 1d0))))
|
d@33
|
65 (incf sum alpha_i)))))
|
d@33
|
66
|
d@33
|
67 ;; this is p(d|c_i), where the chord model is represented as a
|
d@33
|
68 ;; Dirichlet distribution with parameters alpha_i
|
d@33
|
69 #+nil
|
d@33
|
70 (defun likelihood (observations alpha)
|
d@33
|
71 ;; observations is a 12d vector summing to 1, alpha summing to 3
|
d@33
|
72 (assert (< (abs (1- (loop for d across observations sum d)))
|
d@33
|
73 (* single-float-epsilon 12)))
|
d@33
|
74 (let ((pairs (loop for alpha_i across alpha
|
d@33
|
75 for d_i across observations
|
d@33
|
76 if (zerop alpha_i)
|
d@33
|
77 do (unless (zerop d_i)
|
d@33
|
78 (return-from likelihood 0.0d0))
|
d@33
|
79 else
|
d@33
|
80 collect (cons alpha_i d_i))))
|
d@33
|
81 ;; now all the CARs of pairs have strictly positive alpha_i
|
d@33
|
82 ;; values, and the d_i are the corresponding observations.
|
d@33
|
83 (let ((alpha_prime (map 'simple-vector #'car pairs)))
|
d@33
|
84 (* (/ (beta alpha_prime))
|
d@33
|
85 (reduce #'* pairs :key (lambda (pair)
|
d@33
|
86 (expt (cdr pair) (1- (car pair)))))))))
|
d@33
|
87
|
d@33
|
88
|
d@33
|
89 (defun likelihood (observations alpha &optional (power 1))
|
d@33
|
90 (assert (< (abs (1- (loop for d across observations sum d)))
|
d@33
|
91 (* single-float-epsilon 12)))
|
d@33
|
92 (let* ((alpha_0 (loop for a across alpha sum a))
|
d@33
|
93 (alpha_0+1 (1+ alpha_0))
|
d@33
|
94 (alpha_00+1 (* alpha_0+1 power))
|
d@33
|
95 (alpha_00 (- alpha_00+1 1))
|
d@33
|
96 (alpha (map 'simple-vector
|
d@33
|
97 (lambda (x) (* x (/ alpha_00 alpha_0)))
|
d@33
|
98 alpha))
|
d@33
|
99 (quantum (expt 0.0005 power))) ; sake of argument
|
d@33
|
100 (let ((pairs
|
d@33
|
101 (loop for d_i across observations
|
d@33
|
102 for alpha_i across alpha
|
d@33
|
103 if (zerop alpha_i)
|
d@33
|
104 do (unless (zerop d_i)
|
d@33
|
105 (return-from likelihood 0.0d0))
|
d@33
|
106 else collect (cons d_i alpha_i))))
|
d@33
|
107 (assert (= (length pairs) 12))
|
d@33
|
108 (let ((alpha_prime (map 'simple-vector #'cdr pairs)))
|
d@33
|
109 (* (/ (beta alpha_prime)) (/ quantum)
|
d@33
|
110 (reduce #'* pairs :key
|
d@33
|
111 (lambda (pair)
|
d@33
|
112 (if (zerop (car pair))
|
d@33
|
113 (* (/ (cdr pair)) (expt quantum (cdr pair)))
|
d@33
|
114 (* quantum (expt (car pair) (1- (cdr
|
d@33
|
115 pair))))))))))))
|
d@33
|
116
|
d@33
|
117 (defun 4ple-likelihood (pitch-classes chord-probabilities intervals level sum)
|
d@33
|
118 (let ((observations))
|
d@33
|
119 (dolist (interval intervals)
|
d@33
|
120 (push (aref pitch-classes interval) observations)
|
d@33
|
121 (decf sum (aref pitch-classes interval)))
|
d@33
|
122 (push sum observations)
|
d@33
|
123 (likelihood/fourwise (make-array (length observations) :initial-contents (reverse observations))
|
d@33
|
124 chord-probabilities level)))
|
d@33
|
125
|
d@33
|
126 (let ((alpha_0s '((1 . 12) (1/2 . 9) (1/4 . 30))))
|
d@33
|
127 (defun likelihood/fourwise (observations alpha &optional (power 1))
|
d@33
|
128 (assert (< (abs (1- (loop for d across observations sum d)))
|
d@33
|
129 (* single-float-epsilon 4)))
|
d@33
|
130 (let* ((alpha_0 (loop for a across alpha sum a))
|
d@33
|
131 (alpha (map 'simple-vector
|
d@33
|
132 (lambda (x) (* x (/ (cdr (assoc power alpha_0s))
|
d@33
|
133 alpha_0)))
|
d@33
|
134 alpha))
|
d@33
|
135 (quantum (expt 0.0005 power))) ; sake of argument
|
d@33
|
136 (let ((pairs
|
d@33
|
137 (loop for d_i across observations
|
d@33
|
138 for alpha_i across alpha
|
d@33
|
139 if (zerop alpha_i)
|
d@33
|
140 do (unless (zerop d_i)
|
d@33
|
141 (return-from likelihood/fourwise 0.0d0))
|
d@33
|
142 else collect (cons d_i alpha_i))))
|
d@33
|
143 (assert (= (length pairs) 4))
|
d@33
|
144 (let ((alpha_prime (map 'simple-vector #'cdr pairs)))
|
d@33
|
145 (* (/ (beta alpha_prime)) (/ quantum)
|
d@33
|
146 (reduce #'* pairs :key
|
d@33
|
147 (lambda (pair)
|
d@33
|
148 (if (zerop (car pair))
|
d@33
|
149 (* (/ (cdr pair)) (expt quantum (cdr pair)))
|
d@33
|
150 (* quantum (expt (car pair) (1- (cdr pair)))))))))))))
|
d@33
|
151
|
d@33
|
152 (defparameter *alpha-scale* 1)
|
d@33
|
153 (defparameter *beta-scale* 1)
|
d@33
|
154 (defparameter *alpha* #(2.925 1.95 1.625))
|
d@33
|
155 (defparameter *beta* #(0.87 4.46))
|
d@33
|
156 (defparameter *minimal-betas* '((1 . 8.75) (1/2 . 3) (1/4 . 2.5)))
|
d@33
|
157 (defparameter *full-betas-1* '((1 . 14) (1/2 . 6) (1/4 . 8))) ;; gets 144|51
|
d@33
|
158 (defparameter *full-betas* '((1 . 14) (3/4 . 6) (1/2 . 6) (1/4 . 8))) ;; guess...
|
d@33
|
159 (defparameter *betas* *full-betas*)
|
d@33
|
160
|
d@33
|
161 (defun 3ple-likelihood (pitch-classes chord-probabilities non-chord intervals level sum
|
d@33
|
162 &optional (alpha *alpha*) (beta *beta*))
|
d@33
|
163 (declare (ignore chord-probabilities non-chord))
|
d@33
|
164 (let ((observations))
|
d@33
|
165 (dolist (interval intervals)
|
d@33
|
166 (push (aref pitch-classes interval) observations)
|
d@33
|
167 (decf sum (aref pitch-classes interval)))
|
d@33
|
168 (push sum observations)
|
d@33
|
169 (when (= sum 1) ;; So there are no chord notes at all... ?? move to likelihood function
|
d@33
|
170 (return-from 3ple-likelihood 0))
|
d@33
|
171 (likelihood/threeplusonewise (make-array (length observations) :initial-contents (reverse observations))
|
d@33
|
172 alpha beta
|
d@33
|
173 level)
|
d@33
|
174 #+nil (likelihood/threeplusonewise (make-array (length observations) :initial-contents (reverse observations))
|
d@33
|
175 (map 'vector #'(lambda (x) (* x *alpha-scale*))
|
d@33
|
176 #(2.925 1.95 1.625))
|
d@33
|
177 #+nil (map 'vector #'(lambda (x) (* x *beta-scale*))
|
d@33
|
178 #(0.87 4.46))
|
d@33
|
179 (make-array 2 :initial-contents (list 0.87 *beta-scale*))
|
d@33
|
180 level)))
|
d@33
|
181
|
d@33
|
182 ;; #(0.87 4.46) worked
|
d@33
|
183
|
d@33
|
184 ;;; observations is a non-relativistic four-vector of proportions:
|
d@33
|
185 ;;; #(tonic mediant dominant other).
|
d@33
|
186 ;;;
|
d@33
|
187 ;;; alpha is a three-vector of Dirichlet parameters for proportions of
|
d@33
|
188 ;;; tonic, mediant, dominant of the total chord notes.
|
d@33
|
189 ;;;
|
d@33
|
190 ;;; beta is a two-vector of Dirichlet parameters for proportions of
|
d@33
|
191 ;;; non-chord vs chord notes.
|
d@33
|
192 ;;;
|
d@33
|
193 ;;; suggested values:
|
d@33
|
194 ;;; alpha: #(2.925 1.95 1.625) ; (tonic, mediant, dominant)
|
d@33
|
195 ;;; beta: #(0.44 1.76) ; (non-chord, chord)
|
d@33
|
196 ;;;
|
d@33
|
197 ;;; model:
|
d@33
|
198 ;;; p(tmdo|c) = p(o|c)p(tmd|oc)
|
d@33
|
199 ;;; where
|
d@33
|
200 ;;; p(o|c) ~ Beta(0.44,1.76) (i.e. p({o,o'}|c) ~ Dir({0.44,1.76})
|
d@33
|
201 ;;; and
|
d@33
|
202 ;;; p(tmd|oc) ~ (1-o) Dir({2.925,1.95,1.625})
|
d@33
|
203 (defun likelihood/threeplusonewise
|
d@33
|
204 (observations alpha beta &optional (power 1))
|
d@33
|
205 (assert (< (abs (1- (loop for d across observations sum d)))
|
d@33
|
206 (* single-float-epsilon 4)))
|
d@33
|
207 (let* ((quantum (expt 0.00000005 power))) ; sake of argument
|
d@33
|
208 (let* ((o (aref observations 3))
|
d@33
|
209 (pairs
|
d@33
|
210 (loop repeat 3
|
d@33
|
211 for d_i across observations
|
d@33
|
212 for alpha_i across alpha
|
d@33
|
213 if (zerop alpha_i)
|
d@33
|
214 do (unless (zerop d_i)
|
d@33
|
215 (return-from likelihood/threeplusonewise 0.0d0))
|
d@33
|
216 else collect (cons (/ d_i (- 1 o)) alpha_i))))
|
d@33
|
217 (assert (= (length pairs) 3))
|
d@33
|
218 (assert (< (abs (1- (loop for (d) in pairs sum d))) (*
|
d@33
|
219 single-float-epsilon 3)))
|
d@33
|
220 (flet ((key (pair)
|
d@33
|
221 (if (zerop (car pair))
|
d@33
|
222 (* (/ (cdr pair)) (expt quantum (cdr pair)))
|
d@33
|
223 (* quantum (expt (car pair) (1- (cdr pair)))))))
|
d@33
|
224 (let ((alpha_prime (map 'simple-vector #'cdr pairs)))
|
d@33
|
225 (*
|
d@33
|
226 ;; p(o|c)
|
d@33
|
227 (/ (beta beta)) (/ quantum)
|
d@33
|
228 (reduce #'* (list (cons o (aref beta 0))
|
d@33
|
229 (cons (- 1 o) (aref beta 1)))
|
d@33
|
230 :key #'key)
|
d@33
|
231 ;; p(tmd|oc)
|
d@33
|
232 (/ (beta alpha_prime)) (/ quantum)
|
d@33
|
233 (reduce #'* pairs :key #'key)))))))
|