REST-for-Physics  v2.3
Rare Event Searches ToolKit for Physics
TRestTrackPathMinimizationProcess.cxx
1
10
11#include "TRestTrackPathMinimizationProcess.h"
12
13using namespace std;
14
16
17TRestTrackPathMinimizationProcess::TRestTrackPathMinimizationProcess() { Initialize(); }
18
19TRestTrackPathMinimizationProcess::~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
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 */
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
156 cout << "Min path ";
157 for (const auto& v : bestPath) cout << v << " ";
158 cout << " " << min_path << endl;
159 }
160}
161
167void 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
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
234 cout << "Min path ";
235 for (const auto& v : bestPath) cout << v << " ";
236 cout << " " << min_path << endl;
237 }
238}
239
245void 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
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
endl_t RESTendl
Termination flag object for TRestStringOutput.
void SetLibraryVersion(TString version)
Set the library version of this metadata class.
TRestStringOutput::REST_Verbose_Level GetVerboseLevel()
returns the verboselevel in type of REST_Verbose_Level enumerator
void SetSectionName(std::string sName)
set the section name, clear the section content
@ 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.