LCOV - code coverage report
Current view: top level - glib/girepository/cmph - graph.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 0 159 0.0 %
Date: 2024-05-07 05:15:23 Functions: 0 19 0.0 %
Branches: 0 86 0.0 %

           Branch data     Line data    Source code
       1                 :            : #include "graph.h"
       2                 :            : 
       3                 :            : #include <stdio.h>
       4                 :            : #include <stdlib.h>
       5                 :            : #include <limits.h>
       6                 :            : #include <assert.h>
       7                 :            : #include <string.h>
       8                 :            : #include "vstack.h"
       9                 :            : #include "bitbool.h"
      10                 :            : 
      11                 :            : //#define DEBUG
      12                 :            : #include "debug.h"
      13                 :            : 
      14                 :            : /* static const cmph_uint8 bitmask[8] = { 1, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 1 << 6, 1 << 7 }; */
      15                 :            : /* #define GETBIT(array, i) (array[(i) / 8] & bitmask[(i) % 8]) */
      16                 :            : /* #define SETBIT(array, i) (array[(i) / 8] |= bitmask[(i) % 8]) */
      17                 :            : /* #define UNSETBIT(array, i) (array[(i) / 8] &= (~(bitmask[(i) % 8]))) */
      18                 :            : 
      19                 :            : #define abs_edge(e, i) (e % g->nedges + i * g->nedges)
      20                 :            : 
      21                 :            : struct __graph_t
      22                 :            : {
      23                 :            :         cmph_uint32 nnodes;
      24                 :            :         cmph_uint32 nedges;
      25                 :            :         cmph_uint32 *edges;
      26                 :            :         cmph_uint32 *first;
      27                 :            :         cmph_uint32 *next;
      28                 :            :         cmph_uint8  *critical_nodes;   /* included -- Fabiano*/
      29                 :            :         cmph_uint32 ncritical_nodes;   /* included -- Fabiano*/
      30                 :            :         cmph_uint32 cedges;
      31                 :            :         int shrinking;
      32                 :            : };
      33                 :            : 
      34                 :            : static cmph_uint32 EMPTY = UINT_MAX;
      35                 :            : 
      36                 :          0 : graph_t *graph_new(cmph_uint32 nnodes, cmph_uint32 nedges)
      37                 :            : {
      38                 :          0 :         graph_t *graph = (graph_t *)malloc(sizeof(graph_t));
      39         [ #  # ]:          0 :         if (!graph) return NULL;
      40                 :            : 
      41                 :          0 :         graph->edges = (cmph_uint32 *)malloc(sizeof(cmph_uint32) * 2 * nedges);
      42                 :          0 :         graph->next =  (cmph_uint32 *)malloc(sizeof(cmph_uint32) * 2 * nedges);
      43                 :          0 :         graph->first = (cmph_uint32 *)malloc(sizeof(cmph_uint32) * nnodes);
      44                 :          0 :         graph->critical_nodes = NULL; /* included -- Fabiano*/
      45                 :          0 :         graph->ncritical_nodes = 0;   /* included -- Fabiano*/
      46                 :          0 :         graph->nnodes = nnodes;
      47                 :          0 :         graph->nedges = nedges;
      48                 :            : 
      49                 :          0 :         graph_clear_edges(graph);
      50                 :          0 :         return graph;
      51                 :            : }
      52                 :            : 
      53                 :            : 
      54                 :          0 : void graph_destroy(graph_t *graph)
      55                 :            : {
      56                 :            :         DEBUGP("Destroying graph\n");
      57                 :          0 :         free(graph->edges);
      58                 :          0 :         free(graph->first);
      59                 :          0 :         free(graph->next);
      60                 :          0 :         free(graph->critical_nodes); /* included -- Fabiano*/
      61                 :          0 :         free(graph);
      62                 :          0 :         return;
      63                 :            : }
      64                 :            : 
      65                 :          0 : void graph_print(graph_t *g)
      66                 :            : {
      67                 :            :         cmph_uint32 i, e;
      68         [ #  # ]:          0 :         for (i = 0; i < g->nnodes; ++i)
      69                 :            :         {
      70                 :            :                 DEBUGP("Printing edges connected to %u\n", i);
      71                 :          0 :                 e = g->first[i];
      72         [ #  # ]:          0 :                 if (e != EMPTY)
      73                 :            :                 {
      74                 :          0 :                         printf("%u -> %u\n", g->edges[abs_edge(e, 0)], g->edges[abs_edge(e, 1)]);
      75         [ #  # ]:          0 :                         while ((e = g->next[e]) != EMPTY)
      76                 :            :                         {
      77                 :          0 :                                 printf("%u -> %u\n", g->edges[abs_edge(e, 0)], g->edges[abs_edge(e, 1)]);
      78                 :            :                         }
      79                 :            :                 }
      80                 :            :                         
      81                 :            :         }
      82                 :          0 :         return;
      83                 :            : }
      84                 :            : 
      85                 :          0 : void graph_add_edge(graph_t *g, cmph_uint32 v1, cmph_uint32 v2)
      86                 :            : {
      87                 :          0 :         cmph_uint32 e = g->cedges;
      88                 :            : 
      89         [ #  # ]:          0 :         assert(v1 < g->nnodes);
      90         [ #  # ]:          0 :         assert(v2 < g->nnodes);
      91         [ #  # ]:          0 :         assert(e < g->nedges);
      92         [ #  # ]:          0 :         assert(!g->shrinking);
      93                 :            : 
      94                 :          0 :         g->next[e] = g->first[v1];
      95                 :          0 :         g->first[v1] = e;
      96                 :          0 :         g->edges[e] = v2;
      97                 :            : 
      98                 :          0 :         g->next[e + g->nedges] = g->first[v2];
      99                 :          0 :         g->first[v2] = e + g->nedges;
     100                 :          0 :         g->edges[e + g->nedges] = v1;
     101                 :            : 
     102                 :          0 :         ++(g->cedges);
     103                 :          0 : }
     104                 :            : 
     105                 :          0 : static int check_edge(graph_t *g, cmph_uint32 e, cmph_uint32 v1, cmph_uint32 v2)
     106                 :            : {
     107                 :            :         DEBUGP("Checking edge %u %u looking for %u %u\n", g->edges[abs_edge(e, 0)], g->edges[abs_edge(e, 1)], v1, v2);
     108   [ #  #  #  # ]:          0 :         if (g->edges[abs_edge(e, 0)] == v1 && g->edges[abs_edge(e, 1)] == v2) return 1;
     109   [ #  #  #  # ]:          0 :         if (g->edges[abs_edge(e, 0)] == v2 && g->edges[abs_edge(e, 1)] == v1) return 1;
     110                 :          0 :         return 0;
     111                 :            : }
     112                 :            : 
     113                 :          0 : cmph_uint32 graph_edge_id(graph_t *g, cmph_uint32 v1, cmph_uint32 v2)
     114                 :            : {
     115                 :            :         cmph_uint32 e;
     116                 :          0 :         e = g->first[v1];
     117         [ #  # ]:          0 :         assert(e != EMPTY);
     118         [ #  # ]:          0 :         if (check_edge(g, e, v1, v2)) return abs_edge(e, 0);
     119                 :            :         do
     120                 :            :         {
     121                 :          0 :                 e = g->next[e];
     122         [ #  # ]:          0 :                 assert(e != EMPTY);
     123                 :            :         }
     124         [ #  # ]:          0 :         while (!check_edge(g, e, v1, v2));
     125                 :          0 :         return abs_edge(e, 0);
     126                 :            : }
     127                 :          0 : static void del_edge_point(graph_t *g, cmph_uint32 v1, cmph_uint32 v2)
     128                 :            : {
     129                 :            :         cmph_uint32 e, prev;
     130                 :            : 
     131                 :            :         DEBUGP("Deleting edge point %u %u\n", v1, v2);
     132                 :          0 :         e = g->first[v1];
     133         [ #  # ]:          0 :         if (check_edge(g, e, v1, v2)) 
     134                 :            :         {
     135                 :          0 :                 g->first[v1] = g->next[e];
     136                 :            :                 //g->edges[e] = EMPTY;
     137                 :            :                 DEBUGP("Deleted\n");
     138                 :          0 :                 return;
     139                 :            :         }
     140                 :            :         DEBUGP("Checking linked list\n");
     141                 :            :         do
     142                 :            :         {
     143                 :          0 :                 prev = e;
     144                 :          0 :                 e = g->next[e];
     145         [ #  # ]:          0 :                 assert(e != EMPTY);
     146                 :            :         }
     147         [ #  # ]:          0 :         while (!check_edge(g, e, v1, v2));
     148                 :            : 
     149                 :          0 :         g->next[prev] = g->next[e];
     150                 :            :         //g->edges[e] = EMPTY;
     151                 :            :         DEBUGP("Deleted\n");
     152                 :            : }
     153                 :            : 
     154                 :            :         
     155                 :          0 : void graph_del_edge(graph_t *g, cmph_uint32 v1, cmph_uint32 v2)
     156                 :            : {
     157                 :          0 :         g->shrinking = 1;
     158                 :          0 :         del_edge_point(g, v1, v2);
     159                 :          0 :         del_edge_point(g, v2, v1);
     160                 :          0 : }
     161                 :            : 
     162                 :          0 : void graph_clear_edges(graph_t *g)
     163                 :            : {
     164                 :            :         cmph_uint32 i;
     165         [ #  # ]:          0 :         for (i = 0; i < g->nnodes; ++i) g->first[i] = EMPTY;
     166         [ #  # ]:          0 :         for (i = 0; i < g->nedges*2; ++i) 
     167                 :            :         {
     168                 :          0 :                 g->edges[i] = EMPTY;
     169                 :          0 :                 g->next[i] = EMPTY;
     170                 :            :         }
     171                 :          0 :         g->cedges = 0;
     172                 :          0 :         g->shrinking = 0;
     173                 :          0 : }
     174                 :            : 
     175                 :          0 : static cmph_uint8 find_degree1_edge(graph_t *g, cmph_uint32 v, cmph_uint8 *deleted, cmph_uint32 *e)
     176                 :            : {
     177                 :          0 :         cmph_uint32 edge = g->first[v];
     178                 :          0 :         cmph_uint8 found = 0;
     179                 :            :         DEBUGP("Checking degree of vertex %u\n", v);
     180         [ #  # ]:          0 :         if (edge == EMPTY) return 0;
     181         [ #  # ]:          0 :         else if (!(GETBIT(deleted, abs_edge(edge, 0)))) 
     182                 :            :         {
     183                 :          0 :                 found = 1;
     184                 :          0 :                 *e = edge;
     185                 :            :         }
     186                 :            :         while(1)
     187                 :            :         {
     188                 :          0 :                 edge = g->next[edge];
     189         [ #  # ]:          0 :                 if (edge == EMPTY) break;
     190         [ #  # ]:          0 :                 if (GETBIT(deleted, abs_edge(edge, 0))) continue;
     191         [ #  # ]:          0 :                 if (found) return 0;
     192                 :            :                 DEBUGP("Found first edge\n");
     193                 :          0 :                 *e = edge;
     194                 :          0 :                 found = 1;
     195                 :            :         }
     196                 :          0 :         return found;
     197                 :            : }
     198                 :            : 
     199                 :          0 : static void cyclic_del_edge(graph_t *g, cmph_uint32 v, cmph_uint8 *deleted)
     200                 :            : {
     201                 :            : 
     202                 :          0 :         cmph_uint32 e = 0;
     203                 :            :         cmph_uint8 degree1;
     204                 :          0 :         cmph_uint32 v1 = v;
     205                 :          0 :         cmph_uint32 v2 = 0;
     206                 :            : 
     207                 :          0 :         degree1 = find_degree1_edge(g, v1, deleted, &e);
     208         [ #  # ]:          0 :         if (!degree1) return;
     209                 :            :         while(1) 
     210                 :            :         {
     211                 :            :                 DEBUGP("Deleting edge %u (%u->%u)\n", e, g->edges[abs_edge(e, 0)], g->edges[abs_edge(e, 1)]);
     212                 :          0 :                 SETBIT(deleted, abs_edge(e, 0));
     213                 :            :                 
     214                 :          0 :                 v2 = g->edges[abs_edge(e, 0)];
     215         [ #  # ]:          0 :                 if (v2 == v1) v2 = g->edges[abs_edge(e, 1)];
     216                 :            : 
     217                 :            :                 DEBUGP("Checking if second endpoint %u has degree 1\n", v2); 
     218                 :          0 :                 degree1 = find_degree1_edge(g, v2, deleted, &e);
     219         [ #  # ]:          0 :                 if (degree1) 
     220                 :            :                 {
     221                 :            :                         DEBUGP("Inspecting vertex %u\n", v2);
     222                 :          0 :                         v1 = v2;
     223                 :            :                 }
     224                 :          0 :                 else break;
     225                 :            :         }
     226                 :            : }
     227                 :            : 
     228                 :          0 : int graph_is_cyclic(graph_t *g)
     229                 :            : {
     230                 :            :         cmph_uint32 i;
     231                 :            :         cmph_uint32 v;
     232                 :          0 :         cmph_uint8 *deleted = (cmph_uint8 *)malloc((g->nedges*sizeof(cmph_uint8))/8 + 1);
     233                 :          0 :         size_t deleted_len = g->nedges/8 + 1;
     234                 :          0 :         memset(deleted, 0, deleted_len);
     235                 :            : 
     236                 :            :         DEBUGP("Looking for cycles in graph with %u vertices and %u edges\n", g->nnodes, g->nedges);
     237         [ #  # ]:          0 :         for (v = 0; v < g->nnodes; ++v)
     238                 :            :         {
     239                 :          0 :                 cyclic_del_edge(g, v, deleted);
     240                 :            :         }
     241         [ #  # ]:          0 :         for (i = 0; i < g->nedges; ++i)
     242                 :            :         {
     243         [ #  # ]:          0 :                 if (!(GETBIT(deleted, i))) 
     244                 :            :                 {
     245                 :            :                         DEBUGP("Edge %u %u->%u was not deleted\n", i, g->edges[i], g->edges[i + g->nedges]);
     246                 :          0 :                         free(deleted);
     247                 :          0 :                         return 1;
     248                 :            :                 }
     249                 :            :         }
     250                 :          0 :         free(deleted);
     251                 :          0 :         return 0;
     252                 :            : }
     253                 :            : 
     254                 :          0 : cmph_uint8 graph_node_is_critical(graph_t * g, cmph_uint32 v) /* included -- Fabiano */
     255                 :            : {
     256                 :          0 :         return (cmph_uint8)GETBIT(g->critical_nodes,v);
     257                 :            : }
     258                 :            : 
     259                 :          0 : void graph_obtain_critical_nodes(graph_t *g) /* included -- Fabiano*/
     260                 :            : {
     261                 :            :         cmph_uint32 i;
     262                 :            :         cmph_uint32 v;
     263                 :          0 :         cmph_uint8 *deleted = (cmph_uint8 *)malloc((g->nedges*sizeof(cmph_uint8))/8+1);
     264                 :          0 :         size_t deleted_len = g->nedges/8 + 1;
     265                 :          0 :         memset(deleted, 0, deleted_len);
     266                 :          0 :         free(g->critical_nodes);
     267                 :          0 :         g->critical_nodes = (cmph_uint8 *)malloc((g->nnodes*sizeof(cmph_uint8))/8 + 1);
     268                 :          0 :         g->ncritical_nodes = 0;
     269                 :          0 :         memset(g->critical_nodes, 0, (g->nnodes*sizeof(cmph_uint8))/8 + 1);
     270                 :            :         DEBUGP("Looking for the 2-core in graph with %u vertices and %u edges\n", g->nnodes, g->nedges);
     271         [ #  # ]:          0 :         for (v = 0; v < g->nnodes; ++v)
     272                 :            :         {
     273                 :          0 :                 cyclic_del_edge(g, v, deleted);
     274                 :            :         }
     275                 :            : 
     276         [ #  # ]:          0 :         for (i = 0; i < g->nedges; ++i)
     277                 :            :         {
     278         [ #  # ]:          0 :                 if (!(GETBIT(deleted,i))) 
     279                 :            :                 {
     280                 :            :                         DEBUGP("Edge %u %u->%u belongs to the 2-core\n", i, g->edges[i], g->edges[i + g->nedges]);
     281         [ #  # ]:          0 :                         if(!(GETBIT(g->critical_nodes,g->edges[i]))) 
     282                 :            :                         {
     283                 :          0 :                           g->ncritical_nodes ++;
     284                 :          0 :                           SETBIT(g->critical_nodes,g->edges[i]);
     285                 :            :                         }
     286         [ #  # ]:          0 :                         if(!(GETBIT(g->critical_nodes,g->edges[i + g->nedges]))) 
     287                 :            :                         {
     288                 :          0 :                           g->ncritical_nodes ++;
     289                 :          0 :                           SETBIT(g->critical_nodes,g->edges[i + g->nedges]);
     290                 :            :                         }
     291                 :            :                 }
     292                 :            :         }
     293                 :          0 :         free(deleted);
     294                 :          0 : }
     295                 :            : 
     296                 :          0 : cmph_uint8 graph_contains_edge(graph_t *g, cmph_uint32 v1, cmph_uint32 v2) /* included -- Fabiano*/
     297                 :            : {
     298                 :            :         cmph_uint32 e;
     299                 :          0 :         e = g->first[v1];
     300         [ #  # ]:          0 :         if(e == EMPTY) return 0;
     301         [ #  # ]:          0 :         if (check_edge(g, e, v1, v2)) return 1;
     302                 :            :         do
     303                 :            :         {
     304                 :          0 :                 e = g->next[e];
     305         [ #  # ]:          0 :                 if(e == EMPTY) return 0;
     306                 :            :         }
     307         [ #  # ]:          0 :         while (!check_edge(g, e, v1, v2));
     308                 :          0 :         return 1;
     309                 :            : }
     310                 :            : 
     311                 :          0 : cmph_uint32 graph_vertex_id(graph_t *g, cmph_uint32 e, cmph_uint32 id) /* included -- Fabiano*/
     312                 :            : {
     313                 :          0 :   return (g->edges[e + id*g->nedges]);
     314                 :            : }
     315                 :            : 
     316                 :          0 : cmph_uint32 graph_ncritical_nodes(graph_t *g) /* included -- Fabiano*/
     317                 :            : {
     318                 :          0 :   return g->ncritical_nodes;
     319                 :            : }
     320                 :            : 
     321                 :          0 : graph_iterator_t graph_neighbors_it(graph_t *g, cmph_uint32 v)
     322                 :            : {
     323                 :            :         graph_iterator_t it;
     324                 :          0 :         it.vertex = v;
     325                 :          0 :         it.edge = g->first[v];
     326                 :          0 :         return it;
     327                 :            : }
     328                 :          0 : cmph_uint32 graph_next_neighbor(graph_t *g, graph_iterator_t* it)
     329                 :            : {
     330                 :            :         cmph_uint32 ret;
     331         [ #  # ]:          0 :         if(it->edge == EMPTY) return GRAPH_NO_NEIGHBOR; 
     332         [ #  # ]:          0 :         if (g->edges[it->edge] == it->vertex) ret = g->edges[it->edge + g->nedges];
     333                 :          0 :         else ret = g->edges[it->edge];
     334                 :          0 :         it->edge = g->next[it->edge];
     335                 :          0 :         return ret;
     336                 :            : }
     337                 :            :         
     338                 :            : 

Generated by: LCOV version 1.14