int main() { srandom(time(0)); graph_t a; vector_int v1; vector_int_init_value_end(&v1, -1, 1,5, 2,5, 1,2, 2,1, 0,3, 0,2, 3,4, 3,6, 4,6, 6,4, -1,7, -1); new_graph(&a, &v1, 0, GRAPH_DIRECTED); print_graph_vectors(&a, stdout); printf("ec=%d\t",graph_edges_count(&a)); printf("vc=%d\n",graph_vertices_count(&a)); int vc = graph_vertices_count(&a); vector_int mem; vector_int_init(&mem, vc); vector_int_fill(&mem, -1); vector_int cs; vector_int_init(&cs, 0); int cc; graph_clusters_strong(&a,&mem,&cs,&cc); printf("mem:"); print_vector_int(&mem, stdout); printf("<<<combine vertices\n"); graph_t b; graph_combine_vertices(&a, &mem, &b); print_graph_vectors(&b, stdout); printf("ec=%d\t",graph_edges_count(&b)); printf("vc=%d\n",graph_vertices_count(&b)); double re; printf(">>>>randomly attack\n"); re = graph_fault_propagation(&b, 0.3, 0.2, GRAPH_ATK_RANDOM); printf("random re=%f\n",re); printf(">>>>outgoing based attack\n"); re = graph_fault_propagation(&b, 0.3, 0.2, GRAPH_ATK_OUTGOING); printf("outgoing re=%f\n",re); printf(">>>>incoming based attack\n"); re = graph_fault_propagation(&b, 0.3, 0.2, GRAPH_ATK_INCOMING); printf("incoming re=%f\n",re); vector_int inf; vector_int_init(&inf, 0); int cascading_nodes_count = graph_cascading_nodes_count(&b, &inf, 0.3, 0.2, GRAPH_ATK_RANDOM); assert(cascading_nodes_count == vector_int_sum(&inf)); vector_int_destroy(&inf); vector_int_destroy(&mem); vector_int_destroy(&cs); vector_int_destroy(&v1); graph_destroy(&b); graph_destroy(&a); return 0; }
/* * graph_combine_vertices */ int graph_combine_vertices(const graph_t *graph, const vector_int *membership, graph_t *res) { int ec = graph_edges_count(graph); vector_int new_edges; vector_int_init(&new_edges, 2 * ec); int from, to, nef, net; int eid = 0; for (int i = 0; i < ec; i++) { graph_edge(graph, i, &from, &to); nef = VECTOR(*membership)[from]; net = VECTOR(*membership)[to]; if (nef == net || nef < 0 || net < 0) continue; VECTOR(new_edges)[2*eid+0] = nef; VECTOR(new_edges)[2*eid+1] = net; eid++; } eid--; vector_int_resize(&new_edges, 2 * eid); new_graph(res, &new_edges, 0, graph->directed); graph_remove_multi_edges(res); return 0; }
/* * graph_remove_multi_edges */ void graph_remove_multi_edges(graph_t *graph) { int ec = graph_edges_count(graph); int vc = graph_vertices_count(graph); /* mark the edges needed to be removed */ int *mark = Calloc(ec, int); assert(0 != mark); int to,_to,e; vector_int eids; vector_int_init(&eids, 0); for (int i = 0; i < vc; i++) { _graph_edges_to(graph, &eids, i); for (int j = 1; j < vector_int_size(&eids); j++) { _to = GRAPH_TO(graph, VECTOR(eids)[j-1]); to = GRAPH_TO(graph, VECTOR(eids)[j]); e = VECTOR(eids)[j]; if (_to == to) mark[e] = 1; } } vector_int_clear(&eids); for (int i = 0; i < ec; i++) { if (mark[i] != 0) vector_int_push_back(&eids, i); } graph_del_edges(graph, graph_ess_vector(&eids)); vector_int_destroy(&eids); Free(mark); }
/* * graph_has_multiple */ int graph_has_multiple(const graph_t *graph) { int vc = graph_vertices_count(graph); int ec = graph_edges_count(graph); int dflag = graph_is_directed(graph); if (vc == 0 || ec == 0) return 0; vector_int neis; vector_int_init(&neis, 0); int found = 0, n; for (int i = 0; i < vc && !found; i++) { graph_neighbors(graph, &neis, i, GRAPH_OUT); n = vector_int_size(&neis); for (int j = 1; j < n; j++) { if (VECTOR(neis)[j-1] == VECTOR(neis)[j]) { if (dflag) /* Directed, so this is a real multiple edge */ return 1; else if (VECTOR(neis)[j-1] != i) /* Undirected, but not a loop edge */ return 1; else if (j < n-1 && VECTOR(neis)[j] == VECTOR(neis)[j+1]) /* Undirected, loop edge, multiple times */ return 1; } } } return 0; }
unsigned int graph_connected_components(graph_t g) { unsigned int classes_count = 0, n, m, left, right; union_find_t uf; edge_t *edges; n = graph_vertices_count(g); m = graph_edges_count(g); uf = union_find_create(n); edges = graph_edges(g); for (unsigned int i = 0; i < m; i++) { left = vertex_label(edge_left_vertex(edges[i])); right = vertex_label(edge_right_vertex(edges[i])); left = union_find_find(uf, left); right = union_find_find(uf, right); if (!union_find_connected(uf, left, right)) { union_find_union(uf, left, right); } edges[i] = edge_destroy(edges[i]); } free(edges); classes_count = union_find_count(uf); uf = union_find_destroy(uf); return (classes_count); }
/* * graph_del_edges - delete the edges */ int graph_del_edges(graph_t *graph, graph_es_t eids) { int ec = graph_edges_count(graph); int vc = graph_vertices_count(graph); /* mark the edges needed to be removed */ int *mark = Calloc(ec, int); assert(0 != mark); graph_eit_t eit; graph_eit_create(graph, eids, &eit); int edges_to_remove = 0; for (GRAPH_EIT_RESET(eit); !GRAPH_EIT_END(eit); GRAPH_EIT_NEXT(eit)) { int e = GRAPH_EIT_GET(eit); if (0 == mark[e]) { edges_to_remove++; mark[e]++; } } int remaining_edges = ec - edges_to_remove; /* We don't need the iterator any more */ graph_eit_destroy(&eit); /* We build some new vectors to store the remaining edges */ vector_int newfrom, newto, newoi, newii; vector_int_init(&newfrom, remaining_edges); vector_int_init(&newto, remaining_edges); vector_int_init(&newoi, remaining_edges); vector_int_init(&newii, remaining_edges); /* Actually remove the edges, move from pos i to pos j in newfrom/newto */ for (int i = 0, j = 0; j < remaining_edges; i++) { if (0 == mark[i]) { VECTOR(newfrom)[j] = VECTOR(graph->from)[i]; VECTOR(newto)[j] = VECTOR(graph->to)[i]; j++; } } vector_int_order_inc2(&newfrom, &newto, &newoi, graph->n); vector_int_order_inc2(&newto, &newfrom, &newii, graph->n); /* attributes */ /* os & is */ vector_int_scan_tie(&(graph->os), &newfrom, &newoi, graph->n); vector_int_scan_tie(&(graph->is), &newto, &newii, graph->n); /* Ok, we've all memory needed, free the old structure */ vector_int_destroy(&graph->from); vector_int_destroy(&graph->to); vector_int_destroy(&graph->oi); vector_int_destroy(&graph->ii); graph->from = newfrom; graph->to = newto; graph->oi = newoi; graph->ii = newii; Free(mark); return 0; }
unsigned int mst_total_weight(graph_t mst) { unsigned int result = 0, num_edges; edge_t *edges; num_edges = graph_edges_count(mst); edges = graph_edges(mst); for (unsigned int i = 0; i < num_edges; i++) { if (edge_is_primary(edges[i])) { result += edge_weight(edges[i]); } edges[i] = edge_destroy(edges[i]); } free(edges); return result; }
/* * graph_add_vertices * * @graph: target * @nv: number of vertices * @attr: the attributes of the new vertices */ int graph_add_vertices(graph_t *graph, int nv, void *attr) { assert(0 <= nv); vector_int_resize(&(graph->os), graph->n + nv + 1); vector_int_resize(&(graph->is), graph->n + nv + 1); int ec = graph_edges_count(graph); for (int i = graph->n + 1; i < graph->n + nv + 1; i++) { VECTOR(graph->os)[i] = ec; VECTOR(graph->is)[i] = ec; } graph->n += nv; /* attribute -mark-gyc-*/ return 0; }
/* * graph_add_edges */ int graph_add_edges(graph_t *graph, vector_int *edges, void *attr) { assert(0 == vector_int_size(edges) % 2); assert(1 == vector_int_isininterval(edges, 0, graph_vertices_count(graph)-1)); int ec = graph_edges_count(graph); int ec_to_add = vector_int_size(edges) / 2; /* from & to */ vector_int_reserve(&(graph->from), ec + ec_to_add); vector_int_reserve(&(graph->to), ec + ec_to_add); int i = 0; int directed = graph->directed; while (i < ec_to_add * 2) { if (directed || VECTOR(*edges)[i] > VECTOR(*edges)[i+1]) { vector_int_push_back(&(graph->from), VECTOR(*edges)[i++]); vector_int_push_back(&(graph->to), VECTOR(*edges)[i++]); } else { vector_int_push_back(&(graph->to), VECTOR(*edges)[i++]); vector_int_push_back(&(graph->from), VECTOR(*edges)[i++]); } } /* oi & ii */ vector_int newoi, newii; vector_int_init(&newoi, ec + ec_to_add); vector_int_init(&newii, ec + ec_to_add); vector_int_order_inc2(&(graph->from), &(graph->to), &newoi, graph->n); vector_int_order_inc2(&(graph->to), &(graph->from), &newii, graph->n); /* attributes */ /* os & is */ vector_int_scan_tie(&(graph->os), &(graph->from), &newoi, graph->n); vector_int_scan_tie(&(graph->is), &(graph->to), &newii, graph->n); /* everything went fine */ vector_int_destroy(&(graph->oi)); vector_int_destroy(&(graph->ii)); graph->oi = newoi; graph->ii = newii; return 0; }
graph_t kruskal(graph_t graph) { graph_t result = graph_empty(graph_vertices_count(graph)); unsigned int L, R, num_edges = graph_edges_count(graph); vertex_t l = NULL, r = NULL; pqueue_t Q = pqueue_empty(num_edges); union_find_t C = union_find_create(graph_vertices_count(graph)); edge_t E = NULL, *edges = graph_edges(graph); for (unsigned int i = 0; i < num_edges; i++) { pqueue_enqueue(Q, edges[i]); } free(edges); edges = NULL; while (!pqueue_is_empty(Q) && union_find_count(C) > 1) { E = edge_copy(pqueue_fst(Q)); l = edge_left_vertex(E); r = edge_right_vertex(E); L = union_find_find(C, vertex_label(l)); R = union_find_find(C, vertex_label(r)); if (L != R) { union_find_union(C, L, R); E = edge_set_primary(E, true); } else { E = edge_set_primary(E, false); } result = graph_add_edge(result, E); pqueue_dequeue(Q); } while (!pqueue_is_empty(Q)) { E = edge_copy(pqueue_fst(Q)); pqueue_dequeue(Q); E = edge_set_primary(E, false); result = graph_add_edge(result, E); } Q = pqueue_destroy(Q); C = union_find_destroy(C); return result; }
unsigned int mst_total_weight(graph_t mst) { /* Returns the sum of the weights of all the primary * edges of the given graph. */ unsigned int sum, m; edge_t *edges; edges = graph_edges(mst); sum = 0; m = graph_edges_count(mst); for (unsigned int i = 0; i < m; i++) { if (edge_is_primary(edges[i])) { sum += edge_weight(edges[i]); } edges[i] = edge_destroy(edges[i]); } free(edges); return (sum); }
int graph_subgraph(const graph_t *graph, graph_t *subgraph, graph_vs_t vids) { int vc = graph_vertices_count(graph); int ec = graph_edges_count(graph); vector_int vss; vector_int_init(&vss, vc); vector_int_fill(&vss, -1); int i,j,u,v; graph_vit_t vit; graph_vit_create(graph, vids, &vit); int nvc = GRAPH_VIT_SIZE(vit); for (GRAPH_VIT_RESET(vit), i=0; !GRAPH_VIT_END(vit); GRAPH_VIT_NEXT(vit), i++) { int vid = GRAPH_VIT_GET(vit); VECTOR(vss)[vid] = i; } graph_vit_destroy(&vit); int nec = 0; vector_int new_edges; vector_int_init(&new_edges, 2 * ec); for (int eid = 0; eid < ec; eid++) { graph_edge(graph, eid, &i, &j); u = VECTOR(vss)[i]; v = VECTOR(vss)[j]; if (-1 == u || -1 == v) continue; VECTOR(new_edges)[2*nec+0] = u; VECTOR(new_edges)[2*nec+1] = v; nec++; } vector_int_resize(&new_edges, 2 * nec); new_graph(subgraph, &new_edges, nvc, graph_is_directed(graph)); vector_int_destroy(&new_edges); vector_int_destroy(&vss); return 0; }
int main() { int vc = 9334; int ec = 26841; vector_int edges; vector_int_init(&edges, ec * 2); srand((int)time(0)); int src = -1, dst = -1; for (int i = 0, ei = 0; i < ec; i++,ei+=2) { src = (int)(rand() % vc); dst = (int)(rand() % vc); while (src == dst) { src = (int)(rand() % vc); dst = (int)(rand() % vc); } VECTOR(edges)[ei] = src; VECTOR(edges)[ei+1] = dst; } graph_t a; new_graph(&a, &edges, vc, 1); assert(vc == graph_vertices_count(&a)); assert(ec == graph_edges_count(&a)); printf("reciprocal = %f \n", graph_reciprocal(&a)); int min, max, sum; double ave; graph_degree_minmax_avesum(&a, &min, &max, &ave, &sum, GRAPH_OUT, GRAPH_NO_LOOPS); printf("minout=%d\nmaxout=%d\n\n",min,max); printf("sum=%d\nave=%f\n\n\n",sum,ave); graph_degree_minmax_avesum(&a, &min, &max, &ave, &sum, GRAPH_IN, GRAPH_NO_LOOPS); printf("minin=%d\nmaxin=%d\n\n\n",min,max); printf("sum=%d\nave=%f\n\n\n",sum,ave); FILE * f = fopen("a.sif","w"); print_edge(&edges, f); fclose(f); //print_graph_ct(&a, GRAPH_OUT, stdout); }
bool graph_has_cycle(graph_t g) { bool has_secondary_edge; edge_t *edges; unsigned int i, m; edges = graph_edges(g); has_secondary_edge = false; i = 0; m = graph_edges_count(g); while (!has_secondary_edge && i < m) { has_secondary_edge = !edge_is_primary(edges[i]); edges[i] = edge_destroy(edges[i]); i += 1; } while (i < m) { edges[i] = edge_destroy(edges[i]); i += 1; } free(edges); return (has_secondary_edge); }
graph_t kruskal(graph_t graph) { /* Computes a MST of the given graph. * * This function returns a copy of the input graph in which * only the edges of the MST are marked as primary. The * remaining edges are marked as secondary. * * The input graph does not change. * */ graph_t mst; union_find_t uf; pqueue_t pq; edge_t *edges; edge_t e; unsigned int left, right, n, m; /* Inicialización */ n = graph_vertices_count(graph); m = graph_edges_count(graph); mst = graph_empty(n); uf = union_find_create(n); pq = pqueue_empty(m); /* Llenar `pq` */ edges = graph_edges(graph); for (unsigned int j = 0; j < m; j++) { pqueue_enqueue(pq, edges[j]); } /* Ahora las aristas están en `pq` */ free(edges); edges = NULL; /* Principal */ while (!pqueue_is_empty(pq) && union_find_count(uf) > 1) { e = edge_copy(pqueue_fst(pq)); left = vertex_label(edge_left_vertex(e)); right = vertex_label(edge_right_vertex(e)); left = union_find_find(uf, left); right = union_find_find(uf, right); if (!union_find_connected(uf, left, right)) { e = edge_set_primary(e, true); union_find_union(uf, left, right); } else { e = edge_set_primary(e, false); } mst = graph_add_edge(mst, e); pqueue_dequeue(pq); } /* Agregar aristas restantes como secundarias */ while (!pqueue_is_empty(pq)) { e = edge_copy(pqueue_fst(pq)); e = edge_set_primary(e, false); mst = graph_add_edge(mst, e); pqueue_dequeue(pq); } /* Destroy */ uf = union_find_destroy(uf); pq = pqueue_destroy(pq); return (mst); }