Skip to content

Commit d24e60a

Browse files
committed
askrene: small fixes suggested by Rusty Russell
- use graph_max_num_arcs/nodes instead of tal_count in bound checks, - don't use ccan/lqueue, use instead a minimalistic queue implementation with an array, - add missing const qualifiers to temporary tal allocators, - check preconditions with assert, - remove inline specifier for static functions, Changelog-None Signed-off-by: Lagrang3 <[email protected]>
1 parent 54d9821 commit d24e60a

File tree

4 files changed

+66
-81
lines changed

4 files changed

+66
-81
lines changed

plugins/askrene/algorithm.c

Lines changed: 59 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#include "config.h"
22
#include <ccan/bitmap/bitmap.h>
3-
#include <ccan/lqueue/lqueue.h>
43
#include <ccan/tal/tal.h>
54
#include <plugins/askrene/algorithm.h>
65
#include <plugins/askrene/priorityqueue.h>
@@ -10,44 +9,37 @@ static const s64 INFINITE = INT64_MAX;
109
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
1110
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
1211

13-
/* Simple queue to traverse the network. */
14-
struct queue_data {
15-
u32 idx;
16-
struct lqueue_link ql;
17-
};
18-
1912
bool BFS_path(const tal_t *ctx, const struct graph *graph,
2013
const struct node source, const struct node destination,
2114
const s64 *capacity, const s64 cap_threshold, struct arc *prev)
2215
{
23-
tal_t *this_ctx = tal(ctx, tal_t);
16+
const tal_t *this_ctx = tal(ctx, tal_t);
2417
bool target_found = false;
18+
assert(graph);
2519
const size_t max_num_arcs = graph_max_num_arcs(graph);
2620
const size_t max_num_nodes = graph_max_num_nodes(graph);
2721

2822
/* check preconditions */
29-
if (!graph || source.idx >= max_num_nodes || !capacity || !prev)
30-
goto finish;
31-
32-
if (tal_count(capacity) != max_num_arcs ||
33-
tal_count(prev) != max_num_nodes)
34-
goto finish;
23+
assert(source.idx < max_num_nodes);
24+
assert(capacity);
25+
assert(prev);
26+
assert(tal_count(capacity) == max_num_arcs);
27+
assert(tal_count(prev) == max_num_nodes);
3528

3629
for (size_t i = 0; i < max_num_nodes; i++)
3730
prev[i].idx = INVALID_INDEX;
3831

39-
LQUEUE(struct queue_data, ql) myqueue = LQUEUE_INIT;
40-
struct queue_data *qdata;
32+
/* A minimalistic queue is implemented here. Nodes are not visited more
33+
* than once, therefore a maximum size of max_num_nodes is sufficient.
34+
* max_num_arcs would work as well but we expect max_num_arcs to be a
35+
* factor >10 greater than max_num_nodes. */
36+
u32 *queue = tal_arr(this_ctx, u32, max_num_nodes);
37+
size_t queue_start = 0, queue_end = 0;
4138

42-
qdata = tal(this_ctx, struct queue_data);
43-
qdata->idx = source.idx;
44-
lqueue_enqueue(&myqueue, qdata);
39+
queue[queue_end++] = source.idx;
4540

46-
while (!lqueue_empty(&myqueue)) {
47-
qdata = lqueue_dequeue(&myqueue);
48-
struct node cur = {.idx = qdata->idx};
49-
50-
tal_free(qdata);
41+
while (queue_start < queue_end) {
42+
struct node cur = {.idx = queue[queue_start++]};
5143

5244
if (cur.idx == destination.idx) {
5345
target_found = true;
@@ -69,13 +61,11 @@ bool BFS_path(const tal_t *ctx, const struct graph *graph,
6961

7062
prev[next.idx] = arc;
7163

72-
qdata = tal(this_ctx, struct queue_data);
73-
qdata->idx = next.idx;
74-
lqueue_enqueue(&myqueue, qdata);
64+
assert(queue_end < max_num_nodes);
65+
queue[queue_end++] = next.idx;
7566
}
7667
}
7768

78-
finish:
7969
tal_free(this_ctx);
8070
return target_found;
8171
}
@@ -87,24 +77,25 @@ bool dijkstra_path(const tal_t *ctx, const struct graph *graph,
8777
s64 *distance)
8878
{
8979
bool target_found = false;
80+
assert(graph);
9081
const size_t max_num_arcs = graph_max_num_arcs(graph);
9182
const size_t max_num_nodes = graph_max_num_nodes(graph);
92-
tal_t *this_ctx = tal(ctx, tal_t);
83+
const tal_t *this_ctx = tal(ctx, tal_t);
9384

9485
/* check preconditions */
95-
if (!graph || source.idx >=max_num_nodes || !cost || !capacity ||
96-
!prev || !distance)
97-
goto finish;
86+
assert(source.idx<max_num_nodes);
87+
assert(cost);
88+
assert(capacity);
89+
assert(prev);
90+
assert(distance);
9891

9992
/* if prune is true then the destination cannot be invalid */
100-
if (destination.idx >=max_num_nodes && prune)
101-
goto finish;
93+
assert(destination.idx < max_num_nodes || !prune);
10294

103-
if (tal_count(cost) != max_num_arcs ||
104-
tal_count(capacity) != max_num_arcs ||
105-
tal_count(prev) != max_num_nodes ||
106-
tal_count(distance) != max_num_nodes)
107-
goto finish;
95+
assert(tal_count(cost) == max_num_arcs);
96+
assert(tal_count(capacity) == max_num_arcs);
97+
assert(tal_count(prev) == max_num_nodes);
98+
assert(tal_count(distance) == max_num_nodes);
10899

109100
/* FIXME: maybe this is unnecessary */
110101
bitmap *visited = tal_arrz(this_ctx, bitmap,
@@ -217,9 +208,8 @@ static s64 get_augmenting_flow(const struct graph *graph,
217208
* Sends an amount of flow through an arc, changing the flow balance of the
218209
* nodes connected by the arc and the [residual] capacity of the arc and its
219210
* dual. */
220-
static inline void sendflow(const struct graph *graph, const struct arc arc,
221-
const s64 flow, s64 *arc_capacity,
222-
s64 *node_balance)
211+
static void sendflow(const struct graph *graph, const struct arc arc,
212+
const s64 flow, s64 *arc_capacity, s64 *node_balance)
223213
{
224214
const struct arc dual = arc_dual(graph, arc);
225215

@@ -279,20 +269,17 @@ bool simple_feasibleflow(const tal_t *ctx,
279269
s64 *capacity,
280270
s64 amount)
281271
{
282-
tal_t *this_ctx = tal(ctx, tal_t);
272+
const tal_t *this_ctx = tal(ctx, tal_t);
273+
assert(graph);
283274
const size_t max_num_arcs = graph_max_num_arcs(graph);
284275
const size_t max_num_nodes = graph_max_num_nodes(graph);
285276

286277
/* check preconditions */
287-
if (amount < 0)
288-
goto finish;
289-
290-
if (!graph || source.idx >= max_num_nodes ||
291-
destination.idx >= max_num_nodes || !capacity)
292-
goto finish;
293-
294-
if (tal_count(capacity) != max_num_arcs)
295-
goto finish;
278+
assert(amount > 0);
279+
assert(source.idx < max_num_nodes);
280+
assert(destination.idx < max_num_nodes);
281+
assert(capacity);
282+
assert(tal_count(capacity) == max_num_arcs);
296283

297284
/* path information
298285
* prev: is the id of the arc that lead to the node. */
@@ -343,8 +330,8 @@ s64 node_balance(const struct graph *graph,
343330

344331
/* Helper.
345332
* Compute the reduced cost of an arc. */
346-
static inline s64 reduced_cost(const struct graph *graph, const struct arc arc,
347-
const s64 *cost, const s64 *potential)
333+
static s64 reduced_cost(const struct graph *graph, const struct arc arc,
334+
const s64 *cost, const s64 *potential)
348335
{
349336
struct node src = arc_tail(graph, arc);
350337
struct node dst = arc_head(graph, arc);
@@ -368,7 +355,7 @@ static struct node dijkstra_nearest_sink(const tal_t *ctx,
368355
s64 *distance)
369356
{
370357
struct node target = {.idx = INVALID_INDEX};
371-
tal_t *this_ctx = tal(ctx, tal_t);
358+
const tal_t *this_ctx = tal(ctx, tal_t);
372359

373360
if (!this_ctx)
374361
/* bad allocation */
@@ -521,7 +508,7 @@ bool mcf_refinement(const tal_t *ctx,
521508
s64 *potential)
522509
{
523510
bool solved = false;
524-
tal_t *this_ctx = tal(ctx, tal_t);
511+
const tal_t *this_ctx = tal(ctx, tal_t);
525512

526513
if (!this_ctx)
527514
/* bad allocation */
@@ -639,24 +626,23 @@ bool simple_mcf(const tal_t *ctx, const struct graph *graph,
639626
const struct node source, const struct node destination,
640627
s64 *capacity, s64 amount, const s64 *cost)
641628
{
642-
tal_t *this_ctx = tal(ctx, tal_t);
629+
const tal_t *this_ctx = tal(ctx, tal_t);
643630
if (!this_ctx)
644631
/* bad allocation */
645632
goto fail;
646633

647-
if (!graph)
648-
goto fail;
649-
634+
assert(graph);
650635
const size_t max_num_arcs = graph_max_num_arcs(graph);
651636
const size_t max_num_nodes = graph_max_num_nodes(graph);
652637

653-
if (amount < 0 || source.idx >= max_num_nodes ||
654-
destination.idx >= max_num_nodes || !capacity || !cost)
655-
goto fail;
656-
657-
if (tal_count(capacity) != max_num_arcs ||
658-
tal_count(cost) != max_num_arcs)
659-
goto fail;
638+
/* check preconditions */
639+
assert(amount > 0);
640+
assert(source.idx < max_num_nodes);
641+
assert(destination.idx < max_num_nodes);
642+
assert(capacity);
643+
assert(cost);
644+
assert(tal_count(capacity) == max_num_arcs);
645+
assert(tal_count(cost) == max_num_arcs);
660646

661647
s64 *potential = tal_arrz(this_ctx, s64, max_num_nodes);
662648
s64 *excess = tal_arrz(this_ctx, s64, max_num_nodes);
@@ -681,12 +667,15 @@ bool simple_mcf(const tal_t *ctx, const struct graph *graph,
681667

682668
s64 flow_cost(const struct graph *graph, const s64 *capacity, const s64 *cost)
683669
{
670+
assert(graph);
684671
const size_t max_num_arcs = graph_max_num_arcs(graph);
685672
s64 total_cost = 0;
686673

687-
assert(graph && capacity && cost);
688-
assert(tal_count(capacity) == max_num_arcs &&
689-
tal_count(cost) == max_num_arcs);
674+
/* check preconditions */
675+
assert(capacity);
676+
assert(cost);
677+
assert(tal_count(capacity) == max_num_arcs);
678+
assert(tal_count(cost) == max_num_arcs);
690679

691680
for (u32 i = 0; i < max_num_arcs; i++) {
692681
struct arc arc = {.idx = i};

plugins/askrene/graph.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,17 @@
55
static void graph_push_outbound_arc(struct graph *graph, const struct arc arc,
66
const struct node node)
77
{
8-
assert(arc.idx < tal_count(graph->arc_tail));
8+
assert(arc.idx < graph_max_num_arcs(graph));
9+
assert(node.idx < graph_max_num_nodes(graph));
910

1011
/* arc is already added, skip */
1112
if (graph->arc_tail[arc.idx].idx != INVALID_INDEX)
1213
return;
1314

1415
graph->arc_tail[arc.idx] = node;
1516

16-
assert(node.idx < tal_count(graph->node_adjacency_first));
1717
const struct arc first_arc = graph->node_adjacency_first[node.idx];
18-
19-
assert(arc.idx < tal_count(graph->node_adjacency_next));
2018
graph->node_adjacency_next[arc.idx] = first_arc;
21-
22-
assert(node.idx < tal_count(graph->node_adjacency_first));
2319
graph->node_adjacency_first[node.idx] = arc;
2420
}
2521

plugins/askrene/graph.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ static inline bool arc_is_dual(const struct graph *graph, struct arc arc)
8484
static inline struct node arc_tail(const struct graph *graph,
8585
const struct arc arc)
8686
{
87-
assert(arc.idx < tal_count(graph->arc_tail));
87+
assert(arc.idx < graph_max_num_arcs(graph));
8888
return graph->arc_tail[arc.idx];
8989
}
9090

@@ -93,7 +93,7 @@ static inline struct node arc_head(const struct graph *graph,
9393
const struct arc arc)
9494
{
9595
const struct arc dual = arc_dual(graph, arc);
96-
assert(dual.idx < tal_count(graph->arc_tail));
96+
assert(dual.idx < graph_max_num_arcs(graph));
9797
return graph->arc_tail[dual.idx];
9898
}
9999

@@ -122,7 +122,7 @@ static inline bool arc_enabled(const struct graph *graph, const struct arc arc)
122122
static inline struct arc node_adjacency_begin(const struct graph *graph,
123123
const struct node node)
124124
{
125-
assert(node.idx < tal_count(graph->node_adjacency_first));
125+
assert(node.idx < graph_max_num_nodes(graph));
126126
return graph->node_adjacency_first[node.idx];
127127
}
128128
static inline bool node_adjacency_end(const struct arc arc)
@@ -132,7 +132,7 @@ static inline bool node_adjacency_end(const struct arc arc)
132132
static inline struct arc node_adjacency_next(const struct graph *graph,
133133
const struct arc arc)
134134
{
135-
assert(arc.idx < tal_count(graph->node_adjacency_next));
135+
assert(arc.idx < graph_max_num_arcs(graph));
136136
return graph->node_adjacency_next[arc.idx];
137137
}
138138

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ static bool solve_case(const tal_t *ctx)
5454
int ret;
5555
static int c = 0;
5656
c++;
57-
tal_t *this_ctx = tal(ctx, tal_t);
57+
const tal_t *this_ctx = tal(ctx, tal_t);
5858

5959
int N_nodes, N_arcs;
6060
ret = myscanf("%d %d\n", &N_nodes, &N_arcs);

0 commit comments

Comments
 (0)