11#include "config.h"
22#include <assert.h>
3+ #include <ccan/asort/asort.h>
34#include <ccan/bitmap/bitmap.h>
45#include <ccan/list/list.h>
56#include <ccan/tal/str/str.h>
67#include <ccan/tal/tal.h>
78#include <common/utils.h>
9+ #include <float.h>
810#include <math.h>
911#include <plugins/askrene/askrene.h>
1012#include <plugins/askrene/dijkstra.h>
@@ -293,7 +295,6 @@ struct pay_parameters {
293295
294296 double delay_feefactor ;
295297 double base_fee_penalty ;
296- double k_factor ;
297298};
298299
299300/* Representation of the linear MCF network.
@@ -311,7 +312,8 @@ struct linear_network
311312 struct arc * node_adjacency_first_arc ;
312313
313314 // probability and fee cost associated to an arc
314- s64 * arc_prob_cost , * arc_fee_cost ;
315+ double * arc_prob_cost ;
316+ s64 * arc_fee_cost ;
315317 s64 * capacity ;
316318
317319 size_t max_num_arcs ,max_num_nodes ;
@@ -413,7 +415,7 @@ static void set_capacity(s64 *capacity, u64 value, u64 *cap_on_capacity)
413415/* Split a directed channel into parts with linear cost function. */
414416static void linearize_channel (const struct pay_parameters * params ,
415417 const struct gossmap_chan * c , const int dir ,
416- s64 * capacity , s64 * cost )
418+ s64 * capacity , double * cost )
417419{
418420 struct amount_msat mincap , maxcap ;
419421
@@ -439,7 +441,7 @@ static void linearize_channel(const struct pay_parameters *params,
439441
440442 cost [i ] = params -> cost_fraction [i ]
441443 * params -> amount .millisatoshis /* Raw: linearize_channel */
442- * params -> k_factor /(b - a );
444+ /(b - a );
443445 }
444446}
445447
@@ -482,22 +484,71 @@ static void init_residual_network(
482484 }
483485}
484486
487+ static int cmp_u64 (const u64 * a , const u64 * b , void * unused )
488+ {
489+ if (* a < * b )
490+ return -1 ;
491+ if (* a > * b )
492+ return 1 ;
493+ return 0 ;
494+ }
495+
496+ static int cmp_double (const double * a , const double * b , void * unused )
497+ {
498+ if (* a < * b )
499+ return -1 ;
500+ if (* a > * b )
501+ return 1 ;
502+ return 0 ;
503+ }
504+
505+ static double get_median_ratio (const tal_t * working_ctx ,
506+ const struct linear_network * linear_network )
507+ {
508+ u64 * u64_arr = tal_arr (working_ctx , u64 , linear_network -> max_num_arcs /2 );
509+ double * double_arr = tal_arr (working_ctx , double , linear_network -> max_num_arcs /2 );
510+ size_t n = 0 ;
511+
512+ for (struct arc arc = {0 };arc .idx < linear_network -> max_num_arcs ; ++ arc .idx ) {
513+ if (arc_is_dual (arc ))
514+ continue ;
515+ assert (n < linear_network -> max_num_arcs /2 );
516+ u64_arr [n ] = linear_network -> arc_fee_cost [arc .idx ];
517+ double_arr [n ] = linear_network -> arc_prob_cost [arc .idx ];
518+ n ++ ;
519+ }
520+ asort (u64_arr , n , cmp_u64 , NULL );
521+ asort (double_arr , n , cmp_double , NULL );
522+
523+ /* Empty network, or tiny probability, nobody cares */
524+ if (n == 0 || double_arr [n /2 ] < 0.001 )
525+ return 1 ;
526+
527+ /* You need to scale arc_prob_cost by this to match arc_fee_cost */
528+ return u64_arr [n /2 ] / double_arr [n /2 ];
529+ }
530+
485531static void combine_cost_function (
532+ const tal_t * working_ctx ,
486533 const struct linear_network * linear_network ,
487534 struct residual_network * residual_network ,
488535 s64 mu )
489536{
537+ /* probabilty and fee costs are not directly comparable!
538+ * Scale by ratio of (positive) medians. */
539+ const double k = get_median_ratio (working_ctx , linear_network );
540+
490541 for (struct arc arc = {0 };arc .idx < linear_network -> max_num_arcs ; ++ arc .idx )
491542 {
492543 if (arc_tail (linear_network ,arc )== INVALID_INDEX )
493544 continue ;
494545
495- const s64 pcost = linear_network -> arc_prob_cost [arc .idx ],
496- fcost = linear_network -> arc_fee_cost [arc .idx ];
546+ const double pcost = linear_network -> arc_prob_cost [arc .idx ];
547+ const s64 fcost = linear_network -> arc_fee_cost [arc .idx ];
497548
498- assert (pcost != INFINITE );
499549 assert (fcost != INFINITE );
500- residual_network -> cost [arc .idx ] = fcost * mu + (MU_MAX - mu )* pcost ;
550+ assert (pcost != DBL_MAX );
551+ residual_network -> cost [arc .idx ] = fcost * mu + (MU_MAX - mu )* pcost * k ;
501552 }
502553}
503554
@@ -594,9 +645,9 @@ init_linear_network(const tal_t *ctx, const struct pay_parameters *params)
594645 for (size_t i = 0 ;i < max_num_nodes ;++ i )
595646 linear_network -> node_adjacency_first_arc [i ].idx = INVALID_INDEX ;
596647
597- linear_network -> arc_prob_cost = tal_arr (linear_network ,s64 ,max_num_arcs );
648+ linear_network -> arc_prob_cost = tal_arr (linear_network ,double ,max_num_arcs );
598649 for (size_t i = 0 ;i < max_num_arcs ;++ i )
599- linear_network -> arc_prob_cost [i ]= INFINITE ;
650+ linear_network -> arc_prob_cost [i ]= DBL_MAX ;
600651
601652 linear_network -> arc_fee_cost = tal_arr (linear_network ,s64 ,max_num_arcs );
602653 for (size_t i = 0 ;i < max_num_arcs ;++ i )
@@ -631,7 +682,8 @@ init_linear_network(const tal_t *ctx, const struct pay_parameters *params)
631682
632683 // `cost` is the word normally used to denote cost per
633684 // unit of flow in the context of MCF.
634- s64 prob_cost [CHANNEL_PARTS ], capacity [CHANNEL_PARTS ];
685+ double prob_cost [CHANNEL_PARTS ];
686+ s64 capacity [CHANNEL_PARTS ];
635687
636688 // split this channel direction to obtain the arcs
637689 // that are outgoing to `node`
@@ -1307,7 +1359,6 @@ struct flow **minflow(const tal_t *ctx,
13071359
13081360 params -> delay_feefactor = delay_feefactor ;
13091361 params -> base_fee_penalty = base_fee_penalty_estimate (amount );
1310- params -> k_factor = 8.0 ;
13111362
13121363 // build the uncertainty network with linearization and residual arcs
13131364 struct linear_network * linear_network = init_linear_network (working_ctx , params );
@@ -1342,7 +1393,7 @@ struct flow **minflow(const tal_t *ctx,
13421393 tal_free (working_ctx );
13431394 return NULL ;
13441395 }
1345- combine_cost_function (linear_network , residual_network , mu );
1396+ combine_cost_function (working_ctx , linear_network , residual_network , mu );
13461397
13471398 /* We solve a linear MCF problem. */
13481399 if (!optimize_mcf (working_ctx , dijkstra ,linear_network ,residual_network ,
0 commit comments