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