|
9 | 9 | #include <impl/dgb/download_stops.hpp> |
10 | 10 | #include <impl/dgb/pool_efficiency.hpp> |
11 | 11 | #include <impl/dgb/expected_time_to_block.hpp> |
| 12 | +#include <impl/dgb/coin/binomial_conf_interval.hpp> |
12 | 13 |
|
13 | 14 | #include <algorithm> |
14 | 15 | #include <filesystem> |
@@ -71,34 +72,35 @@ static std::string format_duration(double secs) { |
71 | 72 | // Returns "~X.Y% (lo-hi%)" string for binomial proportion x/n at 95% confidence. |
72 | 73 | static std::string format_binomial_conf(int x, int n, double conf = 0.95) { |
73 | 74 | if (n == 0) return "???"; |
74 | | - // z for 95% ≈ 1.96 (inverse error function approximation) |
75 | | - double z = 1.96; |
76 | | - double p = static_cast<double>(x) / n; |
77 | | - double topa = p + z * z / (2.0 * n); |
78 | | - double topb = z * std::sqrt(p * (1.0 - p) / n + z * z / (4.0 * n * n)); |
79 | | - double bottom = 1.0 + z * z / n; |
80 | | - double lo = std::max(0.0, (topa - topb) / bottom); |
81 | | - double hi = std::min(1.0, (topa + topb) / bottom); |
| 75 | + // Oracle-faithful Wilson score interval via the dgb::coin SSOT |
| 76 | + // (coin/binomial_conf_interval.hpp; p2pool util/math.py:133). This delegates |
| 77 | + // the prior inline z=1.96 + plain-[0,1]-clip approximation onto the SSOT, |
| 78 | + // which uses z = sqrt(2)*ierf(conf) and add_to_range bracketing. Output is |
| 79 | + // oracle-faithful and NOT byte-identical to the old literal-z form; diag |
| 80 | + // display only (heartbeat log), zero consensus surface. |
| 81 | + const std::array<double, 2> ci = dgb::coin::binomial_conf_interval( |
| 82 | + static_cast<double>(x), static_cast<double>(n), conf); |
| 83 | + const double p = static_cast<double>(x) / n; |
82 | 84 | std::ostringstream os; |
83 | 85 | os << "~" << std::fixed << std::setprecision(1) << (100.0 * p) << "% (" |
84 | | - << static_cast<int>(std::floor(100.0 * lo)) << "-" |
85 | | - << static_cast<int>(std::ceil(100.0 * hi)) << "%)"; |
| 86 | + << static_cast<int>(std::floor(100.0 * ci[0])) << "-" |
| 87 | + << static_cast<int>(std::ceil(100.0 * ci[1])) << "%)"; |
86 | 88 | return os.str(); |
87 | 89 | } |
88 | 90 |
|
89 | 91 | // Wilson score confidence interval for efficiency: 1 - stale_rate, scaled |
90 | 92 | static std::string format_binomial_conf_efficiency(int stale, int n, double stale_prop) { |
91 | 93 | if (n == 0) return "???"; |
92 | | - double z = 1.96; |
93 | | - double p = static_cast<double>(stale) / n; |
94 | | - double topa = p + z * z / (2.0 * n); |
95 | | - double topb = z * std::sqrt(p * (1.0 - p) / n + z * z / (4.0 * n * n)); |
96 | | - double bottom = 1.0 + z * z / n; |
97 | | - double lo_stale = std::max(0.0, (topa - topb) / bottom); |
98 | | - double hi_stale = std::min(1.0, (topa + topb) / bottom); |
99 | | - // Efficiency = (1 - stale_rate) / (1 - stale_prop) |
100 | | - double denom = (stale_prop < 0.999) ? (1.0 - stale_prop) : 1.0; |
101 | | - double eff = (1.0 - p) / denom; |
| 94 | + // Stale-rate CI via the oracle-faithful SSOT, then mapped to efficiency. |
| 95 | + // See format_binomial_conf note: oracle-faithful, NOT byte-identical to the |
| 96 | + // prior inline z=1.96 form; diag display only. |
| 97 | + const std::array<double, 2> ci = dgb::coin::binomial_conf_interval( |
| 98 | + static_cast<double>(stale), static_cast<double>(n), 0.95); |
| 99 | + const double p = static_cast<double>(stale) / n; |
| 100 | + const double lo_stale = ci[0]; |
| 101 | + const double hi_stale = ci[1]; |
| 102 | + const double denom = (stale_prop < 0.999) ? (1.0 - stale_prop) : 1.0; |
| 103 | + const double eff = (1.0 - p) / denom; |
102 | 104 | double eff_lo = (1.0 - hi_stale) / denom; |
103 | 105 | double eff_hi = (1.0 - lo_stale) / denom; |
104 | 106 | eff_lo = std::max(0.0, eff_lo); |
|
0 commit comments