43 nonzero_histories.clear();
44 largest_scores.clear();
45 largest_scores.push_back(0.0);
47 history_grid.resize(noBinOfHistory, 0);
48 mean_history.resize(noBinOfHistory, 0.0);
49 var_history.resize(noBinOfHistory, 0.0);
50 sd_history.resize(noBinOfHistory, 0.0);
51 r_history.resize(noBinOfHistory, 0.0);
52 vov_history.resize(noBinOfHistory, 0.0);
53 fom_history.resize(noBinOfHistory, 0.0);
54 shift_history.resize(noBinOfHistory, 0.0);
55 e_history.resize(noBinOfHistory, 0.0);
56 r2eff_history.resize(noBinOfHistory, 0.0);
57 r2int_history.resize(noBinOfHistory, 0.0);
62 cpu_time.push_back(0.0);
79 std::ostringstream message;
80 message <<
"Expecting zero or positive number as inputs,\n"
81 <<
"but received a negative number.";
82 G4Exception(
"G4ConvergenceTester::AddScore()",
"Warning",
91 nonzero_histories.insert(std::pair<G4int, G4double>(n, x));
92 if(x > largest_scores.back())
95 for(
auto it = largest_scores.begin(); it != largest_scores.end(); ++it)
99 largest_scores.insert(it, x);
104 if(largest_scores.size() > 201)
106 largest_scores.pop_back();
113 statsAreUpdated =
false;
119void G4ConvergenceTester::calStat()
121 efficiency =
G4double(nonzero_histories.size()) / n;
131 for(
const auto& nonzero_historie : nonzero_histories)
133 xi = nonzero_historie.second;
135 var += (xi - mean) * (xi - mean);
136 shift += (xi - mean) * (xi - mean) * (xi - mean);
137 vov += (xi - mean) * (xi - mean) * (xi - mean) * (xi - mean);
140 var += (n - nonzero_histories.size()) * mean * mean;
141 shift += (n - nonzero_histories.size()) * mean * mean * mean * (-1);
142 vov += (n - nonzero_histories.size()) * mean * mean * mean * mean;
146 vov = vov / (var * var) - 1.0 / n;
152 r = sd / mean / std::sqrt(
G4double(n));
154 r2eff = (1 - efficiency) / (efficiency * n);
155 r2int = sum_x2 / (sum * sum) - 1 / (efficiency * n);
157 shift = shift / (2 * var *
n);
159 fom = 1 / (r * r) / cpu_time.back();
165 largest_score_happened = 0;
166 G4double spend_time_of_largest = 0.0;
167 for(
const auto& nonzero_historie : nonzero_histories)
169 if(std::abs(nonzero_historie.second) > largest)
171 largest = nonzero_historie.second;
172 largest_score_happened = nonzero_historie.first;
173 spend_time_of_largest =
174 cpu_time[nonzero_historie.first + 1] - cpu_time[nonzero_historie.first];
186 mean_1 = (sum + largest) / (n + 1);
188 for(
const auto& nonzero_historie : nonzero_histories)
190 xi = nonzero_historie.second;
191 var_1 += (xi - mean_1) * (xi - mean_1);
192 shift_1 += (xi - mean_1) * (xi - mean_1) * (xi - mean_1);
193 vov_1 += (xi - mean_1) * (xi - mean_1) * (xi - mean_1) * (xi - mean_1);
196 var_1 += (xi - mean_1) * (xi - mean_1);
197 shift_1 += (xi - mean_1) * (xi - mean_1) * (xi - mean_1);
198 vov_1 += (xi - mean_1) * (xi - mean_1) * (xi - mean_1) * (xi - mean_1);
200 var_1 += (
n - nonzero_histories.size()) * mean_1 * mean_1;
204 shift_1 += (
n - nonzero_histories.size()) * mean_1 * mean_1 * mean_1 * (-1);
205 vov_1 += (
n - nonzero_histories.size()) * mean_1 * mean_1 * mean_1 * mean_1;
207 vov_1 = vov_1 / (var_1 * var_1) - 1.0 / (n + 1);
211 sd_1 = std::sqrt(var_1);
213 r_1 = sd_1 / mean_1 / std::sqrt(
G4double(n + 1));
215 shift_1 = shift_1 / (2 * var_1 * (
n + 1));
217 fom_1 = 1 / (r * r) / (cpu_time.back() + spend_time_of_largest);
220 if(nonzero_histories.size() < 500)
230 while(
G4int(largest_scores.size()) > j)
232 largest_scores.pop_back();
234 calc_slope_fit(largest_scores);
237 calc_grid_point_of_history();
242 statsAreUpdated =
true;
245void G4ConvergenceTester::calc_grid_point_of_history()
252 for(
G4int i = 1; i <= noBinOfHistory; ++i)
254 history_grid[i - 1] =
G4int(n / (
G4double(noBinOfHistory)) * i - 0.1);
258void G4ConvergenceTester::calc_stat_history()
260 if(history_grid[0] == 0)
266 for(
G4int i = 0; i < noBinOfHistory; ++i)
268 G4int ith = history_grid[i];
270 G4int nonzero_till_ith = 0;
274 for(
const auto& itr : nonzero_histories)
284 if(nonzero_till_ith == 0)
289 mean_till_ith = mean_till_ith / (ith + 1);
290 mean_history[i] = mean_till_ith;
297 for(
const auto& itr : nonzero_histories)
302 sum_x2_till_ith += std::pow(xi, 2.0);
303 var_till_ith += std::pow(xi - mean_till_ith, 2.0);
304 shift_till_ith += std::pow(xi - mean_till_ith, 3.0);
305 vov_till_ith += std::pow(xi - mean_till_ith, 4.0);
310 ((ith + 1) - nonzero_till_ith) * std::pow(mean_till_ith, 2.0);
312 ((ith + 1) - nonzero_till_ith) * std::pow(mean_till_ith, 4.0);
314 G4double sum_till_ith = mean_till_ith * (ith + 1);
316 if(!(std::fabs(var_till_ith) > 0.0))
320 if(!(std::fabs(mean_till_ith) > 0.0))
324 if(!(std::fabs(sum_till_ith) > 0.0))
329 vov_till_ith = vov_till_ith / std::pow(var_till_ith, 2.0) - 1.0 / (ith + 1);
330 vov_history[i] = vov_till_ith;
332 var_till_ith = var_till_ith / (ith + 1 - 1);
333 var_history[i] = var_till_ith;
334 sd_history[i] = std::sqrt(var_till_ith);
336 std::sqrt(var_till_ith) / mean_till_ith / std::sqrt(1.0 * (ith + 1));
338 if(std::fabs(cpu_time[ith]) > 0.0 && std::fabs(r_history[i]) > 0.0)
340 fom_history[i] = 1.0 / std::pow(r_history[i], 2.0) / cpu_time[ith];
344 fom_history[i] = 0.0;
348 ((ith + 1) - nonzero_till_ith) * std::pow(mean_till_ith, 3.0) * (-1.0);
349 shift_till_ith = shift_till_ith / (2 * var_till_ith * (ith + 1));
350 shift_history[i] = shift_till_ith;
352 e_history[i] = 1.0 * nonzero_till_ith / (ith + 1);
353 if(std::fabs(e_history[i]) > 0.0)
355 r2eff_history[i] = (1 - e_history[i]) / (e_history[i] * (ith + 1));
357 r2int_history[i] = (sum_x2_till_ith) / std::pow(sum_till_ith, 2.0) -
358 1 / (e_history[i] * (ith + 1));
372 out << std::setprecision(6);
375 out <<
"G4ConvergenceTester Output Result of " << name <<
G4endl;
376 out << std::setw(20) <<
"EFFICIENCY = " << std::setw(13) << efficiency
378 out << std::setw(20) <<
"MEAN = " << std::setw(13) << mean <<
G4endl;
379 out << std::setw(20) <<
"VAR = " << std::setw(13) << var <<
G4endl;
380 out << std::setw(20) <<
"SD = " << std::setw(13) << sd <<
G4endl;
381 out << std::setw(20) <<
"R = " << std::setw(13) << r <<
G4endl;
382 out << std::setw(20) <<
"SHIFT = " << std::setw(13) << shift <<
G4endl;
383 out << std::setw(20) <<
"VOV = " << std::setw(13) << vov <<
G4endl;
384 out << std::setw(20) <<
"FOM = " << std::setw(13) << fom <<
G4endl;
386 out << std::setw(20) <<
"THE LARGEST SCORE = " << std::setw(13) << largest
387 <<
" and it happened at " << largest_score_happened <<
"th event"
391 out << std::setw(20) <<
"Affected Mean = " << std::setw(13) << mean_1
392 <<
" and its ratio to original is " << mean_1 / mean <<
G4endl;
396 out << std::setw(20) <<
"Affected Mean = " << std::setw(13) << mean_1
401 out << std::setw(20) <<
"Affected VAR = " << std::setw(13) << var_1
402 <<
" and its ratio to original is " << var_1 / var <<
G4endl;
406 out << std::setw(20) <<
"Affected VAR = " << std::setw(13) << var_1
411 out << std::setw(20) <<
"Affected R = " << std::setw(13) << r_1
412 <<
" and its ratio to original is " << r_1 / r <<
G4endl;
416 out << std::setw(20) <<
"Affected R = " << std::setw(13) << r_1 <<
G4endl;
420 out << std::setw(20) <<
"Affected SHIFT = " << std::setw(13) << shift_1
421 <<
" and its ratio to original is " << shift_1 / shift <<
G4endl;
425 out << std::setw(20) <<
"Affected SHIFT = " << std::setw(13) << shift_1
430 out << std::setw(20) <<
"Affected FOM = " << std::setw(13) << fom_1
431 <<
" and its ratio to original is " << fom_1 / fom <<
G4endl;
435 out << std::setw(20) <<
"Affected FOM = " << std::setw(13) << fom_1
441 out <<
"Number of events of this run is too small to do convergence tests."
446 check_stat_history(out);
454 out <<
"SLOPE is large enough" <<
G4endl;
458 out <<
"SLOPE is not large enough" <<
G4endl;
463 out <<
"Number of non zero history too small to calculate SLOPE" <<
G4endl;
466 out <<
"This result passes " << noPass <<
" / " << noTotal
467 <<
" Convergence Test." <<
G4endl;
475 out <<
"Number of events of this run is too small to show history."
480 out << std::setprecision(6);
483 out <<
"G4ConvergenceTester Output History of " << name <<
G4endl;
484 out <<
"i/" << noBinOfHistory <<
" till_ith mean" << std::setw(13)
485 <<
"var" << std::setw(13) <<
"sd" << std::setw(13) <<
"r" << std::setw(13)
486 <<
"vov" << std::setw(13) <<
"fom" << std::setw(13) <<
"shift"
487 << std::setw(13) <<
"e" << std::setw(13) <<
"r2eff" << std::setw(13)
489 for(
G4int i = 1; i <= noBinOfHistory; i++)
491 out << std::setw(4) << i <<
" " << std::setw(5) << history_grid[i - 1]
492 << std::setw(13) << mean_history[i - 1] << std::setw(13)
493 << var_history[i - 1] << std::setw(13) << sd_history[i - 1]
494 << std::setw(13) << r_history[i - 1] << std::setw(13)
495 << vov_history[i - 1] << std::setw(13) << fom_history[i - 1]
496 << std::setw(13) << shift_history[i - 1] << std::setw(13)
497 << e_history[i - 1] << std::setw(13) << r2eff_history[i - 1]
498 << std::setw(13) << r2int_history[i - 1] <<
G4endl;
502void G4ConvergenceTester::check_stat_history(std::ostream& out)
506 std::vector<G4double> first_ally;
507 std::vector<G4double> second_ally;
510 std::size_t
N = mean_history.size() / 2;
516 first_ally.resize(
N);
517 second_ally.resize(
N);
520 std::accumulate(var_history.begin(), var_history.end(), 0.0);
521 if(sum_of_var == 0.0)
523 out <<
"Variances in all historical grids are zero." <<
G4endl;
524 out <<
"Terminating checking behavior of statistics numbers." <<
G4endl;
530 for(i = 0; i <
N; ++i)
532 first_ally[i] = history_grid[
N + i];
533 second_ally[i] = mean_history[
N + i];
536 pearson_r = calc_Pearson_r((
G4int)
N, first_ally, second_ally);
537 t = pearson_r * std::sqrt((
N - 2) / (1 - pearson_r * pearson_r));
541 out <<
"MEAN distribution is RANDOM" <<
G4endl;
546 out <<
"MEAN distribution is not RANDOM" <<
G4endl;
551 for(i = 0; i <
N; ++i)
553 first_ally[i] = 1.0 / std::sqrt(
G4double(history_grid[
N + i]));
554 second_ally[i] = r_history[
N + i];
557 pearson_r = calc_Pearson_r(
G4int(
N), first_ally, second_ally);
558 t = pearson_r * std::sqrt((
N - 2) / (1 - pearson_r * pearson_r));
562 out <<
"r follows 1/std::sqrt(N)" <<
G4endl;
567 out <<
"r does not follow 1/std::sqrt(N)" <<
G4endl;
570 if(is_monotonically_decrease(second_ally))
572 out <<
"r is monotonically decrease " <<
G4endl;
576 out <<
"r is NOT monotonically decrease " <<
G4endl;
579 if(r_history.back() < 0.1)
581 out <<
"r is less than 0.1. r = " << r_history.back() <<
G4endl;
586 out <<
"r is NOT less than 0.1. r = " << r_history.back() <<
G4endl;
590 for(i = 0; i <
N; ++i)
592 first_ally[i] = 1.0 / history_grid[
N + i];
593 second_ally[i] = vov_history[
N + i];
596 pearson_r = calc_Pearson_r(
G4int(
N), first_ally, second_ally);
597 t = pearson_r * std::sqrt((
N - 2) / (1 - pearson_r * pearson_r));
601 out <<
"VOV follows 1/std::sqrt(N)" <<
G4endl;
606 out <<
"VOV does not follow 1/std::sqrt(N)" <<
G4endl;
609 if(is_monotonically_decrease(second_ally))
611 out <<
"VOV is monotonically decrease " <<
G4endl;
615 out <<
"VOV is NOT monotonically decrease " <<
G4endl;
620 for(i = 0; i <
N; ++i)
622 first_ally[i] = history_grid[
N + i];
623 second_ally[i] = fom_history[
N + i];
626 pearson_r = calc_Pearson_r(
G4int(
N), first_ally, second_ally);
627 t = pearson_r * std::sqrt((
N - 2) / (1 - pearson_r * pearson_r));
631 out <<
"FOM distribution is RANDOM" <<
G4endl;
636 out <<
"FOM distribution is not RANDOM" <<
G4endl;
641 std::vector<G4double> first_ally,
642 std::vector<G4double> second_ally)
648 for(i = 0; i <
N; i++)
650 first_mean += first_ally[i];
651 second_mean += second_ally[i];
653 first_mean = first_mean /
N;
654 second_mean = second_mean /
N;
657 for(i = 0; i <
N; ++i)
659 a += (first_ally[i] - first_mean) * (second_ally[i] - second_mean);
664 for(i = 0; i <
N; ++i)
666 b1 += (first_ally[i] - first_mean) * (first_ally[i] - first_mean);
667 b2 += (second_ally[i] - second_mean) * (second_ally[i] - second_mean);
670 G4double rds = a / std::sqrt(b1 * b2);
675G4bool G4ConvergenceTester::is_monotonically_decrease(
676 const std::vector<G4double>& ally)
678 for(
auto it = ally.cbegin(); it != ally.cend() - 1; ++it)
690void G4ConvergenceTester::calc_slope_fit(
const std::vector<G4double>&)
696 if(largest_scores.back() != 0)
698 min = largest_scores.back();
702 min = largest_scores[last - 1];
713 std::vector<G4double> pdf_grid;
715 pdf_grid.resize(noBinOfPDF + 1);
717 pdf_grid[noBinOfPDF] =
min;
718 G4double log10_max = std::log10(max);
719 G4double log10_min = std::log10(min);
720 G4double log10_delta = log10_max - log10_min;
721 for(
G4int i = 1; i < noBinOfPDF; ++i)
723 pdf_grid[i] = std::pow(10.0, log10_max - log10_delta / 10.0 * (i));
726 std::vector<G4double> pdf;
727 pdf.resize(noBinOfPDF);
729 for(
G4int j = 0; j < last; ++j)
731 for(
G4int i = 0; i < 11; ++i)
733 if(largest_scores[j] >= pdf_grid[i + 1])
735 pdf[i] += 1.0 / (pdf_grid[i] - pdf_grid[i + 1]) / n;
741 f_xi.resize(noBinOfPDF);
742 f_yi.resize(noBinOfPDF);
743 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));
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
#define G4MUTEX_INITIALIZER
void ShowResult(std::ostream &out=G4cout)
void ShowHistory(std::ostream &out=G4cout)
G4ConvergenceTester(const G4String &theName="NONAME")
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