ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4ConvergenceTester.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4ConvergenceTester.cc
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
26 //
27 //
28 // Convergence Tests for Monte Carlo results.
29 //
30 // Reference
31 // MCNP(TM) -A General Monte Carlo N-Particle Transport Code
32 // Version 4B
33 // Judith F. Briesmeister, Editor
34 // LA-12625-M, Issued: March 1997, UC 705 and UC 700
35 // CHAPTER 2. GEOMETRY, DATA, PHYSICS, AND MATHEMATICS
36 // VI. ESTIMATION OF THE MONTE CARLO PRECISION
37 //
38 // Positives numbers are assumed for inputs
39 //
40 // Koi, Tatsumi (SLAC/SCCS)
41 //
42 
43 #include "G4ConvergenceTester.hh"
44 #include <iomanip>
45 
47  : name(theName), n(0), sum(0.), mean(0.), var(0.), sd(0.), r(0.), efficiency(0.),
48  r2eff(0.), r2int(0.), shift(0.), vov(0.), fom(0.), largest(0.),
49  largest_score_happened(0), mean_1(0.), var_1(0.), sd_1(0.), r_1(0.),
50  shift_1(0.), vov_1(0.), fom_1(0.), noBinOfHistory(16), slope(0.),
51  noBinOfPDF(10), minimizer(0), noPass(0), noTotal(8), statsAreUpdated(true)
52  , showHistory(true) , calcSLOPE(true)
53 {
54  nonzero_histories.clear();
55  largest_scores.clear();
56  largest_scores.push_back( 0.0 );
57 
58  history_grid.resize( noBinOfHistory , 0 );
59  mean_history.resize( noBinOfHistory , 0.0 );
60  var_history.resize( noBinOfHistory , 0.0 );
61  sd_history.resize( noBinOfHistory , 0.0 );
62  r_history.resize( noBinOfHistory , 0.0 );
63  vov_history.resize( noBinOfHistory , 0.0 );
64  fom_history.resize( noBinOfHistory , 0.0 );
65  shift_history.resize( noBinOfHistory , 0.0 );
66  e_history.resize( noBinOfHistory , 0.0 );
67  r2eff_history.resize( noBinOfHistory , 0.0 );
68  r2int_history.resize( noBinOfHistory , 0.0 );
69 
70  timer = new G4Timer();
71  timer->Start();
72  cpu_time.clear();
73  cpu_time.push_back( 0.0 );
74 }
75 
76 
77 
79 {
80  delete timer;
81 }
82 
83 
84 
86 {
87 
88  //G4cout << x << G4endl;
89 
90  timer->Stop();
91  cpu_time.push_back( timer->GetSystemElapsed() + timer->GetUserElapsed() );
92 
93  if ( x < 0.0 ) {
94  G4cout << "Warning: G4convergenceTester expects zero or positive number as inputs, but received a negative number." << G4endl;
95  }
96 
97  if ( x == 0.0 )
98  {
99  }
100  else
101  {
102  nonzero_histories.insert( std::pair< G4int , G4double > ( n , x ) );
103  if ( x > largest_scores.back() )
104  {
105 // Following serch should become faster if begin from bottom.
106  std::vector< G4double >::iterator it;
107  for ( it = largest_scores.begin() ; it != largest_scores.end() ; it++ )
108  {
109  if ( x > *it )
110  {
111  largest_scores.insert( it , x );
112  break;
113  }
114  }
115 
116  if ( largest_scores.size() > 201 )
117  {
118  largest_scores.pop_back();
119  }
120  //G4cout << largest_scores.size() << " " << largest_scores.front() << " " << largest_scores.back() << G4endl;
121  }
122  sum += x;
123  }
124 
125  // Data has been added so statistics have not been updated to new values
126  statsAreUpdated = false;
127  n++;
128  return;
129 }
130 
131 
132 
134 {
135 
136  efficiency = double( nonzero_histories.size() ) / n;
137 
138  mean = sum / n;
139 
140  G4double sum_x2 = 0.0;
141  var = 0.0;
142  shift = 0.0;
143  vov = 0.0;
144 
145  G4double xi;
146  std::map< G4int , G4double >::iterator it;
147  for ( it = nonzero_histories.begin() ; it != nonzero_histories.end() ; it++ )
148  {
149  xi = it->second;
150  sum_x2 += xi * xi;
151  var += ( xi - mean ) * ( xi - mean );
152  shift += ( xi - mean ) * ( xi - mean ) * ( xi - mean );
153  vov += ( xi - mean ) * ( xi - mean ) * ( xi - mean ) * ( xi - mean );
154  }
155 
156  var += ( n - nonzero_histories.size() ) * mean * mean;
157  shift += ( n - nonzero_histories.size() ) * mean * mean * mean * ( -1 );
158  vov += ( n - nonzero_histories.size() ) * mean * mean * mean * mean;
159 
160  if ( var!=0.0 ) {
161 
162  vov = vov / ( var * var ) - 1.0 / n;
163 
164  var = var/(n-1);
165 
166  sd = std::sqrt ( var );
167 
168  r = sd / mean / std::sqrt ( G4double(n) );
169 
170  r2eff = ( 1 - efficiency ) / ( efficiency * n );
171  r2int = sum_x2 / ( sum * sum ) - 1 / ( efficiency * n );
172 
173  shift = shift / ( 2 * var * n );
174 
175  fom = 1 / (r*r) / cpu_time.back();
176  }
177 
178 // Find Largest History
179  //G4double largest = 0.0;
180  largest = 0.0;
182  G4double spend_time_of_largest = 0.0;
183  for ( it = nonzero_histories.begin() ; it != nonzero_histories.end() ; it++ )
184  {
185  if ( std::abs ( it->second ) > largest )
186  {
187  largest = it->second;
188  largest_score_happened = it->first;
189  spend_time_of_largest = cpu_time [ it->first+1 ] - cpu_time [ it->first ];
190  }
191  }
192 
193  mean_1 = 0.0;
194  var_1 = 0.0;
195  shift_1 = 0.0;
196  vov_1 = 0.0;
197  sd_1 = 0.0;
198  r_1 = 0.0;
199  vov_1 = 0.0;
200 
201 // G4cout << "The largest history = " << largest << G4endl;
202 
203  mean_1 = ( sum + largest ) / ( n + 1 );
204 
205  for ( it = nonzero_histories.begin() ; it != nonzero_histories.end() ; it++ )
206  {
207  xi = it->second;
208  var_1 += ( xi - mean_1 ) * ( xi - mean_1 );
209  shift_1 += ( xi - mean_1 ) * ( xi - mean_1 ) * ( xi - mean_1 );
210  vov_1 += ( xi - mean_1 ) * ( xi - mean_1 ) * ( xi - mean_1 ) * ( xi - mean_1 );
211  }
212  xi = largest;
213  var_1 += ( xi - mean_1 ) * ( xi - mean_1 );
214  shift_1 += ( xi - mean_1 ) * ( xi - mean_1 ) * ( xi - mean_1 );
215  vov_1 += ( xi - mean_1 ) * ( xi - mean_1 ) * ( xi - mean_1 ) * ( xi - mean_1 );
216 
217  var_1 += ( n - nonzero_histories.size() ) * mean_1 * mean_1;
218 
219  if ( var_1 != 0.0 ) {
220  shift_1 += ( n - nonzero_histories.size() ) * mean_1 * mean_1 * mean_1 * ( -1 );
221  vov_1 += ( n - nonzero_histories.size() ) * mean_1 * mean_1 * mean_1 * mean_1;
222 
223  vov_1 = vov_1 / ( var_1 * var_1 ) - 1.0 / ( n + 1 );
224 
225  var_1 = var_1 / n ;
226 
227  sd_1 = std::sqrt ( var_1 );
228 
229  r_1 = sd_1 / mean_1 / std::sqrt ( G4double(n + 1) );
230 
231  shift_1 = shift_1 / ( 2 * var_1 * ( n + 1 ) );
232 
233  fom_1 = 1 / ( r * r ) / ( cpu_time.back() + spend_time_of_largest );
234  }
235 
236  if ( nonzero_histories.size() < 500 )
237  {
238  calcSLOPE = false;
239  }
240  else
241  {
242  G4int i = int ( nonzero_histories.size() );
243 
244  // 5% criterion
245  G4int j = int ( i * 0.05 );
246  while ( int( largest_scores.size() ) > j )
247  {
248  largest_scores.pop_back();
249  }
251  }
252 
255 
256  // statistics have been calculated and this function does not need
257  // to be called again until data has been added
258  statsAreUpdated = true;
259 }
260 
261 
262 
264 {
265 
266 // histroy_grid [ 0,,,15 ]
267 // history_grid [0] 1/16 ,,, history_grid [15] 16/16
268 // if number of event is x then history_grid [15] become x-1.
269 // 16 -> noBinOfHisotry
270 
271  G4int i;
272  for ( i = 1 ; i <= noBinOfHistory ; i++ )
273  {
274  history_grid [ i-1 ] = int ( n / ( double( noBinOfHistory ) ) * i - 0.1 );
275  //G4cout << "history_grid " << i-1 << " " << history_grid [ i-1 ] << G4endl;
276  }
277 
278 }
279 
280 
281 
283 {
284 // G4cout << "i/16 till_ith mean var sd r vov fom shift e r2eff r2int" << G4endl;
285 
286  if ( history_grid [ 0 ] == 0 ) {
287  showHistory=false;
288  return;
289  }
290 
291  for (G4int i = 0 ; i < noBinOfHistory; ++i )
292  {
293 
294  G4int ith = history_grid [ i ];
295 
296  G4int nonzero_till_ith = 0;
297  G4double xi;
298  G4double mean_till_ith = 0.0;
299  std::map< G4int , G4double >::iterator it;
300 
301  for(const auto& itr : nonzero_histories)
302  {
303  if( itr.first <= ith )
304  {
305  xi = itr.second;
306  mean_till_ith += xi;
307  nonzero_till_ith++;
308  }
309  }
310 
311  if ( nonzero_till_ith == 0 )
312  continue;
313 
314  mean_till_ith = mean_till_ith / ( ith+1 );
315  mean_history [ i ] = mean_till_ith;
316 
317  G4double sum_x2_till_ith = 0.0;
318  G4double var_till_ith = 0.0;
319  G4double vov_till_ith = 0.0;
320  G4double shift_till_ith = 0.0;
321 
322  for(const auto& itr : nonzero_histories)
323  {
324  if ( itr.first <= ith )
325  {
326  xi = itr.second;
327  sum_x2_till_ith += std::pow( xi, 2.0 );
328  var_till_ith += std::pow( xi - mean_till_ith, 2.0 ) ;
329  shift_till_ith += std::pow( xi - mean_till_ith, 3.0 );
330  vov_till_ith += std::pow( xi - mean_till_ith, 4.0 );
331  }
332  }
333 
334  var_till_ith += ((ith+1) - nonzero_till_ith) * std::pow(mean_till_ith, 2.0);
335  vov_till_ith += ((ith+1) - nonzero_till_ith) * std::pow(mean_till_ith, 4.0);
336 
337  G4double sum_till_ith = mean_till_ith * (ith+1);
338 
339  if(!(std::fabs(var_till_ith) > 0.0))
340  continue;
341  if(!(std::fabs(mean_till_ith) > 0.0))
342  continue;
343  if(!(std::fabs(sum_till_ith) > 0.0))
344  continue;
345 
346  vov_till_ith = vov_till_ith
347  / std::pow( var_till_ith, 2.0 ) - 1.0 / (ith+1);
348  vov_history [ i ] = vov_till_ith;
349 
350  var_till_ith = var_till_ith / ( ith+1 - 1 );
351  var_history [ i ] = var_till_ith;
352  sd_history [ i ] = std::sqrt( var_till_ith );
353  r_history [ i ] = std::sqrt( var_till_ith )
354  / mean_till_ith
355  / std::sqrt ( 1.0*(ith+1) );
356 
357  if(std::fabs(cpu_time [ ith ]) > 0.0 && std::fabs(r_history [ i ]) > 0.0)
358  {
359  fom_history [ i ] = 1.0
360  / std::pow( r_history [ i ], 2.0 )
361  / cpu_time [ ith ];
362  }
363  else
364  {
365  fom_history [ i ] = 0.0;
366  }
367 
368  shift_till_ith += ((ith+1) - nonzero_till_ith) *
369  std::pow(mean_till_ith, 3.0) * ( -1.0 );
370  shift_till_ith = shift_till_ith
371  / ( 2 * var_till_ith * (ith+1) );
372  shift_history [ i ] = shift_till_ith;
373 
374  e_history [ i ] = 1.0 * nonzero_till_ith
375  / (ith+1);
376  if(std::fabs(e_history [ i ]) > 0.0)
377  {
378  r2eff_history [ i ] = ( 1 - e_history [ i ] )
379  / ( e_history [ i ] * (ith+1) );
380 
381  r2int_history [ i ] = ( sum_x2_till_ith )
382  / std::pow( sum_till_ith, 2.0 ) - 1
383  / ( e_history [ i ] * (ith+1) );
384  }
385 
386  }
387 
388 }
389 
390 
391 
392 void G4ConvergenceTester::ShowResult(std::ostream& out)
393 {
394  // if data has been added since the last computation of the statistical values (not statsAreUpdated)
395  // call calStat to recompute the statistical values
396  if(!statsAreUpdated) { calStat(); }
397 
398  out << std::setprecision( 6 );
399 
400  out << G4endl;
401  out << "G4ConvergenceTester Output Result of " << name << G4endl;
402  out << std::setw(20) << "EFFICIENCY = " << std::setw(13) << efficiency << G4endl;
403  out << std::setw(20) << "MEAN = " << std::setw(13) << mean << G4endl;
404  out << std::setw(20) << "VAR = " << std::setw(13) << var << G4endl;
405  out << std::setw(20) << "SD = " << std::setw(13) << sd << G4endl;
406  out << std::setw(20) << "R = " << std::setw(13) << r << G4endl;
407  out << std::setw(20) << "SHIFT = "<< std::setw(13) << shift << G4endl;
408  out << std::setw(20) << "VOV = "<< std::setw(13) << vov << G4endl;
409  out << std::setw(20) << "FOM = "<< std::setw(13) << fom << G4endl;
410 
411  out << std::setw(20) << "THE LARGEST SCORE = " << std::setw(13) << largest << " and it happened at " << largest_score_happened << "th event" << G4endl;
412  if ( mean!=0 ) {
413  out << std::setw(20) << "Affected Mean = " << std::setw(13) << mean_1 << " and its ratio to original is " << mean_1/mean << G4endl;
414  } else {
415  out << std::setw(20) << "Affected Mean = " << std::setw(13) << mean_1 << G4endl;
416  }
417  if ( var!=0 ) {
418  out << std::setw(20) << "Affected VAR = " << std::setw(13) << var_1 << " and its ratio to original is " << var_1/var << G4endl;
419  } else {
420  out << std::setw(20) << "Affected VAR = " << std::setw(13) << var_1 << G4endl;
421  }
422  if ( r!=0 ) {
423  out << std::setw(20) << "Affected R = " << std::setw(13) << r_1 << " and its ratio to original is " << r_1/r << G4endl;
424  } else {
425  out << std::setw(20) << "Affected R = " << std::setw(13) << r_1 << G4endl;
426  }
427  if ( shift!=0 ) {
428  out << std::setw(20) << "Affected SHIFT = " << std::setw(13) << shift_1 << " and its ratio to original is " << shift_1/shift << G4endl;
429  } else {
430  out << std::setw(20) << "Affected SHIFT = " << std::setw(13) << shift_1 << G4endl;
431  }
432  if ( fom!=0 ) {
433  out << std::setw(20) << "Affected FOM = " << std::setw(13) << fom_1 << " and its ratio to original is " << fom_1/fom << G4endl;
434  } else {
435  out << std::setw(20) << "Affected FOM = " << std::setw(13) << fom_1 << G4endl;
436  }
437 
438  if ( !showHistory ) {
439  out << "Number of events of this run is too small to do convergence tests." << G4endl;
440  return;
441  }
442 
443  check_stat_history(out);
444 
445 // check SLOPE and output result
446  if ( calcSLOPE ) {
447  if ( slope >= 3 )
448  {
449  noPass++;
450  out << "SLOPE is large enough" << G4endl;
451  }
452  else
453  {
454  out << "SLOPE is not large enough" << G4endl;
455  }
456  } else {
457  out << "Number of non zero history too small to calculate SLOPE" << G4endl;
458  }
459 
460  out << "This result passes " << noPass << " / "<< noTotal << " Convergence Test." << G4endl;
461  out << G4endl;
462 
463 }
464 
465 void G4ConvergenceTester::ShowHistory(std::ostream& out)
466 {
467 
468  if ( !showHistory ) {
469  out << "Number of events of this run is too small to show history." << G4endl;
470  return;
471  }
472 
473  out << std::setprecision( 6 );
474 
475  out << G4endl;
476  out << "G4ConvergenceTester Output History of " << name << G4endl;
477  out << "i/" << noBinOfHistory << " till_ith mean"
478  << std::setw(13) << "var"
479  << std::setw(13) << "sd"
480  << std::setw(13) << "r"
481  << std::setw(13) << "vov"
482  << std::setw(13) << "fom"
483  << std::setw(13) << "shift"
484  << std::setw(13) << "e"
485  << std::setw(13) << "r2eff"
486  << std::setw(13) << "r2int"
487  << G4endl;
488  for ( G4int i = 1 ; i <= noBinOfHistory ; i++ )
489  {
490  out << std::setw( 4) << i << " "
491  << std::setw( 5) << history_grid [ i-1 ]
492  << std::setw(13) << mean_history [ i-1 ]
493  << std::setw(13) << var_history [ i-1 ]
494  << std::setw(13) << sd_history [ i-1 ]
495  << std::setw(13) << r_history [ i-1 ]
496  << std::setw(13) << vov_history [ i-1 ]
497  << std::setw(13) << fom_history [ i-1 ]
498  << std::setw(13) << shift_history [ i-1 ]
499  << std::setw(13) << e_history [ i-1 ]
500  << std::setw(13) << r2eff_history [ i-1 ]
501  << std::setw(13) << r2int_history [ i-1 ]
502  << G4endl;
503  }
504 }
505 
507 {
508 
509 // 1 sigma rejection for null hypothesis
510 
511  std::vector<G4double> first_ally;
512  std::vector<G4double> second_ally;
513 
514 // use 2nd half of hisories
515  G4int N = mean_history.size() / 2;
516  G4int i;
517 
518  G4double pearson_r;
519  G4double t;
520 
521  first_ally.resize( N );
522  second_ally.resize( N );
523 
524 //
525  G4double sum_of_var = std::accumulate ( var_history.begin() , var_history.end() , 0.0 );
526  if ( sum_of_var == 0.0 ) {
527  out << "Variances in all historical grids are zero." << G4endl;
528  out << "Terminating checking behavior of statistics numbers." << G4endl;
529  return;
530  }
531 
532 // Mean
533 
534  for ( i = 0 ; i < N ; i++ )
535  {
536  first_ally [ i ] = history_grid [ N + i ];
537  second_ally [ i ] = mean_history [ N + i ];
538  }
539 
540  pearson_r = calc_Pearson_r ( N , first_ally , second_ally );
541  t = pearson_r * std::sqrt ( ( N - 2 ) / ( 1 - pearson_r * pearson_r ) );
542 
543  if ( t < 0.429318 ) // Student t of (Degree of freedom = N-2 )
544  {
545  out << "MEAN distribution is RANDOM" << G4endl;
546  noPass++;
547  }
548  else
549  {
550  out << "MEAN distribution is not RANDOM" << G4endl;
551  }
552 
553 
554 // R
555 
556  for ( i = 0 ; i < N ; i++ )
557  {
558  first_ally [ i ] = 1.0 / std::sqrt ( G4double(history_grid [ N + i ]) );
559  second_ally [ i ] = r_history [ N + i ];
560  }
561 
562  pearson_r = calc_Pearson_r ( N , first_ally , second_ally );
563  t = pearson_r * std::sqrt ( ( N - 2 ) / ( 1 - pearson_r * pearson_r ) );
564 
565  if ( t > 1.090546 )
566  {
567  out << "r follows 1/std::sqrt(N)" << G4endl;
568  noPass++;
569  }
570  else
571  {
572  out << "r does not follow 1/std::sqrt(N)" << G4endl;
573  }
574 
575  if ( is_monotonically_decrease( second_ally ) == true )
576  {
577  out << "r is monotonically decrease " << G4endl;
578  }
579  else
580  {
581  out << "r is NOT monotonically decrease " << G4endl;
582  }
583 
584  if ( r_history.back() < 0.1 )
585  {
586  out << "r is less than 0.1. r = " << r_history.back() << G4endl;
587  noPass++;
588  }
589  else
590  {
591  out << "r is NOT less than 0.1. r = " << r_history.back() << G4endl;
592  }
593 
594 
595 // VOV
596  for ( i = 0 ; i < N ; i++ )
597  {
598  first_ally [ i ] = 1.0 / history_grid [ N + i ];
599  second_ally [ i ] = vov_history [ N + i ];
600  }
601 
602  pearson_r = calc_Pearson_r ( N , first_ally , second_ally );
603  t = pearson_r * std::sqrt ( ( N - 2 ) / ( 1 - pearson_r * pearson_r ) );
604 
605  if ( t > 1.090546 )
606  {
607  out << "VOV follows 1/std::sqrt(N)" << G4endl;
608  noPass++;
609  }
610  else
611  {
612  out << "VOV does not follow 1/std::sqrt(N)" << G4endl;
613  }
614 
615  if ( is_monotonically_decrease( second_ally ) == true )
616  {
617  out << "VOV is monotonically decrease " << G4endl;
618  }
619  else
620  {
621  out << "VOV is NOT monotonically decrease " << G4endl;
622  }
623 
624 // FOM
625 
626  for ( i = 0 ; i < N ; i++ )
627  {
628  first_ally [ i ] = history_grid [ N + i ];
629  second_ally [ i ] = fom_history [ N + i ];
630  }
631 
632  pearson_r = calc_Pearson_r ( N , first_ally , second_ally );
633  t = pearson_r * std::sqrt ( ( N - 2 ) / ( 1 - pearson_r * pearson_r ) );
634 
635  if ( t < 0.429318 )
636  {
637  out << "FOM distribution is RANDOM" << G4endl;
638  noPass++;
639  }
640  else
641  {
642  out << "FOM distribution is not RANDOM" << G4endl;
643  }
644 
645 }
646 
647 
648 
649 G4double G4ConvergenceTester::calc_Pearson_r ( G4int N , std::vector<G4double> first_ally , std::vector<G4double> second_ally )
650 {
651  G4double first_mean = 0.0;
652  G4double second_mean = 0.0;
653 
654  G4int i;
655  for ( i = 0 ; i < N ; i++ )
656  {
657  first_mean += first_ally [ i ];
658  second_mean += second_ally [ i ];
659  }
660  first_mean = first_mean / N;
661  second_mean = second_mean / N;
662 
663  G4double a = 0.0;
664  for ( i = 0 ; i < N ; i++ )
665  {
666  a += ( first_ally [ i ] - first_mean ) * ( second_ally [ i ] - second_mean );
667  }
668 
669  G4double b1 = 0.0;
670  G4double b2 = 0.0;
671  for ( i = 0 ; i < N ; i++ )
672  {
673  b1 += ( first_ally [ i ] - first_mean ) * ( first_ally [ i ] - first_mean );
674  b2 += ( second_ally [ i ] - second_mean ) * ( second_ally [ i ] - second_mean );
675  }
676 
677  G4double rds = a / std::sqrt ( b1 * b2 );
678 
679  return rds;
680 }
681 
682 
683 
685 {
686 
687  std::vector<G4double>::iterator it;
688  for ( it = ally.begin() ; it != ally.end() - 1 ; it++ )
689  {
690  if ( *it < *(it+1) ) return FALSE;
691  }
692 
693  noPass++;
694  return TRUE;
695 }
696 
697 
698 
699 //void G4ConvergenceTester::calc_slope_fit ( std::vector<G4double> largest_socres )
700 void G4ConvergenceTester::calc_slope_fit ( std::vector<G4double> )
701 {
702 
703  // create PDF bins
704  G4double max = largest_scores.front();
705  G4int last = int ( largest_scores.size() );
706  G4double min = 0.0;
707  if ( largest_scores.back() != 0 )
708  {
709  min = largest_scores.back();
710  }
711  else
712  {
713  min = largest_scores[ last-1 ];
714  last = last - 1;
715  }
716 
717  //G4cout << "largest " << max << G4endl;
718  //G4cout << "last " << min << G4endl;
719 
720  if ( max*0.99 < min )
721  {
722  // upper limit is assumed to have been reached
723  slope = 10.0;
724  return;
725  }
726 
727  std::vector < G4double > pdf_grid;
728 
729  pdf_grid.resize( noBinOfPDF+1 ); // no grid = no bins + 1
730  pdf_grid[ 0 ] = max;
731  pdf_grid[ noBinOfPDF ] = min;
732  G4double log10_max = std::log10( max );
733  G4double log10_min = std::log10( min );
734  G4double log10_delta = log10_max - log10_min;
735  for ( G4int i = 1 ; i < noBinOfPDF ; i++ )
736  {
737  pdf_grid[i] = std::pow ( 10.0 , log10_max - log10_delta/10.0*(i) );
738  //G4cout << "pdf i " << i << " " << pdf_grid[i] << G4endl;
739  }
740 
741  std::vector < G4double > pdf;
742  pdf.resize( noBinOfPDF );
743 
744  for ( G4int j=0 ; j < last ; j ++ )
745  {
746  for ( G4int i = 0 ; i < 11 ; i++ )
747  {
748  if ( largest_scores[j] >= pdf_grid[i+1] )
749  {
750  pdf[i] += 1.0 / ( pdf_grid[i] - pdf_grid[i+1] ) / n;
751  //G4cout << "pdf " << j << " " << i << " " << largest_scores[j] << " " << G4endl;
752  break;
753  }
754  }
755  }
756 
757  f_xi.resize( noBinOfPDF );
758  f_yi.resize( noBinOfPDF );
759  for ( G4int i = 0 ; i < noBinOfPDF ; i++ )
760  {
761  //G4cout << "pdf i " << i << " " << (pdf_grid[i]+pdf_grid[i+1])/2 << " " << pdf[i] << G4endl;
762  f_xi[i] = (pdf_grid[i]+pdf_grid[i+1])/2;
763  f_yi[i] = pdf[i];
764  }
765 
766  // number of variables ( a and k )
768  //G4double minimum = minimizer->GetMinimum();
769  std::vector<G4double> mp = minimizer->GetMinimumPoint();
770  G4double k = mp[1];
771 
772  //G4cout << "SLOPE " << 1/mp[1]+1 << G4endl;
773  //G4cout << "SLOPE a " << mp[0] << G4endl;
774  //G4cout << "SLOPE k " << mp[1] << G4endl;
775  //G4cout << "SLOPE minimum " << minimizer->GetMinimum() << G4endl;
776 
777  slope = 1/mp[1]+1;
778  if ( k < 1.0/9 ) // Please look Pareto distribution with "sigma=a" and "k"
779  {
780  slope = 10;
781  }
782  if ( slope > 10 )
783  {
784  slope = 10;
785  }
786 }
787 
788 
789 
791 {
792 
793  G4double a = x[0];
794  G4double k = x[1];
795 
796  if ( a <= 0 )
797  {
798  return 3.402823466e+38; // FLOAT_MAX
799  }
800  if ( k == 0 )
801  {
802  return 3.402823466e+38; // FLOAT_MAX
803  }
804 
805 // f_xi and f_yi is filled at "calc_slope_fit"
806 
807  G4double y = 0.0;
808  G4int i;
809  for ( i = 0 ; i < int ( f_yi.size() ) ; i++ )
810  {
811  //if ( 1/a * ( 1 + k * f_xi [ i ] / a ) < 0 )
812  if ( ( 1 + k * f_xi [ i ] / a ) < 0 )
813  {
814  y +=3.402823466e+38; // FLOAT_MAX
815  }
816  else
817  {
818  y += ( f_yi [ i ] - 1/a*std::pow ( 1 + k * f_xi [ i ] / a , - 1/k - 1 ) ) * ( f_yi [ i ] - 1/a*std::pow ( 1 + k * f_xi [ i ] / a , - 1/k - 1 ) );
819  }
820  }
821 // G4cout << "y = " << y << G4endl;
822 
823  return y;
824 }