Jpp
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
JAlgorithm.hh
Go to the documentation of this file.
1 #ifndef __JTRIGGER__JALGORITHM__
2 #define __JTRIGGER__JALGORITHM__
3 
4 #include <vector>
5 #include <algorithm>
6 #include <iterator>
7 
8 #include "JTrigger/JMatch.hh"
9 
10 
11 /**
12  * \file
13  *
14  * Algorithms for hit clustering and sorting.
15  * \author mdejong
16  */
17 namespace JTRIGGER {}
18 namespace JPP { using namespace JTRIGGER; }
19 
20 namespace JTRIGGER {
21 
22 
23  /**
24  * Partition data according given binary match operator.
25  *
26  * The underlying algorithm is known in literature as 'clique'.
27  * The result is (likely to be) the maximal sub-set with all elements matched to each other.
28  * The complexity is quadratic, i.e. at most (number of elements x number of elements) operations.
29  * The algorithm will sort the data such that all clusterized hits are at the front.
30  * The return value points the first non clusterized hit.
31  *
32  * The template argument <tt>JHit_t</tt> refers to a data structure which should have the following member methods:
33  * - double %getX(); // [m]
34  * - double %getY(); // [m]
35  * - double %getZ(); // [m]
36  * - double %getT(); // [ns]
37  *
38  * \param __begin begin of data
39  * \param __end end of data
40  * \param match binary match operator
41  * \param Nmin minimum cluster size
42  * \return end of data
43  */
44  template<class JHitIterator_t, class JHit_t>
45  inline JHitIterator_t clusterize(JHitIterator_t __begin,
46  JHitIterator_t __end,
47  const JMatch<JHit_t>& match,
48  const int Nmin = 1)
49  {
50  return clusterize(__begin, __end, match, Nmin, typename std::iterator_traits<JHitIterator_t>::iterator_category());
51  }
52 
53 
54  /**
55  * Implementation of method clusterize for random access iterators.
56  */
57  template<class JHitIterator_t, class JHit_t>
58  inline JHitIterator_t clusterize(JHitIterator_t __begin,
59  JHitIterator_t __end,
60  const JMatch<JHit_t>& match,
61  const int Nmin,
62  std::random_access_iterator_tag)
63  {
64  const int N = std::distance(__begin, __end);
65 
66  if (N >= Nmin) {
67 
68  int i, j;
69  int n = N;
70 
71  JHitIterator_t buffer = __begin;
72 
73  // Determine number of associated hits for each hit.
74 
75  std::vector<int> count(N, 1); // Assume always a match with itself.
76 
77  for (i = 0; i != N; ++i) {
78 
79  for (j = i; ++j != N; ) {
80 
81  if (match(buffer[i], buffer[j])) {
82 
83  ++count[i];
84  ++count[j];
85 
86  } else if (n == Nmin) {
87 
88  return __begin;
89  }
90  }
91 
92  if (count[i] < Nmin) {
93 
94  --n;
95 
96  if (n < Nmin) {
97  return __begin;
98  }
99  }
100  }
101 
102  n = N;
103 
104  // Remove hit with the smallest number of associated hits.
105  // This procedure stops when the number of associated hits
106  // is equal to the number of (remaining) hits.
107 
108  for ( ; n >= Nmin; ) {
109 
110  j = 0;
111 
112  for (i = 1; i != n; ++i) {
113  if (count[i] < count[j]) {
114  j = i;
115  }
116  }
117 
118  // Ready?
119 
120  if (count[j] == n) {
121  break;
122  }
123 
124  // Reduce effective size.
125 
126  --n;
127 
128  // Swap the selected hit to end.
129 
130  std::swap(buffer[j], buffer[n]);
131  std::swap(count [j], count [n]);
132 
133  // Decrease number of associated hits for each associated hit.
134 
135  for (i = 0; i != n; ++i) {
136  if (match(buffer[i], buffer[n])) {
137  --count[i];
138  }
139  }
140  }
141 
142  if (n >= Nmin)
143  return __begin + n;
144  else
145  return __begin;
146  }
147 
148  return __begin;
149  }
150 
151 
152  /**
153  * Partition data according given binary match operator.
154  *
155  * The underlying algorithm is known in literature as reverse 'clique'.
156  * The result is (likely to be) the maximal sub-set with all elements matched to each other.
157  * The complexity is quadratic, i.e. at most (number of elements x number of elements) operations.
158  * The algorithm will sort the data such that all clusterized hits are at the front.
159  * The return value points the first non clusterized hit.
160  *
161  * The template argument <tt>JHit_t</tt> refers to a data structure which should have the following member methods:
162  * - double %getX(); // [m]
163  * - double %getY(); // [m]
164  * - double %getZ(); // [m]
165  * - double %getT(); // [ns]
166  *
167  * \param __begin begin of data
168  * \param __end end of data
169  * \param match binary match operator
170  * \return end of data
171  */
172  template<class JHitIterator_t, class JHit_t>
173  inline JHitIterator_t reverse_clusterize(JHitIterator_t __begin,
174  JHitIterator_t __end,
175  const JMatch<JHit_t>& match)
176  {
177  return reverse_clusterize(__begin, __end, match, typename std::iterator_traits<JHitIterator_t>::iterator_category());
178  }
179 
180 
181  /**
182  * Implementation of method reverse_clusterize for random access iterators.
183  */
184  template<class JHitIterator_t, class JHit_t>
185  inline JHitIterator_t reverse_clusterize(JHitIterator_t __begin,
186  JHitIterator_t __end,
187  const JMatch<JHit_t>& match,
188  std::random_access_iterator_tag)
189  {
190  const int N = std::distance(__begin, __end);
191 
192  if (N != 0) {
193 
194  int i, j;
195 
196  JHitIterator_t buffer = __begin;
197 
198  // Determine number of associated hits for each hit.
199 
200  std::vector<int> count(N, 1); // Assume always a match with itself.
201 
202  for (i = 0; i != N; ++i) {
203 
204  for (j = 0; j != i; ++j) {
205  if (match(buffer[i], buffer[j])) {
206  ++count[i];
207  ++count[j];
208  }
209  }
210  }
211 
212  // Keep hit with the largest number of associated hits.
213  // This procedure stops when the number of associated hits is equal to one.
214 
215  for (int k = 0; ; ) {
216 
217  j = k;
218 
219  for (i = j; ++i != N; ) {
220  if (count[i] > count[j]) {
221  j = i;
222  }
223  }
224 
225  // Ready?
226 
227  if (count[j] == 1) {
228  return __begin + k;
229  }
230 
231  // Swap the selected hit to begin.
232 
233  std::swap(buffer[j], buffer[k]);
234  std::swap(count [j], count [k]);
235 
236  // Decrease number of associated hits for each associated hit.
237 
238  for (i = k; ++i != N; ) {
239  if (match(buffer[i], buffer[k])) {
240  --count[i];
241  }
242  }
243 
244  // Increase effective size.
245 
246  ++k;
247  }
248  }
249 
250  return __begin;
251  }
252 
253 
254  /**
255  * Select best root hit according given comparator and partition remaining data
256  * according given binary match operator and this root hit.
257  * The complexity is linear, i.e. at most number of elements operations.
258  * The complexity is quadratic, i.e. at most (number of elements x number of elements) operations.
259  * The algorithm will sort the data such that all clusterized hits are at the front.
260  *
261  * \param __begin begin of data
262  * \param __end end of data
263  * \param comparator comparator
264  * \param match binary match operator
265  * \return end of data
266  */
267  template<class JHitIterator_t, class JComparator_t, class JHit_t>
268  inline JHitIterator_t clusterize(JHitIterator_t __begin,
269  JHitIterator_t __end,
270  JComparator_t comparator,
271  const JMatch<JHit_t>& match)
272  {
273  if (__begin != __end) {
274 
275  std::sort(__begin, __end, comparator);
276 
277  const JHit_t& root = *__begin;
278 
279  return std::partition(++__begin, __end, JBind2nd(match, root));
280 
281  } else {
282 
283  return __end;
284  }
285  }
286 
287 
288  /**
289  * Partition data according given binary match operator.
290  *
291  * The underlying algorithm is known in literature as reverse 'clique'.
292  * The result is (likely to be) the maximal sub-set with all elements matched to each other.
293  * The complexity is quadratic, i.e. at most (number of elements x number of elements) operations.
294  * The algorithm will sort the data such that all clusterized hits are at the front.
295  * The return value points the first non clusterized hit.
296  *
297  * The template argument <tt>JHit_t</tt> refers to a data structure which should have the following member methods:
298  * - double %getX(); // [m]
299  * - double %getY(); // [m]
300  * - double %getZ(); // [m]
301  * - double %getT(); // [ns]
302  * - double %getW(); // [au]
303  *
304  * \param __begin begin of data
305  * \param __end end of data
306  * \param match binary match operator
307  * \return end of data
308  */
309  template<class JHitIterator_t, class JHit_t>
310  inline JHitIterator_t clusterizeWeight(JHitIterator_t __begin,
311  JHitIterator_t __end,
312  const JMatch<JHit_t>& match)
313  {
314  return clusterizeWeight(__begin, __end, match, typename std::iterator_traits<JHitIterator_t>::iterator_category());
315  }
316 
317 
318  /**
319  * Implementation of method clusterizeWeight for random access iterators.
320  */
321  template<class JHitIterator_t, class JHit_t>
322  inline JHitIterator_t clusterizeWeight(JHitIterator_t __begin,
323  JHitIterator_t __end,
324  const JMatch<JHit_t>& match,
325  std::random_access_iterator_tag)
326  {
327  if (__begin != __end) {
328 
329  const int N = std::distance(__begin, __end);
330 
331  int i, j;
332 
333  // Determine weight of each hit.
334 
335  std::vector<double> weight(N, 0.0);
336 
337  JHitIterator_t buffer = __begin;
338 
339  for (i = 0; i != N; ++i) {
340 
341  weight[i] += buffer[i].getW();
342 
343  for (j = i; ++j != N; ) {
344 
345  if (match(buffer[i], buffer[j])) {
346 
347  weight[i] += buffer[j].getW();
348  weight[j] += buffer[i].getW();
349  }
350  }
351  }
352 
353  // Remove hit with the smallest weight of associated hits.
354  // This procedure stops when the weight of associated hits
355  // is equal to the maximal weight of (remaining) hits.
356 
357  int n = N;
358  double W;
359 
360  for ( ; ; ) {
361 
362  j = 0;
363  W = weight[j];
364 
365  for (i = 1; i != n; ++i) {
366 
367  if (weight[i] < weight[j]) {
368  j = i;
369  }
370 
371  if (weight[i] > W) {
372  W = weight[i];
373  }
374  }
375 
376  // Ready?
377 
378  if (weight[j] == W) {
379  break;
380  }
381 
382  // Reduce effective size.
383 
384  --n;
385 
386  // Swap the selected hit to end.
387 
388  std::swap(buffer[j], buffer[n]);
389  std::swap(weight[j], weight[n]);
390 
391  // Decrease weight of associated hits for each associated hit.
392 
393  for (i = 0; i != n; ++i) {
394  if (match(buffer[i], buffer[n])) {
395  weight[i] -= buffer[n].getW();
396  }
397  }
398  }
399 
400  return __begin + n;
401 
402  } else {
403 
404  return __end;
405  }
406  }
407 
408 
409  /**
410  * Compare two hits by weight.
411  *
412  * The template argument <tt>JHit_t</tt> refers to a data structure which should have the following member methods:
413  * - double %getW(); // [a.u.]
414  *
415  * \param first first hit
416  * \param second second hit
417  * \return true if first hit has larger weight than second; else false
418  */
419  template<class JHit_t>
420  inline bool weightSorter(const JHit_t& first, const JHit_t& second)
421  {
422  return first.getW() > second.getW();
423  }
424 
425 
426  /**
427  * Compare two hits by weight.
428  *
429  * The template argument <tt>JHit_t</tt> refers to a data structure which should have the following member methods:
430  * - double %getT(); // [a.u.]
431  *
432  * \param first first hit
433  * \param second second hit
434  * \return true if first hit earlier than second; else false
435  */
436  template<class JHit_t>
437  inline bool timeSorter(const JHit_t& first, const JHit_t& second)
438  {
439  return first.getT() < second.getT();
440  }
441 }
442 
443 #endif
JBinder2nd< JHit_t > JBind2nd(const JMatch< JHit_t > &match, const JHit_t &second)
Auxiliary method to create JBinder2nd object.
Definition: JBind2nd.hh:70
Function object interface for hit matching.
Definition: JMatch.hh:27
JHitIterator_t clusterizeWeight(JHitIterator_t __begin, JHitIterator_t __end, const JMatch< JHit_t > &match)
Partition data according given binary match operator.
Definition: JAlgorithm.hh:310
Base class for match operations inside clusterize methods.
JHitIterator_t clusterize(JHitIterator_t __begin, JHitIterator_t __end, const JMatch< JHit_t > &match, const int Nmin=1)
Partition data according given binary match operator.
Definition: JAlgorithm.hh:45
bool timeSorter(const JHit_t &first, const JHit_t &second)
Compare two hits by weight.
Definition: JAlgorithm.hh:437
bool weightSorter(const JHit_t &first, const JHit_t &second)
Compare two hits by weight.
Definition: JAlgorithm.hh:420
JHitIterator_t reverse_clusterize(JHitIterator_t __begin, JHitIterator_t __end, const JMatch< JHit_t > &match)
Partition data according given binary match operator.
Definition: JAlgorithm.hh:173