| 689 | } |
| 690 | |
| 691 | const char *reduce_num_flows(const tal_t *ctx, |
| 692 | const struct route_query *rq, |
| 693 | struct flow ***flows, |
| 694 | struct amount_msat deliver, |
| 695 | size_t num_parts) |
| 696 | { |
| 697 | /* Keep the largest flows (not as I originally implemented, the largest |
| 698 | * capacity flows). Here's Lagrang3's analysis: |
| 699 | * |
| 700 | * I think it is better to keep the largest-deliver flows. If we only |
| 701 | * go for the highest capacity we may throw away the low cost benefits |
| 702 | * of the MCF. |
| 703 | |
| 704 | * Hypothetical scenario: MCF finds 3 flows but maxparts=2, |
| 705 | * flow 1: deliver=10, cost=0, capacity=0 |
| 706 | * flow 2: deliver=7, cost=1, capacity=5 |
| 707 | * flow 3: deliver=1, cost=10, capacity=100 |
| 708 | * |
| 709 | * It is better to keep flows 1 and 2 by accomodating 1 more unit of |
| 710 | * flow in flow2 at 1 value expense (per flow), than to keep flows 2 and |
| 711 | * 3 by accomodating 5 more units of flow in flow2 at cost 1 and 5 in |
| 712 | * flow3 at cost 100. |
| 713 | * |
| 714 | * The trade-off is: if we prioritize the delivery value already |
| 715 | * computed by MCF then we find better solutions, but we might fail to |
| 716 | * find feasible solutions sometimes. If we prioritize capacity then we |
| 717 | * generally find bad solutions though we find feasibility more often |
| 718 | * than the alternative. |
| 719 | */ |
| 720 | size_t orig_num_flows = tal_count(*flows); |
| 721 | asort(*flows, orig_num_flows, revcmp_flows, NULL); |
| 722 | while (tal_count(*flows) > num_parts) |
| 723 | del_flow_from_arr(flows, tal_count(*flows) - 1); |
| 724 | |
| 725 | if (!increase_flows(rq, *flows, deliver, -1.0)) |
| 726 | return child_log(ctx, LOG_INFORM, |
| 727 | "Failed to reduce %zu flows down to maxparts (%zu)", |
| 728 | orig_num_flows, num_parts); |
| 729 | |
| 730 | return NULL; |
| 731 | } |
no test coverage detected