@@ -171,6 +171,7 @@ static const s64 MU_MAX = 100;
171
171
172
172
/* every payment under 1000sat will be routed through a single path */
173
173
static const struct amount_msat SINGLE_PATH_THRESHOLD = AMOUNT_MSAT (1000000 );
174
+ static const double DEFAULT_BASE_PROBABILITY = 0.98 ;
174
175
175
176
/* Let's try this encoding of arcs:
176
177
* Each channel `c` has two possible directions identified by a bit
@@ -300,6 +301,13 @@ struct pay_parameters {
300
301
301
302
double delay_feefactor ;
302
303
double base_fee_penalty ;
304
+ /* base_prob is understood as global probability for channel
305
+ * availability, ie. a channel chosen at random will be able to forward
306
+ * 1msat with a probability given by this value. We don't know the
307
+ * actual value for this quantity but we can still use it to penalize
308
+ * the use of many channels per payment, ie. reducing this number we
309
+ * tend to obtaine less routes and/or shorter paths. */
310
+ double base_prob ;
303
311
};
304
312
305
313
/* Helper function.
@@ -359,6 +367,7 @@ static void linearize_channel(const struct pay_parameters *params,
359
367
const struct gossmap_chan * c , const int dir ,
360
368
s64 * capacity , double * cost )
361
369
{
370
+ const double base_prob_cost = - log (params -> base_prob );
362
371
struct amount_msat mincap , maxcap ;
363
372
364
373
/* This takes into account any payments in progress. */
@@ -391,9 +400,23 @@ static void linearize_channel(const struct pay_parameters *params,
391
400
{
392
401
set_capacity (& capacity [i ], params -> cap_fraction [i ]* (b - a ), & cap_on_capacity );
393
402
394
- cost [i ] = params -> cost_fraction [i ] * 1000
395
- * amount_msat_ratio (params -> amount , params -> accuracy )
396
- / (b - a );
403
+ /* It is conceptually wrong to add a base cost to every arc,
404
+ * that would mean we might pay several times for the same base
405
+ * cost. The linearization of the base cost is another corner
406
+ * that needs improvement.
407
+ * For a cost function of the form
408
+ * C(x) = x*k1 + k0
409
+ * we produce a linear variation of the form
410
+ * C_lin(x) = x*(k1 + k0/T)
411
+ * where T is the entire payment amount.
412
+ * Since we also scale up the probability cost function by
413
+ * 1000*T the resulting linear approximation becomes:
414
+ * C_lin(x) = x*1000*(k1*T + k0)
415
+ **/
416
+ cost [i ] = 1000 * (params -> cost_fraction [i ] / (b - a ) *
417
+ amount_msat_ratio (params -> amount ,
418
+ params -> accuracy ) +
419
+ base_prob_cost );
397
420
}
398
421
}
399
422
@@ -970,7 +993,8 @@ struct flow **minflow(const tal_t *ctx,
970
993
const struct gossmap_node * target ,
971
994
struct amount_msat amount ,
972
995
u32 mu ,
973
- double delay_feefactor )
996
+ double delay_feefactor ,
997
+ double base_prob )
974
998
{
975
999
struct flow * * flow_paths ;
976
1000
/* We allocate everything off this, and free it at the end,
@@ -991,6 +1015,7 @@ struct flow **minflow(const tal_t *ctx,
991
1015
* */
992
1016
params -> accuracy =
993
1017
amount_msat_max (AMOUNT_MSAT (1 ), amount_msat_div_ceil (amount , 1000 ));
1018
+ params -> base_prob = base_prob ;
994
1019
995
1020
// template the channel partition into linear arcs
996
1021
params -> cap_fraction [0 ]= 0 ;
@@ -1149,7 +1174,8 @@ static void init_linear_network_single_path(
1149
1174
(* arc_capacity )[arc .idx ] = 1 ;
1150
1175
(* arc_prob_cost )[arc .idx ] =
1151
1176
(-1.0 ) * log (pickhardt_richter_probability (
1152
- mincap , maxcap , params -> amount ));
1177
+ mincap , maxcap , params -> amount ) *
1178
+ params -> base_prob );
1153
1179
1154
1180
struct amount_msat fee ;
1155
1181
if (!amount_msat_fee (& fee , params -> amount ,
@@ -1171,7 +1197,8 @@ struct flow **single_path_flow(const tal_t *ctx, const struct route_query *rq,
1171
1197
const struct gossmap_node * source ,
1172
1198
const struct gossmap_node * target ,
1173
1199
struct amount_msat amount , u32 mu ,
1174
- double delay_feefactor )
1200
+ double delay_feefactor ,
1201
+ double base_prob )
1175
1202
{
1176
1203
struct flow * * flow_paths ;
1177
1204
/* We allocate everything off this, and free it at the end,
@@ -1188,6 +1215,7 @@ struct flow **single_path_flow(const tal_t *ctx, const struct route_query *rq,
1188
1215
params -> accuracy = amount ;
1189
1216
params -> delay_feefactor = delay_feefactor ;
1190
1217
params -> base_fee_penalty = base_fee_penalty_estimate (amount );
1218
+ params -> base_prob = base_prob ;
1191
1219
1192
1220
struct graph * graph ;
1193
1221
double * arc_prob_cost ;
@@ -1352,7 +1380,7 @@ linear_routes(const tal_t *ctx, struct route_query *rq,
1352
1380
struct flow * * (* solver )(const tal_t * , const struct route_query * ,
1353
1381
const struct gossmap_node * ,
1354
1382
const struct gossmap_node * ,
1355
- struct amount_msat , u32 , double ))
1383
+ struct amount_msat , u32 , double , double ))
1356
1384
{
1357
1385
const tal_t * working_ctx = tal (ctx , tal_t );
1358
1386
const char * error_message ;
@@ -1373,6 +1401,7 @@ linear_routes(const tal_t *ctx, struct route_query *rq,
1373
1401
1374
1402
/* Re-use the reservation system to make flows aware of each other. */
1375
1403
struct reserve_hop * reservations = new_reservations (working_ctx , rq );
1404
+ double base_prob = DEFAULT_BASE_PROBABILITY ;
1376
1405
1377
1406
while (!amount_msat_is_zero (amount_to_deliver )) {
1378
1407
size_t num_parts , parts_slots , excess_parts ;
@@ -1409,11 +1438,13 @@ linear_routes(const tal_t *ctx, struct route_query *rq,
1409
1438
parts_slots == 1 ) {
1410
1439
new_flows = single_path_flow (working_ctx , rq , srcnode ,
1411
1440
dstnode , amount_to_deliver ,
1412
- mu , delay_feefactor );
1441
+ mu , delay_feefactor ,
1442
+ base_prob );
1413
1443
} else {
1414
1444
new_flows =
1415
1445
solver (working_ctx , rq , srcnode , dstnode ,
1416
- amount_to_deliver , mu , delay_feefactor );
1446
+ amount_to_deliver , mu , delay_feefactor ,
1447
+ base_prob );
1417
1448
}
1418
1449
1419
1450
if (!new_flows ) {
@@ -1448,9 +1479,10 @@ linear_routes(const tal_t *ctx, struct route_query *rq,
1448
1479
}
1449
1480
1450
1481
if (tal_count (new_flows ) > parts_slots ) {
1451
- /* Remove the excees of parts and leave one slot for the
1452
- * next round of computations. */
1453
- excess_parts = 1 + tal_count (new_flows ) - parts_slots ;
1482
+ /* try again but with a bigger activation cost per
1483
+ * channel */
1484
+ base_prob *= DEFAULT_BASE_PROBABILITY ;
1485
+ continue ;
1454
1486
} else if (tal_count (new_flows ) == parts_slots &&
1455
1487
amount_msat_less (all_deliver , amount_to_deliver )) {
1456
1488
/* Leave exactly 1 slot for the next round of
@@ -1467,6 +1499,8 @@ linear_routes(const tal_t *ctx, struct route_query *rq,
1467
1499
tal_count (new_flows ));
1468
1500
goto fail ;
1469
1501
}
1502
+
1503
+ // FIXME: if too many parts -> decrease the base prob
1470
1504
1471
1505
/* Is this set of flows too expensive?
1472
1506
* We can check if the new flows are within the fee budget,
0 commit comments