141 строка
4.3 KiB
C
141 строка
4.3 KiB
C
|
/*
|
||
|
* Copyright (c) 2014 Cisco Systems, Inc. All rights reserved.
|
||
|
* Copyright (c) 2017 Amazon.com, Inc. or its affiliates. All Rights
|
||
|
* reserved.
|
||
|
* $COPYRIGHT$
|
||
|
*
|
||
|
* Additional copyrights may follow
|
||
|
*
|
||
|
* $HEADER$
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* This file defines a number of internal structures to the BP graph
|
||
|
* code which need to be exposed only for unit testing. This file
|
||
|
* should not be included in code that uses the BP graph interface.
|
||
|
*/
|
||
|
|
||
|
#ifndef BIPARTITE_GRAPH_INTERNAL
|
||
|
#define BIPARTITE_GRAPH_INTERNAL 1
|
||
|
|
||
|
struct opal_bp_graph_edge_t {
|
||
|
opal_object_t super;
|
||
|
|
||
|
opal_list_item_t outbound_li;
|
||
|
opal_list_item_t inbound_li;
|
||
|
|
||
|
/** source of this edge */
|
||
|
int source;
|
||
|
|
||
|
/** v_index of target of this edge */
|
||
|
int target;
|
||
|
|
||
|
/** cost (weight) of this edge */
|
||
|
int64_t cost;
|
||
|
|
||
|
/**
|
||
|
* (flow-network) capacity of this edge. Zero-capacity edges essentially do
|
||
|
* not exist and will be ignored by most of the algorithms implemented here.
|
||
|
*/
|
||
|
int capacity;
|
||
|
|
||
|
/** any other information associated with this edge */
|
||
|
void *e_data;
|
||
|
};
|
||
|
|
||
|
struct opal_bp_graph_vertex_t {
|
||
|
/** index in the graph's array of vertices */
|
||
|
int v_index;
|
||
|
|
||
|
/** any other information associated with the vertex */
|
||
|
void *v_data;
|
||
|
|
||
|
/** linked list of edges for which this vertex is a source */
|
||
|
opal_list_t out_edges;
|
||
|
|
||
|
/** linked list of edges for which this vertex is a target */
|
||
|
opal_list_t in_edges;
|
||
|
};
|
||
|
|
||
|
struct opal_bp_graph_t {
|
||
|
/** number of vertices currently in this graph */
|
||
|
int num_vertices;
|
||
|
|
||
|
/** vertices in this graph (with number of set elements == num_vertices) */
|
||
|
opal_pointer_array_t vertices;
|
||
|
|
||
|
/** index of the source vertex, or -1 if not present */
|
||
|
int source_idx;
|
||
|
|
||
|
/** index of the sink vertex, or -1 if not present */
|
||
|
int sink_idx;
|
||
|
|
||
|
/** user callback to clean up the v_data */
|
||
|
opal_bp_graph_cleanup_fn_t v_data_cleanup_fn;
|
||
|
|
||
|
/** user callback to clean up the e_data */
|
||
|
opal_bp_graph_cleanup_fn_t e_data_cleanup_fn;
|
||
|
};
|
||
|
|
||
|
|
||
|
#define LIST_FOREACH_CONTAINED(item, list, type, member) \
|
||
|
for (item = container_of( (list)->opal_list_sentinel.opal_list_next, type, member ); \
|
||
|
&item->member != &(list)->opal_list_sentinel; \
|
||
|
item = container_of( \
|
||
|
((opal_list_item_t *) (&item->member))->opal_list_next, type, member ))
|
||
|
|
||
|
#define LIST_FOREACH_SAFE_CONTAINED(item, next, list, type, member) \
|
||
|
for (item = container_of( (list)->opal_list_sentinel.opal_list_next, type, member ), \
|
||
|
next = container_of( \
|
||
|
((opal_list_item_t *) (&item->member))->opal_list_next, type, member ); \
|
||
|
&item->member != &(list)->opal_list_sentinel; \
|
||
|
item = next, \
|
||
|
next = container_of( \
|
||
|
((opal_list_item_t *) (&item->member))->opal_list_next, type, member ))
|
||
|
|
||
|
#define NUM_VERTICES(g) (g->num_vertices)
|
||
|
|
||
|
#define CHECK_VERTEX_RANGE(g,v) \
|
||
|
do { \
|
||
|
if ((v) < 0 || \
|
||
|
(v) >= NUM_VERTICES(g)) { \
|
||
|
return OPAL_ERR_BAD_PARAM; \
|
||
|
} \
|
||
|
} while (0)
|
||
|
|
||
|
/* cast away any constness of &g->vertices b/c the opal_pointer_array API is
|
||
|
* not const-correct */
|
||
|
#define V_ID_TO_PTR(g, v_id) \
|
||
|
((opal_bp_graph_vertex_t *) \
|
||
|
opal_pointer_array_get_item((opal_pointer_array_t *)&g->vertices, v_id))
|
||
|
|
||
|
#define FOREACH_OUT_EDGE(g,v_id,e_ptr) \
|
||
|
LIST_FOREACH_CONTAINED(e_ptr, \
|
||
|
&(V_ID_TO_PTR(g, v_id)->out_edges), \
|
||
|
opal_bp_graph_edge_t, \
|
||
|
outbound_li)
|
||
|
|
||
|
#define FOREACH_IN_EDGE(g,v_id,e_ptr) \
|
||
|
LIST_FOREACH_CONTAINED(e_ptr, \
|
||
|
&(V_ID_TO_PTR(g, v_id)->in_edges), \
|
||
|
opal_bp_graph_edge_t, \
|
||
|
inbound_li)
|
||
|
|
||
|
|
||
|
/* Iterate over (u,v) edge pairs along the given path, where path is defined
|
||
|
* by the predecessor array "pred". Stops when a -1 predecessor is
|
||
|
* encountered. Note: because it is a *predecessor* array, the traversal
|
||
|
* starts at the sink and progresses towards the source. */
|
||
|
#define FOREACH_UV_ON_PATH(pred, source, sink, u, v) \
|
||
|
for (u = pred[sink], v = sink; u != -1; v = u, u = pred[u])
|
||
|
|
||
|
|
||
|
bool opal_bp_graph_bellman_ford(opal_bp_graph_t *gx,
|
||
|
int source,
|
||
|
int target,
|
||
|
int *pred);
|
||
|
|
||
|
int opal_bp_graph_bipartite_to_flow(opal_bp_graph_t *g);
|
||
|
|
||
|
#endif
|