REST-for-Physics  v2.3
Rare Event Searches ToolKit for Physics
TRestTrackPathMinimizationProcess.cxx
1 
11 #include "TRestTrackPathMinimizationProcess.h"
12 
13 using namespace std;
14 
16 
17 TRestTrackPathMinimizationProcess::TRestTrackPathMinimizationProcess() { Initialize(); }
18 
19 TRestTrackPathMinimizationProcess::~TRestTrackPathMinimizationProcess() { delete fOutputTrackEvent; }
20 
22  SetSectionName(this->ClassName());
23  SetLibraryVersion(LIBRARY_VERSION);
24 
25  fInputTrackEvent = nullptr;
26  fOutputTrackEvent = new TRestTrackEvent();
27 }
28 
30 
32  fInputTrackEvent = (TRestTrackEvent*)inputEvent;
33 
34  if (this->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug)
35  cout << "TRestTrackPathMinimizationProcess. Number of tracks : "
36  << fInputTrackEvent->GetNumberOfTracks() << endl;
37 
38  // Copying the input tracks to the output track
39  for (int tck = 0; tck < fInputTrackEvent->GetNumberOfTracks(); tck++)
40  fOutputTrackEvent->AddTrack(fInputTrackEvent->GetTrack(tck));
41 
42  for (int tck = 0; tck < fInputTrackEvent->GetNumberOfTracks(); tck++) {
43  if (!fInputTrackEvent->isTopLevel(tck)) continue;
44  Int_t tckId = fInputTrackEvent->GetTrack(tck)->GetTrackID();
45 
46  TRestVolumeHits* hits = fInputTrackEvent->GetTrack(tck)->GetVolumeHits();
47  const int nHits = hits->GetNumberOfHits();
48 
49  /* {{{ Debug output */
50  if (this->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) {
51  Int_t pId = fInputTrackEvent->GetTrack(tck)->GetParentID();
52  cout << "Track : " << tck << " TrackID : " << tckId << " ParentID : " << pId << endl;
53  cout << "-----------------" << endl;
54  hits->PrintHits();
55  cout << "-----------------" << endl;
56  }
57  /* }}} */
58 
59  RESTDebug << "hits : " << nHits << RESTendl;
60 
61  std::vector<int> bestPath(nHits);
62  for (int i = 0; i < nHits; i++) bestPath[i] = i; // Initialize
63 
64  if (fMinMethod == "bruteforce")
65  BruteForce(hits, bestPath);
66  else if (fMinMethod == "closestN")
67  NearestNeighbour(hits, bestPath);
68  else
69  HeldKarp(hits, bestPath); // default
70 
71  TRestVolumeHits bestHitsOrder;
72  for (const auto& v : bestPath) bestHitsOrder.AddHit(*hits, v);
73 
74  // TODO We must also copy other track info here
75  TRestTrack bestTrack;
76  bestTrack.SetTrackID(fOutputTrackEvent->GetNumberOfTracks() + 1);
77  bestTrack.SetParentID(tckId);
78  bestTrack.SetVolumeHits(bestHitsOrder);
79  fOutputTrackEvent->AddTrack(&bestTrack);
80  }
81 
82  fOutputTrackEvent->SetLevels();
83  return fOutputTrackEvent;
84 }
85 
92  const int nHits = hits->GetNumberOfHits();
93  vector<vector<double>> dist(nHits, vector<double>(nHits));
94  RESTDebug << "Nhits " << nHits << RESTendl;
95 
96  if (nHits < 3) return;
97 
98  for (int i = 0; i < nHits; i++) {
99  for (int j = i; j < nHits; j++) {
100  if (i == j) {
101  dist[i][j] = 0; // Distance within the same vertex
102  } else {
103  dist[i][j] = hits->GetDistance(i, j); // Distance within two hits vertex
104  dist[j][i] = dist[i][j]; // It is symmetric
105  }
106  }
107  }
108 
109  double min_path = 1E9;
110  std::vector<int> current_path(nHits);
111 
112  // Find the shortest path starting from all vertex
113  for (int s = 0; s < nHits; s++) {
114  std::vector<int> vertex(nHits - 1);
115 
116  int j = 0;
117  for (int i = 0; i < nHits; i++) {
118  if (i == s) continue;
119  vertex[j] = i;
120  j++;
121  }
122 
123  // store current Path weight(cost)
124  double current_pathweight = 0;
125  current_path[0] = s;
126 
127  // compute current path weight
128  int k = s;
129  while (!vertex.empty()) {
130  int closestN = 0;
131  int index = 0, bestIndex = 0;
132  double minDist = 1E9;
133  for (const auto& v : vertex) {
134  const double d = dist[k][v];
135  if (d < minDist) {
136  minDist = d;
137  current_pathweight += d;
138  closestN = v;
139  bestIndex = index;
140  }
141  index++;
142  }
143  k = closestN;
144  current_path[nHits - vertex.size()] = k;
145  vertex.erase(vertex.begin() + bestIndex);
146  }
147  if (fCyclic) current_pathweight += dist[k][s];
148 
149  if (current_pathweight < min_path) {
150  min_path = current_pathweight;
151  bestPath = current_path;
152  }
153  }
154 
155  if (this->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) {
156  cout << "Min path ";
157  for (const auto& v : bestPath) cout << v << " ";
158  cout << " " << min_path << endl;
159  }
160 }
161 
167 void TRestTrackPathMinimizationProcess::BruteForce(TRestVolumeHits* hits, std::vector<int>& bestPath) {
168  const int nHits = hits->GetNumberOfHits();
169  vector<vector<double>> dist(nHits, vector<double>(nHits));
170  RESTDebug << "Nhits " << nHits << RESTendl;
171 
172  if (nHits < 3) return;
173 
174  for (int i = 0; i < nHits; i++) {
175  for (int j = i; j < nHits; j++) {
176  if (i == j) {
177  dist[i][j] = 0; // Distance within the same vertex
178  } else {
179  dist[i][j] = hits->GetDistance(i, j); // Distance within two hits vertex
180  dist[j][i] = dist[i][j]; // It is symmetric
181  }
182  }
183  }
184 
185  if (this->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) {
186  for (int i = 0; i < nHits; i++) {
187  for (int j = 0; j < nHits; j++) {
188  cout << dist[i][j] << " ";
189  }
190  cout << "\n";
191  }
192  }
193 
194  double min_path = 1E9;
195 
196  // Find the shortest path starting from all vertex
197  for (int s = 0; s < nHits; s++) {
198  // store all vertex apart from source vertex
199  std::vector<int> vertex(nHits - 1);
200  int index = 0;
201  for (int i = 0; i < nHits; i++) {
202  if (i == s) continue;
203  vertex[index] = i;
204  // debug<<index<<" "<<i<<endl;
205  index++;
206  }
207 
208  // store minimum weight Hamiltonian Cycle.
209  do {
210  // store current Path weight(cost)
211  double current_pathweight = 0;
212 
213  // compute current path weight
214  int k = s;
215  for (const auto& v : vertex) {
216  current_pathweight += dist[k][v];
217  k = v;
218  }
219  // In case of cyclic
220  if (fCyclic) current_pathweight += dist[k][s];
221 
222  // update minimum
223  if (current_pathweight < min_path) {
224  min_path = current_pathweight;
225  bestPath[0] = s;
226  for (size_t i = 0; i < vertex.size(); i++) bestPath[i + 1] = vertex[i];
227  }
228 
229  // Could be optimized using the shortest neighbour after computing Floyd Warshall Algorithm
230  } while (std::next_permutation(vertex.begin(), vertex.end()));
231  }
232 
233  if (this->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) {
234  cout << "Min path ";
235  for (const auto& v : bestPath) cout << v << " ";
236  cout << " " << min_path << endl;
237  }
238 }
239 
245 void TRestTrackPathMinimizationProcess::HeldKarp(TRestVolumeHits* hits, std::vector<int>& bestPath) {
246  const int nHits = hits->GetNumberOfHits();
247 
248  if (nHits < 4) return;
249 
250  Int_t segment_count = nHits * (nHits - 1) / 2;
251  int* elen = (int*)malloc(segment_count * sizeof(int));
252  /*
253  double *enBetween = (double *) malloc( segment_count * sizeof( double ) );
254 
255  Double_t lenghtReduction = 0.25;
256  Double_t fTubeRadius = 1.;
257 
258  Double_t energyIntegral = 0;
259  Int_t integratedSegments = 0;
260  */
261 
262  int k = 0;
263  vector<int> bestP(nHits);
264  Int_t rval = 0;
265  for (int i = 0; i < nHits; i++) {
266  bestP[i] = i;
267  for (int j = 0; j < i; j++) {
268  TVector3 x0, x1, pos0, pos1;
269 
270  x0 = hits->GetPosition(i);
271  x1 = hits->GetPosition(j);
272 
273  Double_t distance = hits->GetDistance(i, j);
274 
275  /* This can be used to weight the segments with the number of hits
276  between nodes
277  *
278  pos0 = lenghtReduction * ( x1-x0 ) + x0;
279  pos1 = (1-lenghtReduction) * ( x1-x0 ) + x0;
280 
281  Double_t energyBetween = originHits->GetEnergyInCylinder( pos0, pos1,
282  fTubeRadius );
283 
284  if( GetVerboseLevel() >= REST_Extreme )
285  {
286  cout << "Distance : " << distance << endl;
287  cout << "Segment energy (" << i << " , " << j << " ) : " <<
288  energyBetween << endl;
289  }
290 
291  if( energyBetween > 0 )
292  {
293  energyIntegral += energyBetween;
294  integratedSegments++;
295  }
296 
297  */
298 
299  elen[k] = (int)(100. * distance);
300 
301  // enBetween[k] = energyBetween;
302  k++;
303  }
304  }
305 
306  /* For the weighting of segments
307  *
308  Double_t meanHitsConnection = energyIntegral/integratedSegments;
309  if( GetVerboseLevel() >= REST_Debug )
310  cout << "energyIntegral : " << energyIntegral << " integratedSegments
311  : " << integratedSegments << endl;
312 
313  for( int n = 0; n < k; n++ )
314  {
315  if( enBetween[n] > meanHitsConnection )
316  elen[n] = elen[n] / 1.5;
317 
318  if( enBetween[n] < meanHitsConnection/3 )
319  elen[n] = elen[n] * 2.5;
320  }
321 
322  cout << "Mean hits : " << meanHitsConnection << endl;
323 
324  if( GetVerboseLevel() >= REST_Extreme )
325  GetChar();
326  */
327 
328  if (GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Extreme) {
329  for (int n = 0; n < segment_count; n++) cout << "n : " << n << " elen : " << elen[n] << endl;
330  GetChar();
331  }
332 
333  rval = TrackMinimization_segment(nHits, elen, &bestP[0]);
334 
335  /**** Just Printing
336  for( int i = 0; i < hits->GetNumberOfHits()-1; i++ )
337  {
338  TVector3 x0, x1, pos0, pos1;
339 
340  x0 = hits->GetPosition( i );
341  x1 = hits->GetPosition( i+1 );
342 
343  pos0 = lenghtReduction * ( x1-x0 ) + x0;
344  pos1 = (1-lenghtReduction) * ( x1-x0 ) + x0;
345 
346  Double_t distance = (x1-x0).Mag();
347  Double_t energyBetween = originHits->GetEnergyInCylinder( pos0, pos1,
348  fTubeRadius );
349 
350  cout << "Hit : " << i << " x : " << hits->GetX(i) << " y : " <<
351  hits->GetY(i) << " z : " << hits->GetZ(i) << endl; cout << "Distance : "
352  << distance << " Energy between : " << energyBetween << endl;
353  }
354  cout << "Hit : " << nHits-1 << " x : " << hits->GetX(nHits-1) << " y : "
355  << hits->GetY(nHits-1) << " z : " << hits->GetZ(nHits-1) << endl;
356  ***** */
357 
358  free(elen);
359  // free( enBetween );
360 
362 
363  if (rval != 0) {
364  if (GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Warning) {
365  cout << "REST WARNING. TRestTrackPathMinimizationProcess. HELDKARP FAILED." << endl;
366  }
367  fOutputTrackEvent->SetOK(false);
368  return;
369  }
370 
371  for (int i = 0; i < nHits; i++) bestPath[i] = bestP[i];
372 }
373 
A base class for any REST event.
Definition: TRestEvent.h:38
TVector3 GetPosition(int n) const
It returns the position of hit number n.
Definition: TRestHits.cxx:515
@ REST_Debug
+show the defined debug messages
void NearestNeighbour(TRestVolumeHits *hits, std::vector< int > &bestPath)
Return the index with the shortest path solving Travelling Salesman Problem (TSP) using nearest neigh...
void HeldKarp(TRestVolumeHits *hits, std::vector< int > &bestPath)
This function eturn the index with the shortest path Note that this method calls external tsp library...
void EndProcess() override
To be executed at the end of the run (outside event loop)
void InitProcess() override
To be executed at the beginning of the run (outside event loop)
void Initialize() override
Making default settings.
TRestEvent * ProcessEvent(TRestEvent *inputEvent) override
Process one event.
void BruteForce(TRestVolumeHits *hits, std::vector< int > &bestPath)
This function return the index with the shortest path solving Travelling Salesman Problem (TSP) using...
Int_t GetChar(std::string hint="Press a KEY to continue ...")
Helps to pause the program, printing a message before pausing.