Skip to content

Commit

Permalink
Merge pull request #1 from madmann91/graph_edge_data
Browse files Browse the repository at this point in the history
Add user data field to graph edges
  • Loading branch information
madmann91 authored Apr 14, 2024
2 parents 502ad5d + 395b902 commit be13dbd
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 28 deletions.
35 changes: 28 additions & 7 deletions src/overture/graph.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,18 @@ struct graph_node* graph_sink(struct graph* graph, enum graph_dir dir) {
}

static inline struct graph_node* alloc_graph_node(size_t data_size) {
return xcalloc(1, sizeof(struct graph_node) + data_size * sizeof(union graph_node_data));
return xcalloc(1, sizeof(struct graph_node) + data_size * sizeof(union graph_user_data));
}

struct graph graph_create(size_t data_size, void* source_key, void* sink_key) {
static inline struct graph_edge* alloc_graph_edge(size_t data_size) {
return xcalloc(1, sizeof(struct graph_edge) + data_size * sizeof(union graph_user_data));
}

struct graph graph_create(size_t node_data_size, size_t edge_data_size, void* source_key, void* sink_key) {
assert((source_key == NULL && sink_key == NULL) || source_key != sink_key);

struct graph_node* source = alloc_graph_node(data_size);
struct graph_node* sink = alloc_graph_node(data_size);
struct graph_node* source = alloc_graph_node(node_data_size);
struct graph_node* sink = alloc_graph_node(node_data_size);
source->index = GRAPH_SOURCE_INDEX;
sink->index = GRAPH_SINK_INDEX;
source->key = source_key;
Expand All @@ -102,7 +106,8 @@ struct graph graph_create(size_t data_size, void* source_key, void* sink_key) {
.source = source,
.sink = sink,
.node_count = GRAPH_OTHER_INDEX,
.data_size = data_size,
.node_data_size = node_data_size,
.edge_data_size = edge_data_size,
.nodes = nodes,
.edges = graph_edge_set_create()
};
Expand Down Expand Up @@ -135,7 +140,7 @@ struct graph_node* graph_insert(struct graph* graph, void* key) {
if (node)
return node;

node = alloc_graph_node(graph->data_size);
node = alloc_graph_node(graph->node_data_size);
node->index = graph->node_count++;
node->key = key;
[[maybe_unused]] bool was_inserted = graph_node_key_map_insert(&graph->nodes, &key, &node);
Expand All @@ -156,7 +161,7 @@ struct graph_edge* graph_connect(
if (edge_ptr)
return *edge_ptr;

edge = xmalloc(sizeof(struct graph_edge));
edge = alloc_graph_edge(graph->edge_data_size);
edge->from = from;
edge->to = to;
edge->next_in = to->ins;
Expand All @@ -167,6 +172,22 @@ struct graph_edge* graph_connect(
return edge;
}

bool graph_disconnect(
struct graph* graph,
struct graph_node* from,
struct graph_node* to)
{
struct graph_edge* edge = &(struct graph_edge) { .from = from, .to = to };
struct graph_edge* const* edge_ptr = graph_edge_set_find(&graph->edges, &edge);
if (!edge_ptr)
return false;

edge = *edge_ptr;
graph_edge_set_remove(&graph->edges, &edge);
free(edge);
return true;
}

struct graph_node_vec graph_compute_post_order(struct graph* graph, enum graph_dir dir) {
struct graph_node_vec post_order = graph_node_vec_create();
struct graph_node_set visited_set = graph_node_set_create();
Expand Down
55 changes: 35 additions & 20 deletions src/overture/graph.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,19 @@

struct graph_node;

/// Per-node or per-edge user data.
union graph_user_data {
void* ptr;
size_t index;
};

/// Graph edge.
struct graph_edge {
struct graph_node* from; /// Source node.
struct graph_node* to; /// Target node.
struct graph_edge* next_in; /// Next incoming edge (with same target), or `NULL`.
struct graph_edge* next_out; /// Next outgoing edge (with same source), or `NULL`.
struct graph_node* from; /// Source node.
struct graph_node* to; /// Target node.
struct graph_edge* next_in; /// Next incoming edge (with same target), or `NULL`.
struct graph_edge* next_out; /// Next outgoing edge (with same source), or `NULL`.
union graph_user_data user_data[]; /// Custom user data.
};

/// Reserved node indices.
Expand All @@ -48,19 +55,13 @@ enum graph_node_index {
GRAPH_OTHER_INDEX
};

/// Per-node user data.
union graph_node_data {
void* ptr;
size_t index;
};

/// Graph node.
struct graph_node {
size_t index; /// Unique index of the node.
void* key; /// Key or label uniquely identifying the node.
struct graph_edge* ins; /// Incoming edges (edges which have this node as target), or `NULL`.
struct graph_edge* outs; /// Outgoing edges (edges which have this node as source), or `NULL`.
union graph_node_data data[]; /// Custom node data.
size_t index; /// Unique index of the node.
void* key; /// Key or label uniquely identifying the node.
struct graph_edge* ins; /// Incoming edges (edges which have this node as target), or `NULL`.
struct graph_edge* outs; /// Outgoing edges (edges which have this node as source), or `NULL`.
union graph_user_data user_data[]; /// Custom user data.
};

SET_DECL(graph_edge_set, struct graph_edge*, PUBLIC)
Expand All @@ -76,7 +77,9 @@ MAP_DECL(graph_node_key_map, void*, struct graph_node*, PUBLIC)
/// Graph data structure.
struct graph {
size_t node_count; /// Number of nodes in the graph.
size_t data_size; /// Number of elements in the per-node data.
size_t edge_count; /// Number of edges in the graph.
size_t node_data_size; /// Number of elements in the per-node data.
size_t edge_data_size; /// Number of elements in the per-edge data.
struct graph_node* source; /// Pointer to the source node of the graph.
struct graph_node* sink; /// Pointer to the sink node of the graph.
struct graph_node_key_map nodes; /// Nodes of the graph.
Expand All @@ -102,10 +105,19 @@ enum graph_dir {
/// Returns the sink or the source of the graph, depending on the given direction.
[[nodiscard]] struct graph_node* graph_sink(struct graph*, enum graph_dir);

/// Creates a graph with the given data size per node, and with just a source and a sink using the
/// given keys as labels for each. The source and sink key can be `NULL`, but this means that they
/// will not be findable via `graph_find()`.
[[nodiscard]] struct graph graph_create(size_t data_size, void* source_key, void* sink_key);
/// Creates a graph with a source and sink node.
/// @param node_data_size Number of elements in the `data` field for each node.
/// @param edge_data_size Number of elements in the `data` field for each edge.
/// @param source_key Key to use to identify the source node. May be `NULL`, in which case the
/// source node cannot be found via @ref graph_find.
/// @param sink_key Key to use to identify the sink node. May be `NULL`, in which case the
/// source node cannot be found via @ref graph_find.
[[nodiscard]] struct graph graph_create(
size_t node_data_size,
size_t edge_data_size,
void* source_key,
void* sink_key);

/// Destroys the given graph.
void graph_destroy(struct graph*);

Expand All @@ -115,6 +127,9 @@ void graph_destroy(struct graph*);
struct graph_node* graph_insert(struct graph*, void* key);
/// Connects two nodes with an edge.
struct graph_edge* graph_connect(struct graph*, struct graph_node*, struct graph_node*);
/// Disconnects two nodes. The corresponding edge is destroyed.
/// @return `true` if the edge was removed, `false` otherwise (because the edge does not exist).
bool graph_disconnect(struct graph*, struct graph_node*, struct graph_node*);

/// Computes the post-order traversal of the graph, starting from the source or the sink of the
/// graph, depending on the traversal direction.
Expand Down
2 changes: 1 addition & 1 deletion test/graph.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

TEST(graph) {
int array[3] = {};
struct graph graph = graph_create(1, &array[0], &array[1]);
struct graph graph = graph_create(1, 0, &array[0], &array[1]);
graph_connect(&graph,
graph_insert(&graph, &array[0]),
graph_insert(&graph, &array[2]));
Expand Down

0 comments on commit be13dbd

Please sign in to comment.