stablejet is hosted by Hepforge, IPPP Durham
StableJet
matchOneToOne.hh
1 //
2 // Utility function for matching elements of one vector to another
3 // using best matching distance. All pairwise distances are calculated
4 // and then sorted; the best match corresponds to the smallest
5 // distance. Both matched elements are removed from the pool,
6 // then the best match is found among the remaining elements, etc.
7 //
8 // I. Volobouev
9 // April 2008
10 
11 #ifndef MATCHONETOONE_HH_
12 #define MATCHONETOONE_HH_
13 
14 #include <vector>
15 #include <algorithm>
16 #include <cfloat>
17 
18 namespace {
19  struct matchOneToOne_MatchInfo
20  {
21  double distance;
22  unsigned i1;
23  unsigned i2;
24 
25  inline bool operator<(const matchOneToOne_MatchInfo& r) const
26  {
27  return distance < r.distance;
28  }
29  inline bool operator>(const matchOneToOne_MatchInfo& r) const
30  {
31  return distance > r.distance;
32  }
33  };
34 }
35 
36 //
37 // (*matchFrom1To2)[idx] will be set to the index of the element in v2
38 // which corresponds to the element at index "idx" in v1. If no match
39 // to the element at index "idx" in v1 is found, (*matchFrom1To2)[idx]
40 // is set to -1. All non-negative (*matchFrom1To2)[idx] values will be
41 // unique. The function returns the total number of matches made.
42 //
43 template <class T1, class T2, class DistanceCalculator>
44 unsigned matchOneToOne(const std::vector<T1>& v1, const std::vector<T2>& v2,
45  const unsigned n1, const unsigned n2,
46  const DistanceCalculator& calc,
47  std::vector<int>* matchFrom1To2,
48  const double maxMatchingDistance = DBL_MAX)
49 {
50  unsigned nused = 0;
51  matchFrom1To2->clear();
52 
53  if (n1)
54  {
55  matchFrom1To2->reserve(n1);
56  for (unsigned i1=0; i1<n1; ++i1)
57  matchFrom1To2->push_back(-1);
58 
59  if (n2)
60  {
61  const unsigned nmatches = n1*n2;
62  std::vector<matchOneToOne_MatchInfo> distanceTable(nmatches);
63  std::vector<int> taken2(n2);
64 
65  for (unsigned i2=0; i2<n2; ++i2)
66  taken2[i2] = 0;
67 
68  matchOneToOne_MatchInfo* m;
69  for (unsigned i1=0; i1<n1; ++i1)
70  for (unsigned i2=0; i2<n2; ++i2)
71  {
72  m = &distanceTable[i1*n2+i2];
73  m->distance = calc(v1[i1], v2[i2]);
74  m->i1 = i1;
75  m->i2 = i2;
76  }
77 
78  std::sort(distanceTable.begin(), distanceTable.end());
79  for (unsigned i=0; i<nmatches && nused<n1 && nused<n2; ++i)
80  {
81  m = &distanceTable[i];
82  if (m->distance > maxMatchingDistance)
83  break;
84  if ((*matchFrom1To2)[m->i1] < 0 && !taken2[m->i2])
85  {
86  (*matchFrom1To2)[m->i1] = static_cast<int>(m->i2);
87  taken2[m->i2] = 1;
88  ++nused;
89  }
90  }
91  }
92  }
93 
94  return nused;
95 }
96 
97 
98 #endif // MATCHONETOONE_HH_