00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef CUGRA_GRAPH_H
00019 #define CUGRA_GRAPH_H
00020
00021 #include <cugra/fwd.h>
00022 #include <cu/clos.h>
00023 #include <cu/dlink.h>
00024 #include <cu/ptr.h>
00025
00026 CU_BEGIN_DECLARATIONS
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 #define CUGRA_GFLAG_UNDIRECTED 1
00048 #define CUGRA_GFLAG_LOOPFREE 2
00049 #define CUGRA_GFLAG_SIMPLEARCED 4
00050
00051 typedef enum {
00052 cugra_direction_BEGIN,
00053 cugra_direction_out = 0,
00054 cugra_direction_in = 1,
00055 cugra_direction_END
00056 } cugra_direction_t;
00057
00058 struct cugra_graph
00059 {
00060 unsigned int gflags;
00061 struct cu_dlink vertices;
00062 };
00063
00064 struct cugra_graph_with_arcset
00065 {
00066 cu_inherit (cugra_graph);
00067 size_t arcset_size;
00068 size_t arcset_mask;
00069 struct cugraP_arcset_node **arcset_arr;
00070 };
00071
00072 struct cugra_vertex
00073 {
00074 struct cu_dlink in_graph;
00075 struct cu_dlink adj_link[2];
00076 };
00077
00078 struct cugra_adjlink
00079 {
00080 struct cu_dlink link;
00081 cugra_vertex_t vertex;
00082 };
00083
00084 struct cugra_arc
00085 {
00086 struct cugra_adjlink adj[2];
00087 };
00088
00089
00090 #define CUGRAP_ARC_ADJLINK_LINK_OFFSET(dir) \
00091 ( offsetof(struct cugra_arc, adj[0]) \
00092 + sizeof(struct cugra_adjlink)*(dir) \
00093 + offsetof(struct cugra_adjlink, link) )
00094
00095
00096
00097
00098 void cugra_graph_init(cugra_graph_t G, unsigned int gflags);
00099
00100
00101 cugra_graph_t cugra_graph_new(unsigned int gflags);
00102
00103
00104 void cugra_graph_merge(cugra_graph_t G_dst, cugra_graph_t G_src);
00105
00106
00107
00108 CU_SINLINE cu_bool_t cugra_graph_is_directed(cugra_graph_t G)
00109 { return !(G->gflags & CUGRA_GFLAG_UNDIRECTED); }
00110
00111
00112
00113 CU_SINLINE cu_bool_t cugra_graph_is_simplearced(cugra_graph_t G)
00114 { return G->gflags & CUGRA_GFLAG_SIMPLEARCED; }
00115
00116
00117
00118 void cugra_graph_vertex_init(cugra_graph_t G, cugra_vertex_t v);
00119
00120
00121
00122
00123 cugra_vertex_t cugra_graph_vertex_new(cugra_graph_t G);
00124
00125
00126 cugra_vertex_t cugra_graph_vertex_new_mem(cugra_graph_t G, size_t size);
00127
00128
00129 cugra_vertex_t cugra_graph_vertex_new_ptr(cugra_graph_t G, void *ptr);
00130
00131
00132 CU_SINLINE void *cugra_vertex_mem(cugra_vertex_t v) { return v + 1; }
00133
00134
00135 CU_SINLINE void *cugra_vertex_ptr(cugra_vertex_t v) { return *(void **)(v+1); }
00136
00137
00138 CU_SINLINE cu_bool_t cugra_vertex_is_isolated(cugra_vertex_t v)
00139 { return cu_dlink_is_singular(&v->adj_link[0])
00140 && cu_dlink_is_singular(&v->adj_link[1]); }
00141
00142
00143 CU_SINLINE cu_bool_t cugra_vertex_is_sink(cugra_vertex_t v)
00144 { return cu_dlink_is_singular(&v->adj_link[0]); }
00145
00146
00147 CU_SINLINE cu_bool_t cugra_vertex_is_source(cugra_vertex_t v)
00148 { return cu_dlink_is_singular(&v->adj_link[1]); }
00149
00150
00151 CU_SINLINE cu_bool_t cugra_vertex_is_convergency(cugra_vertex_t v)
00152 { return cu_dlink_is_2node(&v->adj_link[0]); }
00153
00154
00155 CU_SINLINE cu_bool_t cugra_vertex_is_divergency(cugra_vertex_t v)
00156 { return cu_dlink_is_2node(&v->adj_link[1]); }
00157
00158
00159 CU_SINLINE cu_bool_t cugra_vertex_outdegree_leq_1(cugra_vertex_t v)
00160 { return cu_dlink_count_leq_2(&v->adj_link[0]); }
00161
00162
00163 CU_SINLINE cu_bool_t cugra_vertex_indegree_leq_1(cugra_vertex_t v)
00164 { return cu_dlink_count_leq_2(&v->adj_link[1]); }
00165
00166
00167 cu_bool_t cugra_vertex_has_loop(cugra_vertex_t v);
00168
00169
00170
00171
00172
00173 cu_bool_t cugra_connect_custom(cugra_graph_t G,
00174 cugra_vertex_t tail, cugra_vertex_t head,
00175 size_t arc_size, cugra_arc_t *arc_out);
00176
00177
00178
00179 cu_bool_t cugra_connect(cugra_graph_t G,
00180 cugra_vertex_t tail, cugra_vertex_t head);
00181
00182
00183 int cugra_disconnect(cugra_graph_t G, cugra_vertex_t tail, cugra_vertex_t head);
00184
00185
00186 void cugra_erase_arc(cugra_graph_t G, cugra_arc_t arc);
00187
00188
00189 cugra_arc_t cugra_graph_arc_new(cugra_vertex_t tail, cugra_vertex_t head)
00190 CU_ATTR_DEPRECATED;
00191
00192
00193
00194 cugra_arc_t cugra_graph_arc_new_mem(cugra_vertex_t tail, cugra_vertex_t head,
00195 size_t size)
00196 CU_ATTR_DEPRECATED;
00197
00198
00199
00200 cugra_arc_t cugra_graph_arc_new_ptr(cugra_vertex_t tail, cugra_vertex_t head,
00201 void *ptr)
00202 CU_ATTR_DEPRECATED;
00203
00204
00205 void cugra_erase_vertex(cugra_graph_t G, cugra_vertex_t v);
00206
00207 cu_clos_edec(cugra_erase_vertex_clos, cu_prot(void, cugra_vertex_t),
00208 (cugra_graph_t G;));
00209
00210
00211
00212 void cugra_eliminate_vertex(cugra_graph_t G, cugra_vertex_t v);
00213
00214
00215 void cugra_vertex_erase_loops(cugra_graph_t G, cugra_vertex_t v);
00216
00217
00218 void cugra_graph_erase_loops(cugra_graph_t G);
00219
00220
00221 CU_SINLINE void *cugra_arc_mem(cugra_arc_t a) { return a + 1; }
00222
00223
00224 CU_SINLINE void *cugra_arc_ptr(cugra_arc_t a) { return *(void **)(a + 1); }
00225
00226
00227
00228 CU_SINLINE cugra_vertex_t
00229 cugra_arc_adjacent(cugra_direction_t dir, cugra_arc_t e)
00230 { return e->adj[dir].vertex; }
00231
00232
00233 CU_SINLINE cugra_vertex_t
00234 cugra_arc_head(cugra_arc_t e) { return e->adj[cugra_direction_out].vertex; }
00235
00236
00237 CU_SINLINE cugra_vertex_t
00238 cugra_arc_tail(cugra_arc_t e) { return e->adj[cugra_direction_in].vertex; }
00239
00240
00241 CU_SINLINE cu_bool_t
00242 cugra_arc_connects(cugra_arc_t a, cugra_vertex_t vT, cugra_vertex_t vH)
00243 { return cugra_arc_tail(a) == vT && cugra_arc_head(a) == vH; }
00244
00245
00246 CU_SINLINE cu_bool_t
00247 cugra_arc_unord_connects(cugra_arc_t a, cugra_vertex_t v0, cugra_vertex_t v1)
00248 { return cugra_arc_head(a) == v0? cugra_arc_tail(a) == v1
00249 : cugra_arc_head(a) == v1 && cugra_arc_tail(a) == v0; }
00250
00251
00252 CU_SINLINE cu_bool_t
00253 cugra_arc_is_loop(cugra_arc_t a)
00254 { return cugra_arc_head(a) == cugra_arc_tail(a); }
00255
00256
00257 CU_SINLINE cugra_arc_t
00258 cugra_vertex_arcs_begin(cugra_direction_t dir, cugra_vertex_t v)
00259 {
00260 return (cugra_arc_t)cu_ptr_sub(v->adj_link[dir].next,
00261 CUGRAP_ARC_ADJLINK_LINK_OFFSET(dir));
00262 }
00263
00264
00265 CU_SINLINE cugra_arc_t
00266 cugra_vertex_arcs_end(cugra_direction_t dir, cugra_vertex_t v)
00267 {
00268 return (cugra_arc_t)cu_ptr_sub(&v->adj_link[dir],
00269 CUGRAP_ARC_ADJLINK_LINK_OFFSET(dir));
00270 }
00271
00272
00273
00274 CU_SINLINE cugra_arc_t
00275 cugra_vertex_arcs_next(cugra_direction_t dir, cugra_arc_t e)
00276 {
00277 return (cugra_arc_t)cu_ptr_sub(e->adj[dir].link.next,
00278 CUGRAP_ARC_ADJLINK_LINK_OFFSET(dir));
00279 }
00280
00281
00282 CU_SINLINE cugra_arc_t cugra_vertex_outarcs_begin(cugra_vertex_t v)
00283 { return cugra_vertex_arcs_begin(cugra_direction_out, v); }
00284
00285
00286 CU_SINLINE cugra_arc_t cugra_vertex_outarcs_end(cugra_vertex_t v)
00287 { return cugra_vertex_arcs_end(cugra_direction_out, v); }
00288
00289
00290 CU_SINLINE cugra_arc_t cugra_vertex_outarcs_next(cugra_arc_t e)
00291 { return cugra_vertex_arcs_next(cugra_direction_out, e); }
00292
00293
00294 CU_SINLINE cugra_arc_t cugra_vertex_inarcs_begin(cugra_vertex_t v)
00295 { return cugra_vertex_arcs_begin(cugra_direction_in, v); }
00296
00297
00298 CU_SINLINE cugra_arc_t cugra_vertex_inarcs_end(cugra_vertex_t v)
00299 { return cugra_vertex_arcs_end(cugra_direction_in, v); }
00300
00301
00302 CU_SINLINE cugra_arc_t cugra_vertex_inarcs_next(cugra_arc_t e)
00303 { return cugra_vertex_arcs_next(cugra_direction_in, e); }
00304
00305
00306 CU_SINLINE cugra_vertex_t cugra_graph_vertices_begin(cugra_graph_t G)
00307 {
00308 return (cugra_vertex_t)cu_ptr_add(G->vertices.next,
00309 -offsetof(struct cugra_vertex, in_graph));
00310 }
00311
00312
00313 CU_SINLINE cugra_vertex_t cugra_graph_vertices_end(cugra_graph_t G)
00314 {
00315 return (cugra_vertex_t)cu_ptr_add(&G->vertices,
00316 -offsetof(struct cugra_vertex, in_graph));
00317 }
00318
00319
00320 CU_SINLINE cugra_vertex_t cugra_graph_vertices_next(cugra_vertex_t v)
00321 {
00322 return (cugra_vertex_t)cu_ptr_add(v->in_graph.next,
00323 -offsetof(struct cugra_vertex, in_graph));
00324 }
00325
00326
00327 cugra_arc_t cugra_graph_arcs_begin(cugra_graph_t G);
00328
00329
00330 CU_SINLINE cugra_arc_t cugra_graph_arcs_end(cugra_graph_t G) { return NULL; }
00331
00332
00333 cugra_arc_t cugra_graph_arcs_next(cugra_graph_t G, cugra_arc_t a);
00334
00335
00336 #define cugra_vertex_for_inarcs(a, v) \
00337 for (a = cugra_vertex_inarcs_begin(v); \
00338 a != cugra_vertex_inarcs_end(v); \
00339 a = cugra_vertex_inarcs_next(a))
00340
00341 #define cugra_vertex_for_outarcs(a, v) \
00342 for (a = cugra_vertex_outarcs_begin(v); \
00343 a != cugra_vertex_outarcs_end(v); \
00344 a = cugra_vertex_outarcs_next(a))
00345
00346 #define cugra_vertex_for_arcs(dir, a, v) \
00347 for (a = cugra_vertex_arcs_begin(dir, v); \
00348 a != cugra_vertex_arcs_end(dir, v); \
00349 a = cugra_vertex_arcs_next(dir, a))
00350
00351 #define cugra_vertex_for_inoutarcs(dir, a, v) \
00352 for (dir = cugra_direction_BEGIN; dir < cugra_direction_END; ++dir) \
00353 for (a = cugra_vertex_arcs_begin(dir, v); \
00354 a != cugra_vertex_arcs_end(dir, v); \
00355 a = cugra_vertex_arcs_next(dir, a))
00356
00357 #define cugra_graph_for_vertices(v, G) \
00358 for (v = cugra_graph_vertices_begin(G); \
00359 v != cugra_graph_vertices_end(G); \
00360 v = cugra_graph_vertices_next(v))
00361
00362
00363
00364 #if CU_COMPAT < 20080210
00365 # define cugra_vertex_inarcs_for cugra_vertex_for_inarcs
00366 # define cugra_vertex_outarcs_for cugra_vertex_for_outarcs
00367 # define cugra_vertex_arcs_for cugra_vertex_for_arcs
00368 # define cugra_vertex_inoutarcs_for cugra_vertex_for_inoutarcs
00369 # define cugra_graph_vertices_for cugra_graph_for_vertices
00370 #endif
00371 #define cugra_graph_cct cugra_graph_init
00372
00373 CU_END_DECLARATIONS
00374
00375 #endif