@@ -1119,10 +1119,12 @@ const PRECISION_LOWER_BOUND_DENOMINATOR: u64 = log_approx::LOWER_BITS_BOUND;
1119
1119
const AMOUNT_PENALTY_DIVISOR : u64 = 1 << 20 ;
1120
1120
const BASE_AMOUNT_PENALTY_DIVISOR : u64 = 1 << 30 ;
1121
1121
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).
1123
1123
#[ 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)
1126
1128
}
1127
1129
1128
1130
/// Given liquidity bounds, calculates the success probability (in the form of a numerator and
@@ -1155,23 +1157,26 @@ fn success_probability(
1155
1157
let max = ( max_liquidity_msat as f64 ) / capacity;
1156
1158
let amount = ( total_inflight_amount_msat as f64 ) / capacity;
1157
1159
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.
1163
1165
//
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 ;
1175
1180
let numerator = ( num * BILLIONISH ) as u64 + 1 ;
1176
1181
let denominator = ( den * BILLIONISH ) as u64 + 1 ;
1177
1182
debug_assert ! ( numerator <= 1 << 30 , "Got large numerator ({}) from float {}." , numerator, num) ;
@@ -1180,13 +1185,13 @@ fn success_probability(
1180
1185
} ;
1181
1186
1182
1187
if min_zero_implies_no_successes && min_liquidity_msat == 0 &&
1183
- denominator < u64:: max_value ( ) / 21
1188
+ denominator < u64:: max_value ( ) / 78
1184
1189
{
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%.
1186
1191
// Note that we prefer to increase the denominator rather than decrease the numerator as
1187
1192
// the denominator is more likely to be larger and thus provide greater precision. This is
1188
1193
// mostly an overoptimization but makes a large difference in tests.
1189
- denominator = denominator * 21 / 16
1194
+ denominator = denominator * 78 / 64
1190
1195
}
1191
1196
1192
1197
( numerator, denominator)
@@ -3012,47 +3017,47 @@ mod tests {
3012
3017
info,
3013
3018
short_channel_id : 42 ,
3014
3019
} ) ;
3015
- assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 11497 ) ;
3020
+ assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 11577 ) ;
3016
3021
let usage = ChannelUsage {
3017
3022
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
3018
3023
} ;
3019
- assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 7408 ) ;
3024
+ assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 8462 ) ;
3020
3025
let usage = ChannelUsage {
3021
3026
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 2_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
3022
3027
} ;
3023
- assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 6151 ) ;
3028
+ assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 6889 ) ;
3024
3029
let usage = ChannelUsage {
3025
3030
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 3_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
3026
3031
} ;
3027
- assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 5427 ) ;
3032
+ assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 5883 ) ;
3028
3033
let usage = ChannelUsage {
3029
3034
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 4_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
3030
3035
} ;
3031
- assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 4955 ) ;
3036
+ assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 5412 ) ;
3032
3037
let usage = ChannelUsage {
3033
3038
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 5_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
3034
3039
} ;
3035
- assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 4736 ) ;
3040
+ assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 4940 ) ;
3036
3041
let usage = ChannelUsage {
3037
3042
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 6_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
3038
3043
} ;
3039
- assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 4484 ) ;
3044
+ assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 4689 ) ;
3040
3045
let usage = ChannelUsage {
3041
3046
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 7_450_000_000 , htlc_maximum_msat : 1_000 } , ..usage
3042
3047
} ;
3043
- assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 4484 ) ;
3048
+ assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 4468 ) ;
3044
3049
let usage = ChannelUsage {
3045
3050
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 7_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
3046
3051
} ;
3047
- assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 4263 ) ;
3052
+ assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 4468 ) ;
3048
3053
let usage = ChannelUsage {
3049
3054
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 8_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
3050
3055
} ;
3051
- assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 4263 ) ;
3056
+ assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 4217 ) ;
3052
3057
let usage = ChannelUsage {
3053
3058
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 9_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
3054
3059
} ;
3055
- assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 4044 ) ;
3060
+ assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 3996 ) ;
3056
3061
}
3057
3062
3058
3063
#[ test]
@@ -3252,7 +3257,7 @@ mod tests {
3252
3257
} ) ;
3253
3258
3254
3259
// 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 ) ;
3256
3261
}
3257
3262
assert_eq ! ( scorer. historical_estimated_channel_liquidity_probabilities( 42 , & target) ,
3258
3263
None ) ;
@@ -3270,7 +3275,7 @@ mod tests {
3270
3275
} ) ;
3271
3276
3272
3277
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 ) ;
3274
3279
}
3275
3280
// The "it failed" increment is 32, where the probability should lie several buckets into
3276
3281
// the first octile.
@@ -3294,7 +3299,7 @@ mod tests {
3294
3299
short_channel_id : 42 ,
3295
3300
} ) ;
3296
3301
3297
- assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 105 ) ;
3302
+ assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 83 ) ;
3298
3303
}
3299
3304
// The first points should be decayed just slightly and the last bucket has a new point.
3300
3305
assert_eq ! ( scorer. historical_estimated_channel_liquidity_probabilities( 42 , & target) ,
@@ -3305,12 +3310,12 @@ mod tests {
3305
3310
// simply check bounds here.
3306
3311
let five_hundred_prob =
3307
3312
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 ) ;
3310
3315
let one_prob =
3311
3316
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 ) ;
3314
3319
3315
3320
// Advance the time forward 16 half-lives (which the docs claim will ensure all data is
3316
3321
// gone), and check that we're back to where we started.
@@ -3324,7 +3329,7 @@ mod tests {
3324
3329
short_channel_id : 42 ,
3325
3330
} ) ;
3326
3331
3327
- assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 168 ) ;
3332
+ assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 135 ) ;
3328
3333
}
3329
3334
// Once fully decayed we still have data, but its all-0s. In the future we may remove the
3330
3335
// data entirely instead.
@@ -3512,8 +3517,8 @@ mod tests {
3512
3517
short_channel_id : 42 ,
3513
3518
} ) ;
3514
3519
// 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 ) ;
3517
3522
assert_eq ! ( scorer. historical_estimated_channel_liquidity_probabilities( 42 , & target) ,
3518
3523
None ) ;
3519
3524
assert_eq ! ( scorer. historical_estimated_payment_success_probability( 42 , & target, 42 , & params, false ) ,
0 commit comments