@@ -1119,10 +1119,12 @@ const PRECISION_LOWER_BOUND_DENOMINATOR: u64 = log_approx::LOWER_BITS_BOUND;
11191119const AMOUNT_PENALTY_DIVISOR : u64 = 1 << 20 ;
11201120const BASE_AMOUNT_PENALTY_DIVISOR : u64 = 1 << 30 ;
11211121
1122- /// Raises three `f64`s to the 3rd power, without `powi` because it requires `std` (dunno why).
1122+ /// Raises three `f64`s to the 9th power, without `powi` because it requires `std` (dunno why).
11231123#[ inline( always) ]
1124- fn three_f64_pow_3 ( a : f64 , b : f64 , c : f64 ) -> ( f64 , f64 , f64 ) {
1125- ( a * a * a, b * b * b, c * c * c)
1124+ fn three_f64_pow_9 ( a : f64 , b : f64 , c : f64 ) -> ( f64 , f64 , f64 ) {
1125+ let ( a2, b2, c2) = ( a * a, b * b, c * c) ;
1126+ let ( a4, b4, c4) = ( a2 * a2, b2 * b2, c2 * c2) ;
1127+ ( a * a4 * a4, b * b4 * b4, c * c4 * c4)
11261128}
11271129
11281130/// Given liquidity bounds, calculates the success probability (in the form of a numerator and
@@ -1155,23 +1157,26 @@ fn success_probability(
11551157 let max = ( max_liquidity_msat as f64 ) / capacity;
11561158 let amount = ( total_inflight_amount_msat as f64 ) / capacity;
11571159
1158- // Assume the channel has a probability density function of (x - 0.5)^2 for values from
1159- // 0 to 1 (where 1 is the channel's full capacity). The success probability given some
1160- // liquidity bounds is thus the integral under the curve from the amount to maximum
1161- // estimated liquidity, divided by the same integral from the minimum to the maximum
1162- // estimated liquidity bounds.
1160+ // Assume the channel has a probability density function of
1161+ // `128 * (1/256 + 9*(x - 0.5)^8)` for values from 0 to 1 (where 1 is the channel's
1162+ // full capacity). The success probability given some liquidity bounds is thus the
1163+ // integral under the curve from the amount to maximum estimated liquidity, divided by
1164+ // the same integral from the minimum to the maximum estimated liquidity bounds.
11631165 //
1164- // Because the integral from x to y is simply (y - 0.5)^3 - (x - 0.5)^3, we can
1165- // calculate the cumulative density function between the min/max bounds trivially. Note
1166- // that we don't bother to normalize the CDF to total to 1, as it will come out in the
1167- // division of num / den.
1168- let ( max_pow, amt_pow, min_pow) = three_f64_pow_3 ( max - 0.5 , amount - 0.5 , min - 0.5 ) ;
1169- let num = max_pow - amt_pow;
1170- let den = max_pow - min_pow;
1171-
1172- // Because our numerator and denominator max out at 0.5^3 we need to multiply them by
1173- // quite a large factor to get something useful (ideally in the 2^30 range).
1174- const BILLIONISH : f64 = 1024.0 * 1024.0 * 1024.0 ;
1166+ // Because the integral from x to y is simply
1167+ // `128*(1/256 * (y - 0.5) + (y - 0.5)^9) - 128*(1/256 * (x - 0.5) + (x - 0.5)^9), we
1168+ // can calculate the cumulative density function between the min/max bounds trivially.
1169+ // Note that we don't bother to normalize the CDF to total to 1 (using the 128
1170+ // multiple), as it will come out in the division of num / den.
1171+ let ( max_norm, amt_norm, min_norm) = ( max - 0.5 , amount - 0.5 , min - 0.5 ) ;
1172+ let ( max_pow, amt_pow, min_pow) = three_f64_pow_9 ( max_norm, amt_norm, min_norm) ;
1173+ let ( max_v, amt_v, min_v) = ( max_pow + max_norm / 256.0 , amt_pow + amt_norm / 256.0 , min_pow + min_norm / 256.0 ) ;
1174+ let num = max_v - amt_v;
1175+ let den = max_v - min_v;
1176+
1177+ // Because our numerator and denominator max out at 0.0078125 we need to multiply them
1178+ // by quite a large factor to get something useful (ideally in the 2^30 range).
1179+ const BILLIONISH : f64 = 1024.0 * 1024.0 * 1024.0 * 64.0 ;
11751180 let numerator = ( num * BILLIONISH ) as u64 + 1 ;
11761181 let denominator = ( den * BILLIONISH ) as u64 + 1 ;
11771182 debug_assert ! ( numerator <= 1 << 30 , "Got large numerator ({}) from float {}." , numerator, num) ;
@@ -1180,13 +1185,13 @@ fn success_probability(
11801185 } ;
11811186
11821187 if min_zero_implies_no_successes && min_liquidity_msat == 0 &&
1183- denominator < u64:: max_value ( ) / 21
1188+ denominator < u64:: max_value ( ) / 78
11841189 {
1185- // If we have no knowledge of the channel, scale probability down by ~75%
1190+ // If we have no knowledge of the channel, scale probability down by a multiple of ~82%.
11861191 // Note that we prefer to increase the denominator rather than decrease the numerator as
11871192 // the denominator is more likely to be larger and thus provide greater precision. This is
11881193 // mostly an overoptimization but makes a large difference in tests.
1189- denominator = denominator * 21 / 16
1194+ denominator = denominator * 78 / 64
11901195 }
11911196
11921197 ( numerator, denominator)
@@ -3012,47 +3017,47 @@ mod tests {
30123017 info,
30133018 short_channel_id : 42 ,
30143019 } ) ;
3015- assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 11497 ) ;
3020+ assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 11577 ) ;
30163021 let usage = ChannelUsage {
30173022 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
30183023 } ;
3019- assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 7408 ) ;
3024+ assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 8462 ) ;
30203025 let usage = ChannelUsage {
30213026 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 2_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
30223027 } ;
3023- assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 6151 ) ;
3028+ assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 6889 ) ;
30243029 let usage = ChannelUsage {
30253030 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 3_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
30263031 } ;
3027- assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 5427 ) ;
3032+ assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 5883 ) ;
30283033 let usage = ChannelUsage {
30293034 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 4_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
30303035 } ;
3031- assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 4955 ) ;
3036+ assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 5412 ) ;
30323037 let usage = ChannelUsage {
30333038 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 5_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
30343039 } ;
3035- assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 4736 ) ;
3040+ assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 4940 ) ;
30363041 let usage = ChannelUsage {
30373042 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 6_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
30383043 } ;
3039- assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 4484 ) ;
3044+ assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 4689 ) ;
30403045 let usage = ChannelUsage {
30413046 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 7_450_000_000 , htlc_maximum_msat : 1_000 } , ..usage
30423047 } ;
3043- assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 4484 ) ;
3048+ assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 4468 ) ;
30443049 let usage = ChannelUsage {
30453050 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 7_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
30463051 } ;
3047- assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 4263 ) ;
3052+ assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 4468 ) ;
30483053 let usage = ChannelUsage {
30493054 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 8_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
30503055 } ;
3051- assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 4263 ) ;
3056+ assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 4217 ) ;
30523057 let usage = ChannelUsage {
30533058 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 9_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
30543059 } ;
3055- assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 4044 ) ;
3060+ assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 3996 ) ;
30563061 }
30573062
30583063 #[ test]
@@ -3252,7 +3257,7 @@ mod tests {
32523257 } ) ;
32533258
32543259 // With no historical data the normal liquidity penalty calculation is used.
3255- assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 168 ) ;
3260+ assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 135 ) ;
32563261 }
32573262 assert_eq ! ( scorer. historical_estimated_channel_liquidity_probabilities( 42 , & target) ,
32583263 None ) ;
@@ -3270,7 +3275,7 @@ mod tests {
32703275 } ) ;
32713276
32723277 assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 2048 ) ;
3273- assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage_1, & params) , 249 ) ;
3278+ assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage_1, & params) , 220 ) ;
32743279 }
32753280 // The "it failed" increment is 32, where the probability should lie several buckets into
32763281 // the first octile.
@@ -3294,7 +3299,7 @@ mod tests {
32943299 short_channel_id : 42 ,
32953300 } ) ;
32963301
3297- assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 105 ) ;
3302+ assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 83 ) ;
32983303 }
32993304 // The first points should be decayed just slightly and the last bucket has a new point.
33003305 assert_eq ! ( scorer. historical_estimated_channel_liquidity_probabilities( 42 , & target) ,
@@ -3305,12 +3310,12 @@ mod tests {
33053310 // simply check bounds here.
33063311 let five_hundred_prob =
33073312 scorer. historical_estimated_payment_success_probability ( 42 , & target, 500 , & params, false ) . unwrap ( ) ;
3308- assert ! ( five_hundred_prob > 0.59 ) ;
3309- assert ! ( five_hundred_prob < 0.60 ) ;
3313+ assert ! ( five_hundred_prob > 0.61 , "{}" , five_hundred_prob ) ;
3314+ assert ! ( five_hundred_prob < 0.62 , "{}" , five_hundred_prob ) ;
33103315 let one_prob =
33113316 scorer. historical_estimated_payment_success_probability ( 42 , & target, 1 , & params, false ) . unwrap ( ) ;
3312- assert ! ( one_prob < 0.85 ) ;
3313- assert ! ( one_prob > 0.84 ) ;
3317+ assert ! ( one_prob < 0.89 , "{}" , one_prob ) ;
3318+ assert ! ( one_prob > 0.88 , "{}" , one_prob ) ;
33143319
33153320 // Advance the time forward 16 half-lives (which the docs claim will ensure all data is
33163321 // gone), and check that we're back to where we started.
@@ -3324,7 +3329,7 @@ mod tests {
33243329 short_channel_id : 42 ,
33253330 } ) ;
33263331
3327- assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 168 ) ;
3332+ assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 135 ) ;
33283333 }
33293334 // Once fully decayed we still have data, but its all-0s. In the future we may remove the
33303335 // data entirely instead.
@@ -3512,8 +3517,8 @@ mod tests {
35123517 short_channel_id : 42 ,
35133518 } ) ;
35143519 // With no historical data the normal liquidity penalty calculation is used, which results
3515- // in a success probability of ~75 %.
3516- assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 1269 ) ;
3520+ // in a success probability of ~82 %.
3521+ assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 910 ) ;
35173522 assert_eq ! ( scorer. historical_estimated_channel_liquidity_probabilities( 42 , & target) ,
35183523 None ) ;
35193524 assert_eq ! ( scorer. historical_estimated_payment_success_probability( 42 , & target, 42 , & params, false ) ,
0 commit comments