KiTrack  1.7.0
SubsetHopfieldNN.h
1 #ifndef SubsetHopfieldNN_h
2 #define SubsetHopfieldNN_h
3 
4 #include <CLHEP/Random/RandFlat.h>
5 
6 #include "KiTrack/Subset.h"
7 #include "KiTrack/HopfieldNeuralNet.h"
8 
9 
10 
11 namespace KiTrack {
12 
16  template< class T >
17  class SubsetHopfieldNN : public Subset<T>{
18 
19  public:
20 
99  template< class GetQI, class AreCompatible >
100  void calculateBestSet( AreCompatible areCompatible, GetQI getQI );
101 
102 
103  SubsetHopfieldNN(){
104 
105  _TStart = 2.1;
106  _TInf = 0.1;
107  _omega = 0.75;
108  _limitForStable = 0.01;
109  _initStateMin = 0.;
110  _initStateMax = 0.1;
111  _activationThreshold = 0.5;
112 
113  }
114 
115  void setTStart( double tStart ){ _TStart = tStart; }
116  void setTInf( double tInf ){ _TInf = tInf; }
117  void setOmega( double omega ){ _omega = omega; }
118  void setLimitForStable( double limitForStable ){ _limitForStable = limitForStable; }
119  void setInitStateMin( double initStateMin ){ _initStateMin = initStateMin; }
120  void setInitStateMax( double initStateMax ){ _initStateMax = initStateMax; }
121  void setActivationThreshold( double activationThreshold ){ _activationThreshold = activationThreshold; }
122 
123  double getTStart(){ return _TStart; }
124  double getTInf(){ return _TInf; }
125  double getOmega(){ return _omega; }
126  double getLimitForStable(){ return _limitForStable; }
127  double getInitStateMin(){ return _initStateMin; }
128  double getInitStateMax(){ return _initStateMax; }
129  double getActivationThreshold(){ return _activationThreshold; }
130 
131  protected:
132 
133 
134  double _TStart;
135  double _TInf;
136  double _omega;
137  double _limitForStable;
138  double _initStateMin;
139  double _initStateMax;
140  double _activationThreshold;
141 
142  };
143 
144 
145  template< class T > template< class GetQI, class AreCompatible >
146  void SubsetHopfieldNN<T>::calculateBestSet( AreCompatible areCompatible, GetQI getQI ){
147 
148 
149  unsigned nAccepted=0;
150  unsigned nRejected=0;
151  unsigned nCompWithAll=0;
152  unsigned nIncompatible=0;
153 
154 
155  std::vector< T > elements = this->_elements; //this pointer is needed here, because of the template!
156 
157  unsigned nElements = elements.size();
158 
159  // the information for the Hopfield Neural Network:
160 
161  std::vector < std::vector <bool> > G; // a matrix telling, if two neurons (elements) are compatible
162  G.resize( nElements );
163  for (unsigned i=0; i<nElements; i++) G[i].resize( elements.size() );
164 
165  std::vector < double > QI ; // the quality indicators of the neurons (elements)
166  QI.resize( nElements );
167 
168  std::vector < double > states; // the initial state to start from.
169  states.resize( nElements );
170 
171 
172 
173 
174  /**********************************************************************************************/
175  /* 1. Find out which elements are compatible and get the QIs */
176  /**********************************************************************************************/
177 
178 
179  for ( unsigned i=0; i < nElements ; i++){ //over all elements
180 
181 
182  T elementA = elements[i]; //the track we want to look at.
183 
184  // Get the quality
185  QI[i] = getQI( elementA );
186 
187  streamlog_out(DEBUG3) << "QI of element " << i << " = " << QI[i] << "\n";
188 
189 
190  // Set an initial state
191  states[i] = CLHEP::RandFlat::shoot ( _initStateMin , _initStateMax ); //random ( uniformly ) values from initStateMin to initStateMax
192 
193 
194  // Fill the states in the G matrix. (whether two elements are compatible or not
195  for ( unsigned j=i+1; j < nElements ; j++ ){ // over all elements that come after the current one (the elements before get filled automatically because of symmetry)
196 
197  T elementB = elements[j]; // the track we check if it is in conflict with trackA
198 
199  if ( areCompatible( elementA , elementB ) ){
200 
201  G[i][j] = 0;
202  G[j][i] = 0;
203 
204  }
205  else{
206 
207  G[i][j] = 1;
208  G[j][i] = 1;
209 
210  }
211 
212  }
213 
214  }
215 
216  // output of the G matrix:
217  if( !G.empty() ){
218 
219  streamlog_out(DEBUG2) << "G:\n";
220 
221 
222  for ( unsigned i=0; i < G.size(); i++ ){
223 
224 
225  for ( unsigned j=0; j < G[i].size(); j++ ){
226 
227  streamlog_out(DEBUG2) << G[i][j] << " ";
228 
229  }
230 
231  streamlog_out(DEBUG2) << "\n";
232 
233  }
234 
235  }
236  // output, where one sees, what elements are incompatible with what others:
237  if( !G.empty() ){
238 
239  streamlog_out(DEBUG2) << "Incompatible ones:\n";
240 
241 
242  for ( unsigned i=0; i < G.size(); i++ ){
243 
244  streamlog_out(DEBUG2) << "Element " << i << ":\t";
245 
246  for ( unsigned j=0; j < G[i].size(); j++ ){
247 
248  if( G[i][j] ) streamlog_out(DEBUG2) << j << ", ";
249 
250  }
251 
252  streamlog_out(DEBUG2) << "\n";
253 
254  }
255 
256  }
257 
258 
259  /**********************************************************************************************/
260  /* 2. Save elements, that are compatible with all others */
261  /**********************************************************************************************/
262 
263  for( unsigned i=0; i < elements.size(); i++ ){
264 
265 
266  bool isCompatibleWithAll = true;
267 
268  //check if this track is compatible with all others
269  for( unsigned j=0; j < elements.size(); j++){
270 
271  //G[i][j] == 0 i and j are compatible, if G[i][j] == 1 i and j are incompatible
272  if( (i != j) && G[i][j] ){
273 
274  isCompatibleWithAll = false;
275  break;
276 
277  }
278 
279  }
280 
281 
282  if ( isCompatibleWithAll ){ //if it is compatible with all others, we don't need the Hopfield Neural Net, we can just save it
283 
284 
285  //add the track to the good ones
286  this->_acceptedElements.push_back( elements[i] );
287  nCompWithAll++;
288 
289 
290  //And now erase it from the ones we will still check:
291  elements.erase( elements.begin() + i );
292  states.erase( states.begin() + i );
293  QI.erase( QI.begin() + i );
294 
295  for( unsigned j=0; j<G.size(); j++ ) G[j].erase( G[j].begin() + i );
296  G.erase( G.begin() + i );
297 
298  i--;
299 
300  }
301  else{
302 
303  nIncompatible++;
304 
305  }
306 
307  }
308 
309 
310  streamlog_out( DEBUG3 ) << nCompWithAll << " elements are compatible with all others, " << nIncompatible
311  << " elements are interfering and will be checked for the best subset\n";
312 
313 
314 
315  /**********************************************************************************************/
316  /* 3. Let the Neural Network perform to find the best subset */
317  /**********************************************************************************************/
318 
319  if( !elements.empty() ){
320 
321  HopfieldNeuralNet net( G , QI , states , _omega);
322 
323  net.setT ( _TStart );
324  net.setTInf( _TInf );
325  net.setLimitForStable( _limitForStable );
326 
327  unsigned nIterations=1;
328 
329  streamlog_out(DEBUG1) << "states: ( ";
330  for ( unsigned int i=0; i< states.size(); i++) streamlog_out(DEBUG1) << states[i] << " ";
331  streamlog_out(DEBUG1) << ")\n";
332 
333  while ( !net.doIteration() ){ // while the Neural Net is not (yet) stable
334 
335  nIterations++;
336 
337  std::vector <double> newStates = net.getStates();
338 
339  streamlog_out(DEBUG1) << "states: ( ";
340 
341  for ( unsigned int i=0; i< newStates.size(); i++) streamlog_out(DEBUG1) << newStates[i] << " ";
342 
343  streamlog_out(DEBUG1) << ")\n";
344 
345  }
346 
347 
348 
349  streamlog_out( DEBUG3 ) << "Hopfield Neural Network is stable after " << nIterations << " iterations.\n";
350 
351 
352 
353 
354  /**********************************************************************************************/
355  /* 4. Now just sort the elements into accepted and rejected ones */
356  /**********************************************************************************************/
357 
358 
359  states = net.getStates();
360 
361 
362 
363  for ( unsigned i=0; i < states.size(); i++ ){
364 
365 
366  if ( states[i] >= _activationThreshold ){
367 
368  this->_acceptedElements.push_back( elements[i] );
369  nAccepted++;
370 
371  }
372  else{
373 
374  this->_rejectedElements.push_back( elements[i] );
375  nRejected++;
376 
377  }
378 
379  }
380 
381  }
382 
383 
384  streamlog_out( DEBUG3 ) << "Hopfield Neural Network accepted " << nAccepted
385  << " elements and rejected " << nRejected << " elements of all in all "
386  << nAccepted + nRejected << "incomaptible elements.\n";
387 
388  streamlog_out( DEBUG3 ) << "So in sum " << nAccepted + nCompWithAll
389  << " elements survived and " << nRejected << " elements got rejected.\n";
390 
391 
392  }
393 
394 
395 }
396 
397 
398 #endif
399 
void setT(double T)
Sets the temperature of the Neural Network (The HNN is cooled down in every iteration) ...
Definition: HopfieldNeuralNet.h:53
Represents a Hopfield Neural Network.
Definition: HopfieldNeuralNet.h:18
A base class for subsets.
Definition: Subset.h:19
std::vector< double > getStates()
Definition: HopfieldNeuralNet.h:71
bool doIteration()
Does one iteration of the neuronal network.
Definition: HopfieldNeuralNet.cc:165
A class to get the best subset with help of a Hopfield Neural Network.
Definition: SubsetHopfieldNN.h:17
void calculateBestSet(AreCompatible areCompatible, GetQI getQI)
Calculates the best set using a Hopfield Neural Network (see this for more info) .
Definition: SubsetHopfieldNN.h:146
void setLimitForStable(double limit)
Set the threshhold value below which the HNN is seen as "stable".
Definition: HopfieldNeuralNet.h:66
void setTInf(double TInf)
Sets the temperature at infinity.
Definition: HopfieldNeuralNet.h:59