mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-02-24 23:18:25 +01:00
- 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 <lagrang3@protonmail.com>
171 lines
5 KiB
C
171 lines
5 KiB
C
#ifndef LIGHTNING_PLUGINS_ASKRENE_GRAPH_H
|
|
#define LIGHTNING_PLUGINS_ASKRENE_GRAPH_H
|
|
|
|
/* Defines a graph data structure. */
|
|
|
|
#include "config.h"
|
|
#include <assert.h>
|
|
#include <ccan/short_types/short_types.h>
|
|
#include <ccan/tal/tal.h>
|
|
|
|
#define INVALID_INDEX 0xffffffff
|
|
|
|
/* A directed arc in a graph.
|
|
* It is a simple data object for typesafey. */
|
|
struct arc {
|
|
/* arc's index */
|
|
u32 idx;
|
|
};
|
|
|
|
/* A node in a graph.
|
|
* It is a simple data object for typesafety. */
|
|
struct node {
|
|
/* node's index */
|
|
u32 idx;
|
|
};
|
|
|
|
static inline struct arc arc_obj(u32 index)
|
|
{
|
|
struct arc arc = {.idx = index};
|
|
return arc;
|
|
}
|
|
static inline struct node node_obj(u32 index)
|
|
{
|
|
struct node node = {.idx = index};
|
|
return node;
|
|
}
|
|
|
|
/* A graph's topology. */
|
|
struct graph {
|
|
/* Every arc emanates from a node, the tail.
|
|
* The head of the arc is the tail of the dual. */
|
|
struct node *arc_tail;
|
|
|
|
/* Adjacency data for nodes. Used to move in a graph in the direction of
|
|
* the arcs by looping over all arcs that exit a node.
|
|
*
|
|
* For every directed arc there is a dual in the opposite direction,
|
|
* therefore we can use the same adjacency information to traverse in
|
|
* the head to tails direction as well. */
|
|
struct arc *node_adjacency_next;
|
|
struct arc *node_adjacency_first;
|
|
|
|
size_t max_num_arcs, max_num_nodes;
|
|
|
|
/* Bit that must be flipped to obtain the dual of an arc. */
|
|
size_t arc_dual_bit;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
static inline size_t graph_max_num_arcs(const struct graph *graph)
|
|
{
|
|
return graph->max_num_arcs;
|
|
}
|
|
static inline size_t graph_max_num_nodes(const struct graph *graph)
|
|
{
|
|
return graph->max_num_nodes;
|
|
}
|
|
|
|
/* Give me the dual of an arc. */
|
|
static inline struct arc arc_dual(const struct graph *graph, struct arc arc)
|
|
{
|
|
arc.idx ^= (1U << graph->arc_dual_bit);
|
|
return arc;
|
|
}
|
|
|
|
/* Is this arc a dual? */
|
|
static inline bool arc_is_dual(const struct graph *graph, struct arc arc)
|
|
{
|
|
return (arc.idx & (1U << graph->arc_dual_bit)) != 0;
|
|
}
|
|
|
|
/* Give me the node at the tail of an arc. */
|
|
static inline struct node arc_tail(const struct graph *graph,
|
|
const struct arc arc)
|
|
{
|
|
assert(arc.idx < graph_max_num_arcs(graph));
|
|
return graph->arc_tail[arc.idx];
|
|
}
|
|
|
|
/* Give me the node at the head of an arc. */
|
|
static inline struct node arc_head(const struct graph *graph,
|
|
const struct arc arc)
|
|
{
|
|
const struct arc dual = arc_dual(graph, arc);
|
|
assert(dual.idx < graph_max_num_arcs(graph));
|
|
return graph->arc_tail[dual.idx];
|
|
}
|
|
|
|
/* We use an arc array but not all arcs in that array do exist in the graph. */
|
|
static inline bool arc_enabled(const struct graph *graph, const struct arc arc)
|
|
{
|
|
return graph->arc_tail[arc.idx].idx < graph->max_num_nodes;
|
|
}
|
|
|
|
/* Used to loop over the arcs that exit a node.
|
|
*
|
|
* for example:
|
|
*
|
|
* void show(struct graph *graph, struct node node) {
|
|
* printf("Showing node %" PRIu32 "\n", node.idx);
|
|
* for (struct arc arc = node_adjacency_begin(graph, node);
|
|
* !node_adjacency_end(arc);
|
|
* arc = node_adjacency_next(graph, arc)) {
|
|
* printf("arc id: %" PRIu32 ", (%" PRIu32 " -> %" PRIu32 ")\n",
|
|
* arc.idx,
|
|
* arc_tail(graph, arc).idx,
|
|
* arc_head(graph, arc).idx);
|
|
* }
|
|
* }
|
|
* */
|
|
static inline struct arc node_adjacency_begin(const struct graph *graph,
|
|
const struct node node)
|
|
{
|
|
assert(node.idx < graph_max_num_nodes(graph));
|
|
return graph->node_adjacency_first[node.idx];
|
|
}
|
|
static inline bool node_adjacency_end(const struct arc arc)
|
|
{
|
|
return arc.idx == INVALID_INDEX;
|
|
}
|
|
static inline struct arc node_adjacency_next(const struct graph *graph,
|
|
const struct arc arc)
|
|
{
|
|
assert(arc.idx < graph_max_num_arcs(graph));
|
|
return graph->node_adjacency_next[arc.idx];
|
|
}
|
|
|
|
/* Used to loop over the arcs that enter a node. */
|
|
static inline struct arc node_rev_adjacency_begin(const struct graph *graph,
|
|
const struct node node)
|
|
{
|
|
return arc_dual(graph, node_adjacency_begin(graph, node));
|
|
}
|
|
static inline bool node_rev_adjacency_end(const struct arc arc)
|
|
{
|
|
return arc.idx == INVALID_INDEX;
|
|
}
|
|
static inline struct arc node_rev_adjacency_next(const struct graph *graph,
|
|
const struct arc arc)
|
|
{
|
|
return arc_dual(graph,
|
|
node_adjacency_next(graph, arc_dual(graph, arc)));
|
|
}
|
|
|
|
/* This call adds an arc to the graph, it adds also the dual automatically.
|
|
* An arc cannot be added twice, if the caller tries to do add the same arc
|
|
* twice the second call is ignored.
|
|
* The call fails if the arc or its dual do not fit into max_num_arcs. */
|
|
bool graph_add_arc(struct graph *graph, const struct arc arc,
|
|
const struct node from, const struct node to);
|
|
|
|
/* Creates a graph object. Nodes and arcs are indexed from 0 to max_num_nodes-1
|
|
* and max_num_arcs-1 respectively. The max_num_arcs should be big enough to
|
|
* accomodate also the dual arcs, ie. if the maximum index for a problem arc is
|
|
* I then Idual = I^(1<<arc_dual_bit) must be a valid arc index
|
|
* Idual<max_num_arcs. */
|
|
struct graph *graph_new(const tal_t *ctx, const size_t max_num_nodes,
|
|
const size_t max_num_arcs, const size_t arc_dual_bit);
|
|
|
|
#endif /* LIGHTNING_PLUGINS_ASKRENE_GRAPH_H */
|