37 nonzero_histories.clear();
38 largest_scores.clear();
39 largest_scores.push_back(0.0);
41 history_grid.resize(noBinOfHistory, 0);
42 mean_history.resize(noBinOfHistory, 0.0);
43 var_history.resize(noBinOfHistory, 0.0);
44 sd_history.resize(noBinOfHistory, 0.0);
45 r_history.resize(noBinOfHistory, 0.0);
46 vov_history.resize(noBinOfHistory, 0.0);
47 fom_history.resize(noBinOfHistory, 0.0);
48 shift_history.resize(noBinOfHistory, 0.0);
49 e_history.resize(noBinOfHistory, 0.0);
50 r2eff_history.resize(noBinOfHistory, 0.0);
51 r2int_history.resize(noBinOfHistory, 0.0);
56 cpu_time.push_back(0.0);
70 G4cout <<
"Warning: G4convergenceTester expects zero or positive number as "
71 "inputs, but received a negative number."
80 nonzero_histories.insert(std::pair<G4int, G4double>(n, x));
81 if(x > largest_scores.back())
84 std::vector<G4double>::iterator it;
85 for(it = largest_scores.begin(); it != largest_scores.end(); it++)
89 largest_scores.insert(it, x);
94 if(largest_scores.size() > 201)
96 largest_scores.pop_back();
103 statsAreUpdated =
false;
108void G4ConvergenceTester::calStat()
110 efficiency = double(nonzero_histories.size()) / n;
120 for(
auto it = nonzero_histories.cbegin(); it != nonzero_histories.cend();
125 var += (xi - mean) * (xi - mean);
126 shift += (xi - mean) * (xi - mean) * (xi - mean);
127 vov += (xi - mean) * (xi - mean) * (xi - mean) * (xi - mean);
130 var += (n - nonzero_histories.size()) * mean * mean;
131 shift += (n - nonzero_histories.size()) * mean * mean * mean * (-1);
132 vov += (n - nonzero_histories.size()) * mean * mean * mean * mean;
136 vov = vov / (var * var) - 1.0 / n;
142 r = sd / mean / std::sqrt(
G4double(n));
144 r2eff = (1 - efficiency) / (efficiency * n);
145 r2int = sum_x2 / (sum * sum) - 1 / (efficiency * n);
147 shift = shift / (2 * var *
n);
149 fom = 1 / (r * r) / cpu_time.back();
155 largest_score_happened = 0;
156 G4double spend_time_of_largest = 0.0;
157 for(
auto it = nonzero_histories.cbegin(); it != nonzero_histories.cend();
160 if(std::abs(it->second) > largest)
162 largest = it->second;
163 largest_score_happened = it->first;
164 spend_time_of_largest = cpu_time[it->first + 1] - cpu_time[it->first];
178 mean_1 = (sum + largest) / (n + 1);
180 for(
auto it = nonzero_histories.cbegin(); it != nonzero_histories.cend();
184 var_1 += (xi - mean_1) * (xi - mean_1);
185 shift_1 += (xi - mean_1) * (xi - mean_1) * (xi - mean_1);
186 vov_1 += (xi - mean_1) * (xi - mean_1) * (xi - mean_1) * (xi - mean_1);
189 var_1 += (xi - mean_1) * (xi - mean_1);
190 shift_1 += (xi - mean_1) * (xi - mean_1) * (xi - mean_1);
191 vov_1 += (xi - mean_1) * (xi - mean_1) * (xi - mean_1) * (xi - mean_1);
193 var_1 += (
n - nonzero_histories.size()) * mean_1 * mean_1;
197 shift_1 += (
n - nonzero_histories.size()) * mean_1 * mean_1 * mean_1 * (-1);
198 vov_1 += (
n - nonzero_histories.size()) * mean_1 * mean_1 * mean_1 * mean_1;
200 vov_1 = vov_1 / (var_1 * var_1) - 1.0 / (n + 1);
204 sd_1 = std::sqrt(var_1);
206 r_1 = sd_1 / mean_1 / std::sqrt(
G4double(n + 1));
208 shift_1 = shift_1 / (2 * var_1 * (
n + 1));
210 fom_1 = 1 / (r * r) / (cpu_time.back() + spend_time_of_largest);
213 if(nonzero_histories.size() < 500)
223 while(
G4int(largest_scores.size()) > j)
225 largest_scores.pop_back();
227 calc_slope_fit(largest_scores);
230 calc_grid_point_of_history();
235 statsAreUpdated =
true;
238void G4ConvergenceTester::calc_grid_point_of_history()
245 for(
G4int i = 1; i <= noBinOfHistory; ++i)
247 history_grid[i - 1] =
G4int(n / (
G4double(noBinOfHistory)) * i - 0.1);
253void G4ConvergenceTester::calc_stat_history()
258 if(history_grid[0] == 0)
264 for(
G4int i = 0; i < noBinOfHistory; ++i)
266 G4int ith = history_grid[i];
268 G4int nonzero_till_ith = 0;
272 for(
const auto& itr : nonzero_histories)
282 if(nonzero_till_ith == 0)
285 mean_till_ith = mean_till_ith / (ith + 1);
286 mean_history[i] = mean_till_ith;
293 for(
const auto& itr : nonzero_histories)
298 sum_x2_till_ith += std::pow(xi, 2.0);
299 var_till_ith += std::pow(xi - mean_till_ith, 2.0);
300 shift_till_ith += std::pow(xi - mean_till_ith, 3.0);
301 vov_till_ith += std::pow(xi - mean_till_ith, 4.0);
306 ((ith + 1) - nonzero_till_ith) * std::pow(mean_till_ith, 2.0);
308 ((ith + 1) - nonzero_till_ith) * std::pow(mean_till_ith, 4.0);
310 G4double sum_till_ith = mean_till_ith * (ith + 1);
312 if(!(std::fabs(var_till_ith) > 0.0))
314 if(!(std::fabs(mean_till_ith) > 0.0))
316 if(!(std::fabs(sum_till_ith) > 0.0))
319 vov_till_ith = vov_till_ith / std::pow(var_till_ith, 2.0) - 1.0 / (ith + 1);
320 vov_history[i] = vov_till_ith;
322 var_till_ith = var_till_ith / (ith + 1 - 1);
323 var_history[i] = var_till_ith;
324 sd_history[i] = std::sqrt(var_till_ith);
326 std::sqrt(var_till_ith) / mean_till_ith / std::sqrt(1.0 * (ith + 1));
328 if(std::fabs(cpu_time[ith]) > 0.0 && std::fabs(r_history[i]) > 0.0)
330 fom_history[i] = 1.0 / std::pow(r_history[i], 2.0) / cpu_time[ith];
334 fom_history[i] = 0.0;
338 ((ith + 1) - nonzero_till_ith) * std::pow(mean_till_ith, 3.0) * (-1.0);
339 shift_till_ith = shift_till_ith / (2 * var_till_ith * (ith + 1));
340 shift_history[i] = shift_till_ith;
342 e_history[i] = 1.0 * nonzero_till_ith / (ith + 1);
343 if(std::fabs(e_history[i]) > 0.0)
345 r2eff_history[i] = (1 - e_history[i]) / (e_history[i] * (ith + 1));
347 r2int_history[i] = (sum_x2_till_ith) / std::pow(sum_till_ith, 2.0) -
348 1 / (e_history[i] * (ith + 1));
362 out << std::setprecision(6);
365 out <<
"G4ConvergenceTester Output Result of " << name <<
G4endl;
366 out << std::setw(20) <<
"EFFICIENCY = " << std::setw(13) << efficiency
368 out << std::setw(20) <<
"MEAN = " << std::setw(13) << mean <<
G4endl;
369 out << std::setw(20) <<
"VAR = " << std::setw(13) << var <<
G4endl;
370 out << std::setw(20) <<
"SD = " << std::setw(13) << sd <<
G4endl;
371 out << std::setw(20) <<
"R = " << std::setw(13) << r <<
G4endl;
372 out << std::setw(20) <<
"SHIFT = " << std::setw(13) << shift <<
G4endl;
373 out << std::setw(20) <<
"VOV = " << std::setw(13) << vov <<
G4endl;
374 out << std::setw(20) <<
"FOM = " << std::setw(13) << fom <<
G4endl;
376 out << std::setw(20) <<
"THE LARGEST SCORE = " << std::setw(13) << largest
377 <<
" and it happened at " << largest_score_happened <<
"th event"
381 out << std::setw(20) <<
"Affected Mean = " << std::setw(13) << mean_1
382 <<
" and its ratio to original is " << mean_1 / mean <<
G4endl;
386 out << std::setw(20) <<
"Affected Mean = " << std::setw(13) << mean_1
391 out << std::setw(20) <<
"Affected VAR = " << std::setw(13) << var_1
392 <<
" and its ratio to original is " << var_1 / var <<
G4endl;
396 out << std::setw(20) <<
"Affected VAR = " << std::setw(13) << var_1
401 out << std::setw(20) <<
"Affected R = " << std::setw(13) << r_1
402 <<
" and its ratio to original is " << r_1 / r <<
G4endl;
406 out << std::setw(20) <<
"Affected R = " << std::setw(13) << r_1 <<
G4endl;
410 out << std::setw(20) <<
"Affected SHIFT = " << std::setw(13) << shift_1
411 <<
" and its ratio to original is " << shift_1 / shift <<
G4endl;
415 out << std::setw(20) <<
"Affected SHIFT = " << std::setw(13) << shift_1
420 out << std::setw(20) <<
"Affected FOM = " << std::setw(13) << fom_1
421 <<
" and its ratio to original is " << fom_1 / fom <<
G4endl;
425 out << std::setw(20) <<
"Affected FOM = " << std::setw(13) << fom_1
431 out <<
"Number of events of this run is too small to do convergence tests."
436 check_stat_history(out);
444 out <<
"SLOPE is large enough" <<
G4endl;
448 out <<
"SLOPE is not large enough" <<
G4endl;
453 out <<
"Number of non zero history too small to calculate SLOPE" <<
G4endl;
456 out <<
"This result passes " << noPass <<
" / " << noTotal
457 <<
" Convergence Test." <<
G4endl;
465 out <<
"Number of events of this run is too small to show history."
470 out << std::setprecision(6);
473 out <<
"G4ConvergenceTester Output History of " << name <<
G4endl;
474 out <<
"i/" << noBinOfHistory <<
" till_ith mean" << std::setw(13)
475 <<
"var" << std::setw(13) <<
"sd" << std::setw(13) <<
"r" << std::setw(13)
476 <<
"vov" << std::setw(13) <<
"fom" << std::setw(13) <<
"shift"
477 << std::setw(13) <<
"e" << std::setw(13) <<
"r2eff" << std::setw(13)
479 for(
G4int i = 1; i <= noBinOfHistory; i++)
481 out << std::setw(4) << i <<
" " << std::setw(5) << history_grid[i - 1]
482 << std::setw(13) << mean_history[i - 1] << std::setw(13)
483 << var_history[i - 1] << std::setw(13) << sd_history[i - 1]
484 << std::setw(13) << r_history[i - 1] << std::setw(13)
485 << vov_history[i - 1] << std::setw(13) << fom_history[i - 1]
486 << std::setw(13) << shift_history[i - 1] << std::setw(13)
487 << e_history[i - 1] << std::setw(13) << r2eff_history[i - 1]
488 << std::setw(13) << r2int_history[i - 1] <<
G4endl;
492void G4ConvergenceTester::check_stat_history(std::ostream& out)
496 std::vector<G4double> first_ally;
497 std::vector<G4double> second_ally;
500 G4int N = mean_history.size() / 2;
506 first_ally.resize(N);
507 second_ally.resize(N);
511 std::accumulate(var_history.begin(), var_history.end(), 0.0);
512 if(sum_of_var == 0.0)
514 out <<
"Variances in all historical grids are zero." <<
G4endl;
515 out <<
"Terminating checking behavior of statistics numbers." <<
G4endl;
521 for(i = 0; i < N; ++i)
523 first_ally[i] = history_grid[N + i];
524 second_ally[i] = mean_history[N + i];
527 pearson_r = calc_Pearson_r(N, first_ally, second_ally);
528 t = pearson_r * std::sqrt((N - 2) / (1 - pearson_r * pearson_r));
532 out <<
"MEAN distribution is RANDOM" <<
G4endl;
537 out <<
"MEAN distribution is not RANDOM" <<
G4endl;
542 for(i = 0; i < N; ++i)
544 first_ally[i] = 1.0 / std::sqrt(
G4double(history_grid[N + i]));
545 second_ally[i] = r_history[N + i];
548 pearson_r = calc_Pearson_r(N, first_ally, second_ally);
549 t = pearson_r * std::sqrt((N - 2) / (1 - pearson_r * pearson_r));
553 out <<
"r follows 1/std::sqrt(N)" <<
G4endl;
558 out <<
"r does not follow 1/std::sqrt(N)" <<
G4endl;
561 if(is_monotonically_decrease(second_ally) ==
true)
563 out <<
"r is monotonically decrease " <<
G4endl;
567 out <<
"r is NOT monotonically decrease " <<
G4endl;
570 if(r_history.back() < 0.1)
572 out <<
"r is less than 0.1. r = " << r_history.back() <<
G4endl;
577 out <<
"r is NOT less than 0.1. r = " << r_history.back() <<
G4endl;
581 for(i = 0; i < N; ++i)
583 first_ally[i] = 1.0 / history_grid[N + i];
584 second_ally[i] = vov_history[N + i];
587 pearson_r = calc_Pearson_r(N, first_ally, second_ally);
588 t = pearson_r * std::sqrt((N - 2) / (1 - pearson_r * pearson_r));
592 out <<
"VOV follows 1/std::sqrt(N)" <<
G4endl;
597 out <<
"VOV does not follow 1/std::sqrt(N)" <<
G4endl;
600 if(is_monotonically_decrease(second_ally) ==
true)
602 out <<
"VOV is monotonically decrease " <<
G4endl;
606 out <<
"VOV is NOT monotonically decrease " <<
G4endl;
611 for(i = 0; i < N; ++i)
613 first_ally[i] = history_grid[N + i];
614 second_ally[i] = fom_history[N + i];
617 pearson_r = calc_Pearson_r(N, first_ally, second_ally);
618 t = pearson_r * std::sqrt((N - 2) / (1 - pearson_r * pearson_r));
622 out <<
"FOM distribution is RANDOM" <<
G4endl;
627 out <<
"FOM distribution is not RANDOM" <<
G4endl;
632 std::vector<G4double> first_ally,
633 std::vector<G4double> second_ally)
639 for(i = 0; i < N; i++)
641 first_mean += first_ally[i];
642 second_mean += second_ally[i];
644 first_mean = first_mean / N;
645 second_mean = second_mean / N;
648 for(i = 0; i < N; ++i)
650 a += (first_ally[i] - first_mean) * (second_ally[i] - second_mean);
655 for(i = 0; i < N; ++i)
657 b1 += (first_ally[i] - first_mean) * (first_ally[i] - first_mean);
658 b2 += (second_ally[i] - second_mean) * (second_ally[i] - second_mean);
661 G4double rds = a / std::sqrt(b1 * b2);
666G4bool G4ConvergenceTester::is_monotonically_decrease(
667 std::vector<G4double> ally)
669 for(
auto it = ally.cbegin(); it != ally.cend() - 1; ++it)
681void G4ConvergenceTester::calc_slope_fit(std::vector<G4double>)
687 if(largest_scores.back() != 0)
689 min = largest_scores.back();
693 min = largest_scores[last - 1];
707 std::vector<G4double> pdf_grid;
709 pdf_grid.resize(noBinOfPDF + 1);
711 pdf_grid[noBinOfPDF] =
min;
712 G4double log10_max = std::log10(max);
713 G4double log10_min = std::log10(min);
714 G4double log10_delta = log10_max - log10_min;
715 for(
G4int i = 1; i < noBinOfPDF; ++i)
717 pdf_grid[i] = std::pow(10.0, log10_max - log10_delta / 10.0 * (i));
721 std::vector<G4double> pdf;
722 pdf.resize(noBinOfPDF);
724 for(
G4int j = 0; j < last; ++j)
726 for(
G4int i = 0; i < 11; ++i)
728 if(largest_scores[j] >= pdf_grid[i + 1])
730 pdf[i] += 1.0 / (pdf_grid[i] - pdf_grid[i + 1]) / n;
739 f_xi.resize(noBinOfPDF);
740 f_yi.resize(noBinOfPDF);
741 for(
G4int i = 0; i < noBinOfPDF; ++i)
745 f_xi[i] = (pdf_grid[i] + pdf_grid[i + 1]) / 2;
760 slope = 1 / mp[1] + 1;
771G4double G4ConvergenceTester::slope_fitting_function(std::vector<G4double> x)
778 return 3.402823466e+38;
782 return 3.402823466e+38;
791 if((1 + k * f_xi[i] / a) < 0)
793 y += 3.402823466e+38;
797 y += (f_yi[i] - 1 / a * std::pow(1 + k * f_xi[i] / a, -1 / k - 1)) *
798 (f_yi[i] - 1 / a * std::pow(1 + k * f_xi[i] / a, -1 / k - 1));
G4GLOB_DLL std::ostream G4cout
G4ConvergenceTester(G4String theName="NONAME")
void ShowResult(std::ostream &out=G4cout)
void ShowHistory(std::ostream &out=G4cout)
std::vector< G4double > GetMinimumPoint()
G4double GetSystemElapsed() const
G4double GetUserElapsed() const
T max(const T t1, const T t2)
brief Return the largest of the two arguments
T min(const T t1, const T t2)
brief Return the smallest of the two arguments