Skip to content

Commit 8512473

Browse files
committed
askrene: fix bug, not all arcs exists
We use an arc "array" in the graph structure, but not all arc indexes correspond to real topological arcs. We must be careful when iterating through all arcs, and check if they are enabled before making operations on them. Changelog-None: askrene: fix bug, not all arcs exists Signed-off-by: Lagrang3 <[email protected]>
1 parent 9d28df7 commit 8512473

File tree

3 files changed

+27
-4
lines changed

3 files changed

+27
-4
lines changed

plugins/askrene/algorithm.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -554,8 +554,9 @@ static bool mcf_refinement(const tal_t *ctx,
554554
* constraints. */
555555
for (u32 arc_id = 0; arc_id < max_num_arcs; arc_id++) {
556556
struct arc arc = {.idx = arc_id};
557+
if(!arc_enabled(graph, arc))
558+
continue;
557559
const s64 r = capacity[arc.idx];
558-
559560
if (reduced_cost(graph, arc, cost, potential) < 0 && r > 0) {
560561
/* This arc's reduced cost is negative and non
561562
* saturated. */
@@ -615,7 +616,19 @@ static bool mcf_refinement(const tal_t *ctx,
615616
for (u32 i = 0; i < max_num_nodes; i++) {
616617
assert(excess[i] == 0);
617618
}
619+
for (u32 i = 0; i < max_num_arcs; i++) {
620+
struct arc arc = {.idx = i};
621+
if(!arc_enabled(graph, arc))
622+
continue;
623+
const s64 cap = capacity[arc.idx];
624+
const s64 rc = reduced_cost(graph, arc, cost, potential);
625+
626+
assert(cap >= 0);
627+
/* asserts logic implication: (rc<0 -> cap==0)*/
628+
assert(!(rc < 0) || cap == 0);
629+
}
618630
#endif
631+
solved = true;
619632

620633
finish:
621634
tal_free(this_ctx);

plugins/askrene/graph.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,12 @@ static inline struct node arc_head(const struct graph *graph,
9797
return graph->arc_tail[dual.idx];
9898
}
9999

100+
/* We use an arc array but not all arcs in that array do exist in the graph. */
101+
static inline bool arc_enabled(const struct graph *graph, const struct arc arc)
102+
{
103+
return graph->arc_tail[arc.idx].idx < graph->max_num_nodes;
104+
}
105+
100106
/* Used to loop over the arcs that exit a node.
101107
*
102108
* for example:

plugins/askrene/test/run-mcf-large.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@
2222
* A feasible solution is guaranteed.
2323
* The last test case has 0 nodes and should be ignored. */
2424

25+
/* check-source does not like me to use scanf, how am I going to read the test
26+
* data otherwise? */
27+
#define myscanf scanf
28+
2529
static int next_bit(s64 x)
2630
{
2731
int b;
@@ -37,7 +41,7 @@ static bool solve_case(const tal_t *ctx)
3741
tal_t *this_ctx = tal(ctx, tal_t);
3842

3943
int N_nodes, N_arcs;
40-
scanf("%d %d\n", &N_nodes, &N_arcs);
44+
myscanf("%d %d\n", &N_nodes, &N_arcs);
4145
printf("Testcase %d\n", c);
4246
printf("nodes %d arcs %d\n", N_nodes, N_arcs);
4347
if (N_nodes == 0 && N_arcs == 0)
@@ -56,7 +60,7 @@ static bool solve_case(const tal_t *ctx)
5660

5761
for (u32 i = 0; i < N_arcs; i++) {
5862
u32 from, to;
59-
scanf("%" PRIu32 " %" PRIu32 " %" PRIi64 " %" PRIi64, &from,
63+
myscanf("%" PRIu32 " %" PRIu32 " %" PRIi64 " %" PRIi64, &from,
6064
&to, &capacity[i], &cost[i]);
6165

6266
struct arc arc = {.idx = i};
@@ -70,7 +74,7 @@ static bool solve_case(const tal_t *ctx)
7074
struct node dst = {.idx = 1};
7175

7276
s64 amount, best_cost;
73-
scanf("%" PRIi64 " %" PRIi64, &amount, &best_cost);
77+
myscanf("%" PRIi64 " %" PRIi64, &amount, &best_cost);
7478

7579
bool result = simple_mcf(ctx, graph, src, dst, capacity, amount, cost);
7680
assert(result);

0 commit comments

Comments
 (0)