Mercurial > hg > beatroot-vamp
comparison Induction.cpp @ 15:887c629502a9
refactor: pull method implementations into .cpp files
author | Chris Cannam |
---|---|
date | Wed, 12 Oct 2011 10:55:52 +0100 |
parents | 4f6626f9ffac |
children | 33d0b18b2509 |
comparison
equal
deleted
inserted
replaced
14:f1252b6a7cf5 | 15:887c629502a9 |
---|---|
20 double Induction::maxIOI = 2.500; | 20 double Induction::maxIOI = 2.500; |
21 double Induction::minIBI = 0.3; | 21 double Induction::minIBI = 0.3; |
22 double Induction::maxIBI = 1.0; | 22 double Induction::maxIBI = 1.0; |
23 int Induction::topN = 10; | 23 int Induction::topN = 10; |
24 | 24 |
25 | |
26 AgentList Induction::beatInduction(EventList events) { | |
27 int i, j, b, bestCount; | |
28 bool submult; | |
29 int intervals = 0; // number of interval clusters | |
30 vector<int> bestn;// count of high-scoring clusters | |
31 bestn.resize(topN); | |
32 | |
33 double ratio, err; | |
34 int degree; | |
35 int maxClusterCount = (int) ceil((maxIOI - minIOI) / clusterWidth); | |
36 vector<double> clusterMean; | |
37 clusterMean.resize(maxClusterCount); | |
38 vector<int> clusterSize; | |
39 clusterSize.resize(maxClusterCount); | |
40 vector<int> clusterScore; | |
41 clusterScore.resize(maxClusterCount); | |
42 | |
43 EventList::iterator ptr1, ptr2; | |
44 Event e1, e2; | |
45 ptr1 = events.begin(); | |
46 while (ptr1 != events.end()) { | |
47 e1 = *ptr1; | |
48 ++ptr1; | |
49 ptr2 = events.begin(); | |
50 e2 = *ptr2; | |
51 ++ptr2; | |
52 while (e2 != e1 && ptr2 != events.end()) { | |
53 e2 = *ptr2; | |
54 ++ptr2; | |
55 } | |
56 while (ptr2 != events.end()) { | |
57 e2 = *ptr2; | |
58 ++ptr2; | |
59 double ioi = e2.time - e1.time; | |
60 if (ioi < minIOI) // skip short intervals | |
61 continue; | |
62 if (ioi > maxIOI) // ioi too long | |
63 break; | |
64 for (b = 0; b < intervals; b++) // assign to nearest cluster | |
65 if (fabs(clusterMean[b] - ioi) < clusterWidth) { | |
66 if ((b < intervals - 1) && ( | |
67 fabs(clusterMean[b+1] - ioi) < | |
68 fabs(clusterMean[b] - ioi))) | |
69 b++; // next cluster is closer | |
70 clusterMean[b] = (clusterMean[b] * clusterSize[b] +ioi)/ | |
71 (clusterSize[b] + 1); | |
72 clusterSize[b]++; | |
73 break; | |
74 } | |
75 if (b == intervals) { // no suitable cluster; create new one | |
76 if (intervals == maxClusterCount) { | |
77 // System.err.println("Warning: Too many clusters"); | |
78 continue; // ignore this IOI | |
79 } | |
80 intervals++; | |
81 for ( ; (b>0) && (clusterMean[b-1] > ioi); b--) { | |
82 clusterMean[b] = clusterMean[b-1]; | |
83 clusterSize[b] = clusterSize[b-1]; | |
84 } | |
85 clusterMean[b] = ioi; | |
86 clusterSize[b] = 1; | |
87 } | |
88 } | |
89 } | |
90 for (b = 0; b < intervals; b++) // merge similar intervals | |
91 // TODO: they are now in order, so don't need the 2nd loop | |
92 // TODO: check BOTH sides before averaging or upper gps don't work | |
93 for (i = b+1; i < intervals; i++) | |
94 if (fabs(clusterMean[b] - clusterMean[i]) < clusterWidth) { | |
95 clusterMean[b] = (clusterMean[b] * clusterSize[b] + | |
96 clusterMean[i] * clusterSize[i]) / | |
97 (clusterSize[b] + clusterSize[i]); | |
98 clusterSize[b] = clusterSize[b] + clusterSize[i]; | |
99 --intervals; | |
100 for (j = i+1; j <= intervals; j++) { | |
101 clusterMean[j-1] = clusterMean[j]; | |
102 clusterSize[j-1] = clusterSize[j]; | |
103 } | |
104 } | |
105 if (intervals == 0) | |
106 return AgentList(); | |
107 for (b = 0; b < intervals; b++) | |
108 clusterScore[b] = 10 * clusterSize[b]; | |
109 bestn[0] = 0; | |
110 bestCount = 1; | |
111 for (b = 0; b < intervals; b++) | |
112 for (i = 0; i <= bestCount; i++) | |
113 if ((i < topN) && ((i == bestCount) || | |
114 (clusterScore[b] > clusterScore[bestn[i]]))){ | |
115 if (bestCount < topN) | |
116 bestCount++; | |
117 for (j = bestCount - 1; j > i; j--) | |
118 bestn[j] = bestn[j-1]; | |
119 bestn[i] = b; | |
120 break; | |
121 } | |
122 for (b = 0; b < intervals; b++) // score intervals | |
123 for (i = b+1; i < intervals; i++) { | |
124 ratio = clusterMean[b] / clusterMean[i]; | |
125 submult = ratio < 1; | |
126 if (submult) | |
127 degree = (int) nearbyint(1/ratio); | |
128 else | |
129 degree = (int) nearbyint(ratio); | |
130 if ((degree >= 2) && (degree <= 8)) { | |
131 if (submult) | |
132 err = fabs(clusterMean[b]*degree - clusterMean[i]); | |
133 else | |
134 err = fabs(clusterMean[b] - clusterMean[i]*degree); | |
135 if (err < (submult? clusterWidth : clusterWidth * degree)) { | |
136 if (degree >= 5) | |
137 degree = 1; | |
138 else | |
139 degree = 6 - degree; | |
140 clusterScore[b] += degree * clusterSize[i]; | |
141 clusterScore[i] += degree * clusterSize[b]; | |
142 } | |
143 } | |
144 } | |
145 | |
146 AgentList a; | |
147 for (int index = 0; index < bestCount; index++) { | |
148 b = bestn[index]; | |
149 // Adjust it, using the size of super- and sub-intervals | |
150 double newSum = clusterMean[b] * clusterScore[b]; | |
151 int newCount = clusterSize[b]; | |
152 int newWeight = clusterScore[b]; | |
153 for (i = 0; i < intervals; i++) { | |
154 if (i == b) | |
155 continue; | |
156 ratio = clusterMean[b] / clusterMean[i]; | |
157 if (ratio < 1) { | |
158 degree = (int) nearbyint(1 / ratio); | |
159 if ((degree >= 2) && (degree <= 8)) { | |
160 err = fabs(clusterMean[b]*degree - clusterMean[i]); | |
161 if (err < clusterWidth) { | |
162 newSum += clusterMean[i] / degree * clusterScore[i]; | |
163 newCount += clusterSize[i]; | |
164 newWeight += clusterScore[i]; | |
165 } | |
166 } | |
167 } else { | |
168 degree = (int) nearbyint(ratio); | |
169 if ((degree >= 2) && (degree <= 8)) { | |
170 err = fabs(clusterMean[b] - degree*clusterMean[i]); | |
171 if (err < clusterWidth * degree) { | |
172 newSum += clusterMean[i] * degree * clusterScore[i]; | |
173 newCount += clusterSize[i]; | |
174 newWeight += clusterScore[i]; | |
175 } | |
176 } | |
177 } | |
178 } | |
179 double beat = newSum / newWeight; | |
180 // Scale within range ... hope the grouping isn't ternary :( | |
181 while (beat < minIBI) // Maximum speed | |
182 beat *= 2.0; | |
183 while (beat > maxIBI) // Minimum speed | |
184 beat /= 2.0; | |
185 if (beat >= minIBI) { | |
186 a.push_back(Agent(beat)); | |
187 } | |
188 } | |
189 #ifdef DEBUG_BEATROOT | |
190 std::cerr << "Induction complete, returning " << a.size() << " agent(s)" << std::endl; | |
191 #endif | |
192 return a; | |
193 } // beatInduction() | |
194 |