int main() { igraph_t g; igraph_integer_t result; igraph_vector_t edges, res; igraph_vs_t vids; long i, n; igraph_tree(&g, 10, 3, IGRAPH_TREE_OUT); igraph_rewire(&g, 1000, IGRAPH_REWIRING_SIMPLE); n=igraph_vcount(&g); igraph_vector_init(&res, 0); igraph_degree(&g, &res, igraph_vss_all(), IGRAPH_IN, 0); for (i=0; i<n; i++) printf("%ld ", (long)igraph_vector_e(&res, i)); printf("\n"); igraph_degree(&g, &res, igraph_vss_all(), IGRAPH_OUT, 0); for (i=0; i<n; i++) printf("%ld ", (long)igraph_vector_e(&res, i)); printf("\n"); igraph_destroy(&g); igraph_vector_destroy(&res); return 0; }
int igraph_similarity_inverse_log_weighted(const igraph_t *graph, igraph_matrix_t *res, const igraph_vs_t vids, igraph_neimode_t mode) { igraph_vector_t weights; igraph_neimode_t mode0; long int i, no_of_nodes; switch (mode) { case IGRAPH_OUT: mode0 = IGRAPH_IN; break; case IGRAPH_IN: mode0 = IGRAPH_OUT; break; default: mode0 = IGRAPH_ALL; } no_of_nodes = igraph_vcount(graph); IGRAPH_VECTOR_INIT_FINALLY(&weights, no_of_nodes); IGRAPH_CHECK(igraph_degree(graph, &weights, igraph_vss_all(), mode0, 1)); for (i=0; i < no_of_nodes; i++) { if (VECTOR(weights)[i] > 1) VECTOR(weights)[i] = 1.0 / log(VECTOR(weights)[i]); } IGRAPH_CHECK(igraph_cocitation_real(graph, res, vids, mode0, &weights)); igraph_vector_destroy(&weights); IGRAPH_FINALLY_CLEAN(1); return 0; }
igraph_bool_t check_laplacian(igraph_t* graph, igraph_matrix_t* matrix, igraph_vector_t* w) { igraph_vector_t vec, res; long int i, j; igraph_vector_init(&vec, 0); igraph_vector_init(&res, igraph_vcount(graph)); if (w) igraph_strength(graph, &vec, igraph_vss_all(), IGRAPH_OUT, IGRAPH_NO_LOOPS, w); else igraph_degree(graph, &vec, igraph_vss_all(), IGRAPH_OUT, IGRAPH_NO_LOOPS); for (i = 0; i < igraph_vcount(graph); i++) { VECTOR(vec)[i] = sqrt(VECTOR(vec)[i]); } for (i = 0; i < igraph_vcount(graph); i++) { for (j = 0; j < igraph_vcount(graph); j++) { VECTOR(res)[i] += MATRIX(*matrix, i, j) * VECTOR(vec)[j]; } } if (igraph_vector_min(&res) > 1e-7) { printf("Invalid Laplacian matrix:\n"); igraph_matrix_print(matrix); return 0; } igraph_vector_destroy(&vec); igraph_vector_destroy(&res); return 1; }
int igraph_local_scan_0_them(const igraph_t *us, const igraph_t *them, igraph_vector_t *res, const igraph_vector_t *weights_them, igraph_neimode_t mode) { igraph_t is; if (igraph_vcount(us) != igraph_vcount(them)) { IGRAPH_ERROR("Number of vertices don't match in scan-0", IGRAPH_EINVAL); } if (igraph_is_directed(us) != igraph_is_directed(them)) { IGRAPH_ERROR("Directedness don't match in scan-0", IGRAPH_EINVAL); } if (weights_them) { return igraph_i_local_scan_0_them_w(us, them, res, weights_them, mode); } igraph_intersection(&is, us, them, /*edgemap1=*/ 0, /*edgemap2=*/ 0); IGRAPH_FINALLY(igraph_destroy, &is); igraph_degree(&is, res, igraph_vss_all(), mode, IGRAPH_LOOPS); igraph_destroy(&is); IGRAPH_FINALLY_CLEAN(1); return 0; }
static PyObject *ignp_fun_degreeList( PyObject *self, PyObject *args ) { long int i; igraph_t *g; PyArrayObject *py_deg; PyObject *x_obj; igraph_vector_t v; igraph_vector_init(&v, 0); PyObject* mem_addr_o; long int mem_addr; if (!PyArg_ParseTuple(args, "OO!", &x_obj, &PyArray_Type, &py_deg )) { return NULL; } mem_addr_o = PyObject_CallMethod(x_obj, "_raw_pointer", "()"); mem_addr = PyInt_AsLong(mem_addr_o); Py_DECREF(mem_addr_o); if (mem_addr == -1) { printf("PyInt to Long Failed"); return NULL; } g = (igraph_t*) mem_addr; igraph_degree(g, &v, igraph_vss_all(), IGRAPH_ALL, IGRAPH_NO_LOOPS); for (i = 0; i<igraph_vector_size(&v); i++) { deg(i) = VECTOR(v)[ i ]; } igraph_vector_destroy(&v); Py_RETURN_NONE; }
/* call-seq: * graph.degree(vs,mode,loops) -> Array * * Returns an Array of Integers specifying the degree of each of the * vertices specified in the vs Array. mode defines the type of the degree. * IGraph::OUT, out-degree, IGraph::IN, in-degree, IGraph::ALL, total degree * (sum of the in- and out-degree). This parameter is ignored for undirected * graphs. * * Example: * * g = IGraph.new([1,2,3,4],true) * g.is_directed? #returns true * */ VALUE cIGraph_degree(VALUE self, VALUE v, VALUE mode, VALUE loops){ igraph_t *graph; igraph_vs_t vids; igraph_vector_t vidv; igraph_neimode_t pmode = NUM2INT(mode); igraph_bool_t loop_mode = loops ? 1 : 0; igraph_vector_t res; int i; VALUE degree_r = rb_ary_new(); //vector to hold the results of the degree calculations igraph_vector_init_int(&res,0); Data_Get_Struct(self, igraph_t, graph); //Convert an array of vertices to a vector of vertex ids igraph_vector_init_int(&vidv,0); cIGraph_vertex_arr_to_id_vec(self,v,&vidv); //create vertex selector from the vecotr of ids igraph_vs_vector(&vids,&vidv); igraph_degree(graph,&res,vids,pmode,loop_mode); for(i=0;i<igraph_vector_size(&res);i++){ rb_ary_push(degree_r,INT2NUM(VECTOR(res)[i])); } igraph_vector_destroy(&vidv); igraph_vector_destroy(&res); igraph_vs_destroy(&vids); return degree_r; }
igraph_integer_t all_degrees(igraph_t *graph, igraph_vector_t *degrees) { igraph_vs_t vs; igraph_vs_all(&vs); igraph_degree(graph, degrees, vs, IGRAPH_ALL, IGRAPH_LOOPS); igraph_vs_destroy(&vs); }
int igraph_local_scan_0(const igraph_t *graph, igraph_vector_t *res, const igraph_vector_t *weights, igraph_neimode_t mode) { if (weights) { igraph_strength(graph, res, igraph_vss_all(), mode, /*loops=*/ 1, weights); } else { igraph_degree(graph, res, igraph_vss_all(), mode, /*loops=*/ 1); } return 0; }
static double sumDegree(const igraph_t *g) { int i; double result = 0.0; igraph_vector_t v; igraph_vector_init(&v, 0); igraph_degree(g, &v, igraph_vss_all(), IGRAPH_ALL, IGRAPH_NO_LOOPS); for (i = 0; i<igraph_vector_size(&v); i++) { result += VECTOR(v)[ (long int)i ]; } igraph_vector_destroy(&v); return result; }
std::vector<int> Graph::degrees() { igraph_vector_t results; igraph_vs_t allnds; std::vector<int> degs; igraph_vs_all(&allnds); igraph_vector_init(&results, size); igraph_vector_null(&results); igraph_degree(graph, &results, allnds, IGRAPH_ALL, IGRAPH_NO_LOOPS); degs.insert(degs.begin(), VECTOR(results), VECTOR(results)+size); igraph_vector_destroy(&results); igraph_vs_destroy(&allnds); return degs; }
igraph_integer_t d(igraph_t *graph, igraph_integer_t v) { igraph_vector_t res; igraph_vs_t vs; igraph_vector_init(&res, 1); igraph_vs_1(&vs, v); igraph_degree(graph, &res, vs, IGRAPH_ALL, IGRAPH_LOOPS); igraph_integer_t d_v = VECTOR(res)[0]; igraph_vs_destroy(&vs); igraph_vector_destroy(&res); return d_v; }
int ggen_transform_delete(igraph_t *g, enum ggen_transform_t t) { igraph_vector_t vertices; igraph_vector_t degrees; unsigned int i,vcount,ssize; int err; if(g == NULL) return 1; vcount = igraph_vcount(g); err = igraph_vector_init(&vertices,vcount); if(err) return 1; err = igraph_vector_init(°rees,vcount); if(err) goto error_id; /* find degree of each vertex, igraph_in if we need to identify sources. */ err = igraph_degree(g,°rees,igraph_vss_all(), (t==GGEN_TRANSFORM_SOURCE)?IGRAPH_IN:IGRAPH_OUT,0); if(err) goto error; /* only sources or sinks are of interest */ ssize = 0; for(i = 0; i < vcount; i++) if(VECTOR(degrees)[i] == 0) VECTOR(vertices)[ssize++] = i; /* delete all identified vertices */ if(ssize > 0) { /* we should resize the array to avoid strange behaviors */ err = igraph_vector_resize(&vertices,ssize); if(err) goto error; err = igraph_delete_vertices(g,igraph_vss_vector(&vertices)); if(err) goto error; } error: igraph_vector_destroy(°rees); error_id: igraph_vector_destroy(&vertices); return err; }
int igraph_i_local_scan_1_sumweights(const igraph_t *graph, igraph_vector_t *res, const igraph_vector_t *weights) { long int no_of_nodes=igraph_vcount(graph); long int node, i, j, nn; igraph_inclist_t allinc; igraph_vector_int_t *neis1, *neis2; long int neilen1, neilen2; long int *neis; long int maxdegree; igraph_vector_int_t order; igraph_vector_int_t rank; igraph_vector_t degree, *edge1=°ree; /* reuse degree as edge1 */ if (igraph_vector_size(weights) != igraph_ecount(graph)) { IGRAPH_ERROR("Invalid weight vector length", IGRAPH_EINVAL); } igraph_vector_int_init(&order, no_of_nodes); IGRAPH_FINALLY(igraph_vector_int_destroy, &order); IGRAPH_VECTOR_INIT_FINALLY(°ree, no_of_nodes); IGRAPH_CHECK(igraph_degree(graph, °ree, igraph_vss_all(), IGRAPH_ALL, IGRAPH_LOOPS)); maxdegree=(long int) igraph_vector_max(°ree)+1; igraph_vector_order1_int(°ree, &order, maxdegree); igraph_vector_int_init(&rank, no_of_nodes); IGRAPH_FINALLY(igraph_vector_int_destroy, &rank); for (i=0; i<no_of_nodes; i++) { VECTOR(rank)[ VECTOR(order)[i] ] = no_of_nodes-i-1; } IGRAPH_CHECK(igraph_inclist_init(graph, &allinc, IGRAPH_ALL)); IGRAPH_FINALLY(igraph_inclist_destroy, &allinc); IGRAPH_CHECK(igraph_i_trans4_il_simplify(graph, &allinc, &rank)); neis=igraph_Calloc(no_of_nodes, long int); if (neis==0) { IGRAPH_ERROR("undirected local transitivity failed", IGRAPH_ENOMEM); } IGRAPH_FINALLY(igraph_free, neis); IGRAPH_CHECK(igraph_strength(graph, res, igraph_vss_all(), IGRAPH_ALL, IGRAPH_LOOPS, weights)); for (nn=no_of_nodes-1; nn>=0; nn--) { node=VECTOR(order)[nn]; IGRAPH_ALLOW_INTERRUPTION(); neis1=igraph_inclist_get(&allinc, node); neilen1=igraph_vector_int_size(neis1); /* Mark the neighbors of the node */ for (i=0; i<neilen1; i++) { int edge = VECTOR(*neis1)[i]; int nei = IGRAPH_OTHER(graph, edge, node); VECTOR(*edge1)[nei] = VECTOR(*weights)[edge]; neis[nei] = node+1; } for (i=0; i<neilen1; i++) { long int edge=VECTOR(*neis1)[i]; long int nei=IGRAPH_OTHER(graph, edge, node); igraph_real_t w=VECTOR(*weights)[edge]; neis2=igraph_inclist_get(&allinc, nei); neilen2=igraph_vector_int_size(neis2); for (j=0; j<neilen2; j++) { long int edge2=VECTOR(*neis2)[j]; long int nei2=IGRAPH_OTHER(graph, edge2, nei); igraph_real_t w2=VECTOR(*weights)[edge2]; if (neis[nei2] == node+1) { VECTOR(*res)[node] += w2; VECTOR(*res)[nei2] += w; VECTOR(*res)[nei] += VECTOR(*edge1)[nei2]; } } } } igraph_free(neis); igraph_inclist_destroy(&allinc); igraph_vector_int_destroy(&rank); igraph_vector_destroy(°ree); igraph_vector_int_destroy(&order); IGRAPH_FINALLY_CLEAN(5); return 0; }
int main() { igraph_t g; igraph_vector_t v, v2; int i, ret; igraph_barabasi_game(&g, 10, 2, 0, 0, 1); if (igraph_ecount(&g) != 18) { return 1; } if (igraph_vcount(&g) != 10) { return 2; } if (!igraph_is_directed(&g)) { return 3; } igraph_vector_init(&v, 0); igraph_get_edgelist(&g, &v, 0); for (i=0; i<igraph_ecount(&g); i++) { if (VECTOR(v)[2*i] <= VECTOR(v)[2*i+1]) { return 4; } } igraph_destroy(&g); /* out degree sequence */ igraph_vector_resize(&v, 10); VECTOR(v)[0]=0; VECTOR(v)[1]=1; VECTOR(v)[2]=3; VECTOR(v)[3]=3; VECTOR(v)[4]=4; VECTOR(v)[5]=5; VECTOR(v)[6]=6; VECTOR(v)[7]=7; VECTOR(v)[8]=8; VECTOR(v)[9]=9; igraph_barabasi_game(&g, 10, 0, &v, 0, 1); if (igraph_ecount(&g) != igraph_vector_sum(&v)) { return 5; } igraph_vector_init(&v2, 0); igraph_degree(&g, &v2, igraph_vss_all(), IGRAPH_OUT, 1); for (i=0; i<igraph_vcount(&g); i++) { if (VECTOR(v)[i] != VECTOR(v2)[i]) { return 6; } } igraph_vector_destroy(&v); igraph_vector_destroy(&v2); igraph_destroy(&g); /* outpref, we cannot really test this quantitatively, would need to set random seed */ igraph_barabasi_game(&g, 10, 2, 0, 1, 1); igraph_vector_init(&v, 0); igraph_get_edgelist(&g, &v, 0); for (i=0; i<igraph_ecount(&g); i++) { if (VECTOR(v)[2*i] <= VECTOR(v)[2*i+1]) { return 7; } } if (!igraph_is_directed(&g)) { return 8; } igraph_vector_destroy(&v); igraph_destroy(&g); /* Error tests */ igraph_set_error_handler(igraph_error_handler_ignore); ret=igraph_barabasi_game(&g, -10, 1, 0, 0, 0); if (ret != IGRAPH_EINVAL) { return 9; } ret=igraph_barabasi_game(&g, 10, -2, 0, 0, 0); if (ret != IGRAPH_EINVAL) { return 10; } igraph_vector_init(&v, 9); ret=igraph_barabasi_game(&g, 10, 0, &v, 0, 0); if (ret != IGRAPH_EINVAL) { return 11; } igraph_vector_destroy(&v); return 0; }
void Graph::degree(Vector* result, const VertexSelector& vids, NeighborMode mode, bool loops) const { assert(m_pGraph); IGRAPH_TRY(igraph_degree(m_pGraph, result->c_vector(), *vids.c_vs(), mode, loops)); }
int igraph_layout_gem(const igraph_t *graph, igraph_matrix_t *res, igraph_bool_t use_seed, igraph_integer_t maxiter, igraph_real_t temp_max, igraph_real_t temp_min, igraph_real_t temp_init) { igraph_integer_t no_nodes = igraph_vcount(graph); igraph_vector_int_t perm; igraph_vector_float_t impulse_x, impulse_y, temp, skew_gauge; igraph_integer_t i; float temp_global; igraph_integer_t perm_pointer = 0; float barycenter_x = 0.0, barycenter_y = 0.0; igraph_vector_t phi; igraph_vector_t neis; const float elen_des2 = 128 * 128; const float gamma = 1/16.0; const float alpha_o = M_PI; const float alpha_r = M_PI / 3.0; const float sigma_o = 1.0 / 3.0; const float sigma_r = 1.0 / 2.0 / no_nodes; if (maxiter < 0) { IGRAPH_ERROR("Number of iterations must be non-negative in GEM layout", IGRAPH_EINVAL); } if (use_seed && (igraph_matrix_nrow(res) != no_nodes || igraph_matrix_ncol(res) != 2)) { IGRAPH_ERROR("Invalid start position matrix size in GEM layout", IGRAPH_EINVAL); } if (temp_max <= 0) { IGRAPH_ERROR("Maximum temperature should be positive in GEM layout", IGRAPH_EINVAL); } if (temp_min <= 0) { IGRAPH_ERROR("Minimum temperature should be positive in GEM layout", IGRAPH_EINVAL); } if (temp_init <= 0) { IGRAPH_ERROR("Initial temperature should be positive in GEM layout", IGRAPH_EINVAL); } if (temp_max < temp_init || temp_init < temp_min) { IGRAPH_ERROR("Minimum <= Initial <= Maximum temperature is required " "in GEM layout", IGRAPH_EINVAL); } if (no_nodes == 0) { return 0; } IGRAPH_CHECK(igraph_vector_float_init(&impulse_x, no_nodes)); IGRAPH_FINALLY(igraph_vector_float_destroy, &impulse_x); IGRAPH_CHECK(igraph_vector_float_init(&impulse_y, no_nodes)); IGRAPH_FINALLY(igraph_vector_float_destroy, &impulse_y); IGRAPH_CHECK(igraph_vector_float_init(&temp, no_nodes)); IGRAPH_FINALLY(igraph_vector_float_destroy, &temp); IGRAPH_CHECK(igraph_vector_float_init(&skew_gauge, no_nodes)); IGRAPH_FINALLY(igraph_vector_float_destroy, &skew_gauge); IGRAPH_CHECK(igraph_vector_int_init_seq(&perm, 0, no_nodes-1)); IGRAPH_FINALLY(igraph_vector_int_destroy, &perm); IGRAPH_VECTOR_INIT_FINALLY(&phi, no_nodes); IGRAPH_VECTOR_INIT_FINALLY(&neis, 10); RNG_BEGIN(); /* Initialization */ igraph_degree(graph, &phi, igraph_vss_all(), IGRAPH_ALL, IGRAPH_LOOPS); if (!use_seed) { const igraph_real_t width_half=no_nodes*100, height_half=width_half; IGRAPH_CHECK(igraph_matrix_resize(res, no_nodes, 2)); for (i=0; i<no_nodes; i++) { MATRIX(*res, i, 0) = RNG_UNIF(-width_half, width_half); MATRIX(*res, i, 1) = RNG_UNIF(-height_half, height_half); barycenter_x += MATRIX(*res, i, 0); barycenter_y += MATRIX(*res, i, 1); VECTOR(phi)[i] *= (VECTOR(phi)[i] / 2.0 + 1.0); } } else { for (i=0; i<no_nodes; i++) { barycenter_x += MATRIX(*res, i, 0); barycenter_y += MATRIX(*res, i, 1); VECTOR(phi)[i] *= (VECTOR(phi)[i] / 2.0 + 1.0); } } igraph_vector_float_fill(&temp, temp_init); temp_global = temp_init * no_nodes; while (temp_global > temp_min * no_nodes && maxiter > 0) { /* choose a vertex v to update */ igraph_integer_t u, v, nlen, j; float px, py, pvx, pvy; if (!perm_pointer) { igraph_vector_int_shuffle(&perm); perm_pointer=no_nodes-1; } v=VECTOR(perm)[perm_pointer--]; /* compute v's impulse */ px = (barycenter_x/no_nodes - MATRIX(*res, v, 0)) * gamma * VECTOR(phi)[v]; py = (barycenter_y/no_nodes - MATRIX(*res, v, 1)) * gamma * VECTOR(phi)[v]; px += RNG_UNIF(-32.0, 32.0); py += RNG_UNIF(-32.0, 32.0); for (u = 0; u < no_nodes; u++) { float dx, dy, dist2; if (u == v) { continue; } dx=MATRIX(*res, v, 0) - MATRIX(*res, u, 0); dy=MATRIX(*res, v, 1) - MATRIX(*res, u, 1); dist2=dx * dx + dy * dy; if (dist2 != 0) { px += dx * elen_des2 / dist2; py += dy * elen_des2 / dist2; } } IGRAPH_CHECK(igraph_neighbors(graph, &neis, v, IGRAPH_ALL)); nlen=igraph_vector_size(&neis); for (j = 0; j < nlen; j++) { igraph_integer_t u=VECTOR(neis)[j]; float dx=MATRIX(*res, v, 0) - MATRIX(*res, u, 0); float dy=MATRIX(*res, v, 1) - MATRIX(*res, u, 1); float dist2= dx * dx + dy * dy; px -= dx * dist2 / (elen_des2 * VECTOR(phi)[v]); py -= dy * dist2 / (elen_des2 * VECTOR(phi)[v]); } /* update v's position and temperature */ if (px != 0 || py != 0) { float plen = sqrtf(px * px + py * py); px *= VECTOR(temp)[v] / plen; py *= VECTOR(temp)[v] / plen; MATRIX(*res, v, 0) += px; MATRIX(*res, v, 1) += py; barycenter_x += px; barycenter_y += py; } pvx=VECTOR(impulse_x)[v]; pvy=VECTOR(impulse_y)[v]; if (pvx != 0 || pvy != 0) { float beta = atan2f(pvy - py, pvx - px); float sin_beta = sinf(beta); float sign_sin_beta = (sin_beta > 0) ? 1 : ((sin_beta < 0) ? -1 : 0); float cos_beta = cosf(beta); float abs_cos_beta = fabsf(cos_beta); float old_temp=VECTOR(temp)[v]; if (sin(beta) >= sin(M_PI_2 + alpha_r / 2.0)) { VECTOR(skew_gauge)[v] += sigma_r * sign_sin_beta; } if (abs_cos_beta >= cosf(alpha_o / 2.0)) { VECTOR(temp)[v] *= sigma_o * cos_beta; } VECTOR(temp)[v] *= (1 - fabsf(VECTOR(skew_gauge)[v])); if (VECTOR(temp)[v] > temp_max) { VECTOR(temp)[v] = temp_max; } VECTOR(impulse_x)[v] = px; VECTOR(impulse_y)[v] = py; temp_global += VECTOR(temp)[v] - old_temp; } maxiter--; } /* while temp && iter */ RNG_END(); igraph_vector_destroy(&neis); igraph_vector_destroy(&phi); igraph_vector_int_destroy(&perm); igraph_vector_float_destroy(&skew_gauge); igraph_vector_float_destroy(&temp); igraph_vector_float_destroy(&impulse_y); igraph_vector_float_destroy(&impulse_x); IGRAPH_FINALLY_CLEAN(7); return 0; }
int ggen_transform_add(igraph_t *g, enum ggen_transform_t t) { igraph_vector_t vertices; igraph_vector_t degrees; igraph_vector_t edges; unsigned int i,vcount,ssize; int err; if(g == NULL) return 1; vcount = igraph_vcount(g); err = igraph_vector_init(&vertices,vcount); if(err) return 1; err = igraph_vector_init(°rees,vcount); if(err) goto error_id; /* find degree of each vertex, in if new source is wanted. */ err = igraph_degree(g,°rees,igraph_vss_all(), (t==GGEN_TRANSFORM_SOURCE)?IGRAPH_IN:IGRAPH_OUT,0); if(err) goto error; /* only sources or sinks are of interest */ ssize = 0; for(i = 0; i < vcount; i++) if(VECTOR(degrees)[i] == 0) VECTOR(vertices)[ssize++] = i; /* we have something to do */ if(ssize > 0) { err = igraph_add_vertices(g,1,NULL); if(err) goto error; err = igraph_vector_init(&edges,ssize*2); if(err) goto error; for(i = 0; i < ssize; i++) { if(t == GGEN_TRANSFORM_SOURCE) { VECTOR(edges)[2*i] = vcount; VECTOR(edges)[2*i+1] = VECTOR(vertices)[i]; } else { VECTOR(edges)[2*i] = VECTOR(vertices)[i]; VECTOR(edges)[2*i+1] = vcount; } } err = igraph_add_edges(g,&edges,NULL); igraph_vector_destroy(&edges); if(err) goto error; } error: igraph_vector_destroy(°rees); error_id: igraph_vector_destroy(&vertices); return err; }
/* Fan-in/ Fan-out method */ igraph_t *ggen_generate_fifo(gsl_rng *r, unsigned long n, unsigned long od, unsigned long id) { igraph_t *g = NULL; igraph_vector_t available_od; igraph_vector_t out_degrees; igraph_vector_t vertices; igraph_vector_t choice; igraph_vector_t edges; unsigned long max; unsigned long i,j,k; unsigned long vcount = 1; int err; ggen_error_start_stack(); if(r == NULL) GGEN_SET_ERRNO(GGEN_EINVAL); if(id == 0 || od == 0 || od > n || id > n) GGEN_SET_ERRNO(GGEN_EINVAL); g = malloc(sizeof(igraph_t)); GGEN_CHECK_ALLOC(g); GGEN_FINALLY3(free,g,1); GGEN_CHECK_IGRAPH(igraph_empty(g,1,1)); GGEN_FINALLY3(igraph_destroy,g,1); GGEN_CHECK_IGRAPH(igraph_vector_init(&available_od,n)); GGEN_FINALLY(igraph_vector_destroy,&available_od); GGEN_CHECK_IGRAPH(igraph_vector_init(&out_degrees,n)); GGEN_FINALLY(igraph_vector_destroy,&out_degrees); GGEN_CHECK_IGRAPH(igraph_vector_init(&vertices,n)); GGEN_FINALLY(igraph_vector_destroy,&vertices); GGEN_CHECK_IGRAPH(igraph_vector_init(&choice,n)); GGEN_FINALLY(igraph_vector_destroy,&choice); GGEN_CHECK_IGRAPH(igraph_vector_init(&edges,n*2)); GGEN_FINALLY(igraph_vector_destroy,&edges); while(vcount < n) { // never trigger errors as it doesn't allocate or free memory igraph_vector_resize(&available_od,vcount); igraph_vector_resize(&out_degrees,vcount); igraph_vector_resize(&vertices,vcount); // compute the available out degree of each vertex GGEN_CHECK_IGRAPH(igraph_degree(g,&out_degrees,igraph_vss_all(),IGRAPH_OUT,0)); // fill available with od and substract out_degrees igraph_vector_fill(&available_od,od); GGEN_CHECK_IGRAPH(igraph_vector_sub(&available_od,&out_degrees)); if(gsl_ran_bernoulli(r,0.5)) //Fan-out Step { // find max max = igraph_vector_max(&available_od); // register all vertices having max as outdegree j = 0; for (i = 0; i < vcount; i++) if(VECTOR(available_od)[i] == max) VECTOR(vertices)[j++] = i; // choose randomly a vertex among availables GGEN_CHECK_GSL_DO(i = gsl_rng_uniform_int(r,j)); // how many children ? GGEN_CHECK_GSL_DO(j = gsl_rng_uniform_int(r,max)); j = j+1; // create all new nodes and add edges GGEN_CHECK_IGRAPH(igraph_add_vertices(g,j,NULL)); // cannot fail igraph_vector_resize(&edges,j*2); for(k = 0; k < j; k++) { VECTOR(edges)[2*k] = i; VECTOR(edges)[2*k+1] = vcount + k; } vcount+=k; } else //Fan-In Step { // register all vertices having an available outdegree j = 0; for (i = 0; i < vcount; i++) if(VECTOR(available_od)[i] > 0) VECTOR(vertices)[j++] = i; // we can add at most id vertices max =( j > id)? id: j; // how many edges to add GGEN_CHECK_GSL_DO(k = gsl_rng_uniform_int(r,max)); k = k+1; // choose that many nodes and add edges from them to the new node // cannot fail either igraph_vector_resize(&choice,k); gsl_ran_choose(r,VECTOR(choice),k, VECTOR(vertices),j,sizeof(VECTOR(vertices)[0])); // add a vertex to the graph GGEN_CHECK_IGRAPH(igraph_add_vertices(g,1,NULL)); igraph_vector_resize(&edges,k*2); // be carefull, vcount is the last ID of vertices not vcount +1 for(i = 0; i < k; i++) { VECTOR(edges)[2*i] = VECTOR(choice)[i]; VECTOR(edges)[2*i+1] = vcount; } vcount++; } // in all cases, edges should be added GGEN_CHECK_IGRAPH(igraph_add_edges(g,&edges,NULL)); } ggen_error_clean(1); return g; ggen_error_label: return NULL; }
/** * \function igraph_community_fastgreedy * \brief Finding community structure by greedy optimization of modularity * * This function implements the fast greedy modularity optimization * algorithm for finding community structure, see * A Clauset, MEJ Newman, C Moore: Finding community structure in very * large networks, http://www.arxiv.org/abs/cond-mat/0408187 for the * details. * * </para><para> * Some improvements proposed in K Wakita, T Tsurumi: Finding community * structure in mega-scale social networks, * http://www.arxiv.org/abs/cs.CY/0702048v1 have also been implemented. * * \param graph The input graph. It must be a simple graph, i.e. a graph * without multiple and without loop edges. This is checked and an * error message is given for non-simple graphs. * \param weights Potentially a numeric vector containing edge * weights. Supply a null pointer here for unweighted graphs. The * weights are expected to be non-negative. * \param merges Pointer to an initialized matrix or NULL, the result of the * computation is stored here. The matrix has two columns and each * merge corresponds to one merge, the ids of the two merged * components are stored. The component ids are numbered from zero and * the first \c n components are the individual vertices, \c n is * the number of vertices in the graph. Component \c n is created * in the first merge, component \c n+1 in the second merge, etc. * The matrix will be resized as needed. If this argument is NULL * then it is ignored completely. * \param modularity Pointer to an initialized matrix or NULL pointer, * in the former case the modularity scores along the stages of the * computation are recorded here. The vector will be resized as * needed. * \return Error code. * * \sa \ref igraph_community_walktrap(), \ref * igraph_community_edge_betweenness() for other community detection * algorithms, \ref igraph_community_to_membership() to convert the * dendrogram to a membership vector. * * Time complexity: O(|E||V|log|V|) in the worst case, * O(|E|+|V|log^2|V|) typically, |V| is the number of vertices, |E| is * the number of edges. */ int igraph_community_fastgreedy(const igraph_t *graph, const igraph_vector_t *weights, igraph_matrix_t *merges, igraph_vector_t *modularity) { long int no_of_edges, no_of_nodes, no_of_joins, total_joins; long int i, j, k, n, m, from, to, dummy; igraph_integer_t ffrom, fto; igraph_eit_t edgeit; igraph_i_fastgreedy_commpair *pairs, *p1, *p2; igraph_i_fastgreedy_community_list communities; igraph_vector_t a; igraph_real_t q, maxq, *dq, weight_sum; igraph_bool_t simple; /*long int join_order[] = { 16,5, 5,6, 6,0, 4,0, 10,0, 26,29, 29,33, 23,33, 27,33, 25,24, 24,31, 12,3, 21,1, 30,8, 8,32, 9,2, 17,1, 11,0, 7,3, 3,2, 13,2, 1,2, 28,31, 31,33, 22,32, 18,32, 20,32, 32,33, 15,33, 14,33, 0,19, 19,2, -1,-1 };*/ /*long int join_order[] = { 43,42, 42,41, 44,41, 41,36, 35,36, 37,36, 36,29, 38,29, 34,29, 39,29, 33,29, 40,29, 32,29, 14,29, 30,29, 31,29, 6,18, 18,4, 23,4, 21,4, 19,4, 27,4, 20,4, 22,4, 26,4, 25,4, 24,4, 17,4, 0,13, 13,2, 1,2, 11,2, 8,2, 5,2, 3,2, 10,2, 9,2, 7,2, 2,28, 28,15, 12,15, 29,16, 4,15, -1,-1 };*/ no_of_nodes = igraph_vcount(graph); no_of_edges = igraph_ecount(graph); if (igraph_is_directed(graph)) { IGRAPH_ERROR("fast greedy community detection works for undirected graphs only", IGRAPH_UNIMPLEMENTED); } total_joins=no_of_nodes-1; if (weights != 0) { if (igraph_vector_size(weights) < igraph_ecount(graph)) IGRAPH_ERROR("fast greedy community detection: weight vector too short", IGRAPH_EINVAL); if (igraph_vector_any_smaller(weights, 0)) IGRAPH_ERROR("weights must be positive", IGRAPH_EINVAL); weight_sum = igraph_vector_sum(weights); } else weight_sum = no_of_edges; IGRAPH_CHECK(igraph_is_simple(graph, &simple)); if (!simple) { IGRAPH_ERROR("fast-greedy community finding works only on simple graphs", IGRAPH_EINVAL); } if (merges != 0) { IGRAPH_CHECK(igraph_matrix_resize(merges, total_joins, 2)); igraph_matrix_null(merges); } if (modularity != 0) { IGRAPH_CHECK(igraph_vector_resize(modularity, total_joins+1)); } /* Create degree vector */ IGRAPH_VECTOR_INIT_FINALLY(&a, no_of_nodes); if (weights) { debug("Calculating weighted degrees\n"); for (i=0; i < no_of_edges; i++) { VECTOR(a)[(long int)IGRAPH_FROM(graph, i)] += VECTOR(*weights)[i]; VECTOR(a)[(long int)IGRAPH_TO(graph, i)] += VECTOR(*weights)[i]; } } else { debug("Calculating degrees\n"); IGRAPH_CHECK(igraph_degree(graph, &a, igraph_vss_all(), IGRAPH_ALL, 0)); } /* Create list of communities */ debug("Creating community list\n"); communities.n = no_of_nodes; communities.no_of_communities = no_of_nodes; communities.e = (igraph_i_fastgreedy_community*)calloc(no_of_nodes, sizeof(igraph_i_fastgreedy_community)); if (communities.e == 0) { IGRAPH_ERROR("can't run fast greedy community detection", IGRAPH_ENOMEM); } IGRAPH_FINALLY(free, communities.e); communities.heap = (igraph_i_fastgreedy_community**)calloc(no_of_nodes, sizeof(igraph_i_fastgreedy_community*)); if (communities.heap == 0) { IGRAPH_ERROR("can't run fast greedy community detection", IGRAPH_ENOMEM); } IGRAPH_FINALLY(free, communities.heap); communities.heapindex = (igraph_integer_t*)calloc(no_of_nodes, sizeof(igraph_integer_t)); if (communities.heapindex == 0) { IGRAPH_ERROR("can't run fast greedy community detection", IGRAPH_ENOMEM); } IGRAPH_FINALLY_CLEAN(2); IGRAPH_FINALLY(igraph_i_fastgreedy_community_list_destroy, &communities); for (i=0; i<no_of_nodes; i++) { igraph_vector_ptr_init(&communities.e[i].neis, 0); communities.e[i].id = i; communities.e[i].size = 1; } /* Create list of community pairs from edges */ debug("Allocating dq vector\n"); dq = (igraph_real_t*)calloc(no_of_edges, sizeof(igraph_real_t)); if (dq == 0) { IGRAPH_ERROR("can't run fast greedy community detection", IGRAPH_ENOMEM); } IGRAPH_FINALLY(free, dq); debug("Creating community pair list\n"); IGRAPH_CHECK(igraph_eit_create(graph, igraph_ess_all(0), &edgeit)); IGRAPH_FINALLY(igraph_eit_destroy, &edgeit); pairs = (igraph_i_fastgreedy_commpair*)calloc(2*no_of_edges, sizeof(igraph_i_fastgreedy_commpair)); if (pairs == 0) { IGRAPH_ERROR("can't run fast greedy community detection", IGRAPH_ENOMEM); } IGRAPH_FINALLY(free, pairs); i=j=0; while (!IGRAPH_EIT_END(edgeit)) { long int eidx = IGRAPH_EIT_GET(edgeit); igraph_edge(graph, eidx, &ffrom, &fto); /* Create the pairs themselves */ from = (long int)ffrom; to = (long int)fto; if (from == to) { IGRAPH_ERROR("loop edge detected, simplify the graph before starting community detection", IGRAPH_EINVAL); } if (from>to) { dummy=from; from=to; to=dummy; } if (weights) { dq[j]=2*(VECTOR(*weights)[eidx]/(weight_sum*2.0) - VECTOR(a)[from]*VECTOR(a)[to]/(4.0*weight_sum*weight_sum)); } else { dq[j]=2*(1.0/(no_of_edges*2.0) - VECTOR(a)[from]*VECTOR(a)[to]/(4.0*no_of_edges*no_of_edges)); } pairs[i].first = from; pairs[i].second = to; pairs[i].dq = &dq[j]; pairs[i].opposite = &pairs[i+1]; pairs[i+1].first = to; pairs[i+1].second = from; pairs[i+1].dq = pairs[i].dq; pairs[i+1].opposite = &pairs[i]; /* Link the pair to the communities */ igraph_vector_ptr_push_back(&communities.e[from].neis, &pairs[i]); igraph_vector_ptr_push_back(&communities.e[to].neis, &pairs[i+1]); /* Update maximums */ if (communities.e[from].maxdq==0 || *communities.e[from].maxdq->dq < *pairs[i].dq) communities.e[from].maxdq = &pairs[i]; if (communities.e[to].maxdq==0 || *communities.e[to].maxdq->dq < *pairs[i+1].dq) communities.e[to].maxdq = &pairs[i+1]; /* Iterate */ i+=2; j++; IGRAPH_EIT_NEXT(edgeit); } igraph_eit_destroy(&edgeit); IGRAPH_FINALLY_CLEAN(1); /* Sorting community neighbor lists by community IDs */ debug("Sorting community neighbor lists\n"); for (i=0, j=0; i<no_of_nodes; i++) { igraph_vector_ptr_sort(&communities.e[i].neis, igraph_i_fastgreedy_commpair_cmp); /* Isolated vertices won't be stored in the heap (to avoid maxdq == 0) */ if (VECTOR(a)[i] > 0) { communities.heap[j] = &communities.e[i]; communities.heapindex[i] = j; j++; } else { communities.heapindex[i] = -1; } } communities.no_of_communities = j; /* Calculate proper vector a (see paper) and initial modularity */ q=0; igraph_vector_scale(&a, 1.0/(2.0 * (weights ? weight_sum : no_of_edges))); for (i=0; i<no_of_nodes; i++) q -= VECTOR(a)[i]*VECTOR(a)[i]; maxq=q; /* Initializing community heap */ debug("Initializing community heap\n"); igraph_i_fastgreedy_community_list_build_heap(&communities); debug("Initial modularity: %.4f\n", q); /* Let's rock ;) */ no_of_joins=0; while (no_of_joins<total_joins) { IGRAPH_ALLOW_INTERRUPTION(); IGRAPH_PROGRESS("fast greedy community detection", no_of_joins*100.0/total_joins, 0); /* Store the modularity */ if (modularity) VECTOR(*modularity)[no_of_joins] = q; /* Some debug info if needed */ /* igraph_i_fastgreedy_community_list_check_heap(&communities); */ #ifdef DEBUG debug("===========================================\n"); for (i=0; i<communities.n; i++) { if (communities.e[i].maxdq == 0) { debug("Community #%ld: PASSIVE\n", i); continue; } debug("Community #%ld\n ", i); for (j=0; j<igraph_vector_ptr_size(&communities.e[i].neis); j++) { p1=(igraph_i_fastgreedy_commpair*)VECTOR(communities.e[i].neis)[j]; debug(" (%ld,%ld,%.4f)", p1->first, p1->second, *p1->dq); } p1=communities.e[i].maxdq; debug("\n Maxdq: (%ld,%ld,%.4f)\n", p1->first, p1->second, *p1->dq); } debug("Global maxdq is: (%ld,%ld,%.4f)\n", communities.heap[0]->maxdq->first, communities.heap[0]->maxdq->second, *communities.heap[0]->maxdq->dq); for (i=0; i<communities.no_of_communities; i++) debug("(%ld,%ld,%.4f) ", communities.heap[i]->maxdq->first, communities.heap[i]->maxdq->second, *communities.heap[0]->maxdq->dq); debug("\n"); #endif if (communities.heap[0] == 0) break; /* no more communities */ if (communities.heap[0]->maxdq == 0) break; /* there are only isolated comms */ to=communities.heap[0]->maxdq->second; from=communities.heap[0]->maxdq->first; debug("Q[%ld] = %.7f\tdQ = %.7f\t |H| = %ld\n", no_of_joins, q, *communities.heap[0]->maxdq->dq, no_of_nodes-no_of_joins-1); /* DEBUG */ /* from=join_order[no_of_joins*2]; to=join_order[no_of_joins*2+1]; if (to == -1) break; for (i=0; i<igraph_vector_ptr_size(&communities.e[to].neis); i++) { p1=(igraph_i_fastgreedy_commpair*)VECTOR(communities.e[to].neis)[i]; if (p1->second == from) communities.maxdq = p1; } */ n = igraph_vector_ptr_size(&communities.e[to].neis); m = igraph_vector_ptr_size(&communities.e[from].neis); /*if (n>m) { dummy=n; n=m; m=dummy; dummy=to; to=from; from=dummy; }*/ debug(" joining: %ld <- %ld\n", to, from); q += *communities.heap[0]->maxdq->dq; /* Merge the second community into the first */ i = j = 0; while (i<n && j<m) { p1 = (igraph_i_fastgreedy_commpair*)VECTOR(communities.e[to].neis)[i]; p2 = (igraph_i_fastgreedy_commpair*)VECTOR(communities.e[from].neis)[j]; debug("Pairs: %ld-%ld and %ld-%ld\n", p1->first, p1->second, p2->first, p2->second); if (p1->second < p2->second) { /* Considering p1 from now on */ debug(" Considering: %ld-%ld\n", p1->first, p1->second); if (p1->second == from) { debug(" WILL REMOVE: %ld-%ld\n", to, from); } else { /* chain, case 1 */ debug(" CHAIN(1): %ld-%ld %ld, now=%.7f, adding=%.7f, newdq(%ld,%ld)=%.7f\n", to, p1->second, from, *p1->dq, -2*VECTOR(a)[from]*VECTOR(a)[p1->second], p1->first, p1->second, *p1->dq-2*VECTOR(a)[from]*VECTOR(a)[p1->second]); igraph_i_fastgreedy_community_update_dq(&communities, p1, *p1->dq - 2*VECTOR(a)[from]*VECTOR(a)[p1->second]); } i++; } else if (p1->second == p2->second) { /* p1->first, p1->second and p2->first form a triangle */ debug(" Considering: %ld-%ld and %ld-%ld\n", p1->first, p1->second, p2->first, p2->second); /* Update dq value */ debug(" TRIANGLE: %ld-%ld-%ld, now=%.7f, adding=%.7f, newdq(%ld,%ld)=%.7f\n", to, p1->second, from, *p1->dq, *p2->dq, p1->first, p1->second, *p1->dq+*p2->dq); igraph_i_fastgreedy_community_update_dq(&communities, p1, *p1->dq + *p2->dq); igraph_i_fastgreedy_community_remove_nei(&communities, p1->second, from); i++; j++; } else { debug(" Considering: %ld-%ld\n", p2->first, p2->second); if (p2->second == to) { debug(" WILL REMOVE: %ld-%ld\n", p2->second, p2->first); } else { /* chain, case 2 */ debug(" CHAIN(2): %ld %ld-%ld, newdq(%ld,%ld)=%.7f\n", to, p2->second, from, to, p2->second, *p2->dq-2*VECTOR(a)[to]*VECTOR(a)[p2->second]); p2->opposite->second=to; /* need to re-sort community nei list `p2->second` */ /* TODO: quicksort is O(n*logn), although we could do a deletion and * insertion which can be done in O(logn) if deletion is O(1) */ debug(" Re-sorting community %ld\n", p2->second); igraph_vector_ptr_sort(&communities.e[p2->second].neis, igraph_i_fastgreedy_commpair_cmp); /* link from.neis[j] to the current place in to.neis if * from.neis[j] != to */ p2->first=to; IGRAPH_CHECK(igraph_vector_ptr_insert(&communities.e[to].neis,i,p2)); n++; i++; if (*p2->dq > *communities.e[to].maxdq->dq) { communities.e[to].maxdq = p2; k=igraph_i_fastgreedy_community_list_find_in_heap(&communities, to); igraph_i_fastgreedy_community_list_sift_up(&communities, k); } igraph_i_fastgreedy_community_update_dq(&communities, p2, *p2->dq - 2*VECTOR(a)[to]*VECTOR(a)[p2->second]); } j++; } } while (i<n) { p1 = (igraph_i_fastgreedy_commpair*)VECTOR(communities.e[to].neis)[i]; if (p1->second == from) { debug(" WILL REMOVE: %ld-%ld\n", p1->first, from); } else { /* chain, case 1 */ debug(" CHAIN(1): %ld-%ld %ld, now=%.7f, adding=%.7f, newdq(%ld,%ld)=%.7f\n", to, p1->second, from, *p1->dq, -2*VECTOR(a)[from]*VECTOR(a)[p1->second], p1->first, p1->second, *p1->dq-2*VECTOR(a)[from]*VECTOR(a)[p1->second]); igraph_i_fastgreedy_community_update_dq(&communities, p1, *p1->dq - 2*VECTOR(a)[from]*VECTOR(a)[p1->second]); } i++; } while (j<m) { p2 = (igraph_i_fastgreedy_commpair*)VECTOR(communities.e[from].neis)[j]; if (to == p2->second) { j++; continue; } /* chain, case 2 */ debug(" CHAIN(2): %ld %ld-%ld, newdq(%ld,%ld)=%.7f\n", to, p2->second, from, p1->first, p2->second, *p2->dq-2*VECTOR(a)[to]*VECTOR(a)[p2->second]); p2->opposite->second=to; /* need to re-sort community nei list `p2->second` */ /* TODO: quicksort is O(n*logn), although we could do a deletion and * insertion which can be done in O(logn) if deletion is O(1) */ debug(" Re-sorting community %ld\n", p2->second); igraph_vector_ptr_sort(&communities.e[p2->second].neis, igraph_i_fastgreedy_commpair_cmp); /* link from.neis[j] to the current place in to.neis if * from.neis[j] != to */ p2->first=to; IGRAPH_CHECK(igraph_vector_ptr_push_back(&communities.e[to].neis,p2)); if (*p2->dq > *communities.e[to].maxdq->dq) { communities.e[to].maxdq = p2; k=igraph_i_fastgreedy_community_list_find_in_heap(&communities, to); igraph_i_fastgreedy_community_list_sift_up(&communities, k); } igraph_i_fastgreedy_community_update_dq(&communities, p2, *p2->dq-2*VECTOR(a)[to]*VECTOR(a)[p2->second]); j++; } /* Now, remove community `from` from the neighbors of community `to` */ if (communities.no_of_communities > 2) { debug(" REMOVING: %ld-%ld\n", to, from); igraph_i_fastgreedy_community_remove_nei(&communities, to, from); i=igraph_i_fastgreedy_community_list_find_in_heap(&communities, from); igraph_i_fastgreedy_community_list_remove(&communities, i); } communities.e[from].maxdq=0; /* Update community sizes */ communities.e[to].size += communities.e[from].size; communities.e[from].size = 0; /* record what has been merged */ /* igraph_vector_ptr_clear is not enough here as it won't free * the memory consumed by communities.e[from].neis. Thanks * to Tom Gregorovic for pointing that out. */ igraph_vector_ptr_destroy(&communities.e[from].neis); if (merges) { MATRIX(*merges, no_of_joins, 0) = communities.e[to].id; MATRIX(*merges, no_of_joins, 1) = communities.e[from].id; communities.e[to].id = no_of_nodes+no_of_joins; } /* Update vector a */ VECTOR(a)[to] += VECTOR(a)[from]; VECTOR(a)[from] = 0.0; no_of_joins++; } /* TODO: continue merging when some isolated communities remained. Always * joining the communities with the least number of nodes results in the * smallest decrease in modularity every step. Now we're simply deleting * the excess rows from the merge matrix */ if (no_of_joins < total_joins) { long int *ivec; ivec=igraph_Calloc(igraph_matrix_nrow(merges), long int); if (ivec == 0) IGRAPH_ERROR("can't run fast greedy community detection", IGRAPH_ENOMEM); IGRAPH_FINALLY(free, ivec); for (i=0; i<no_of_joins; i++) ivec[i] = i+1; igraph_matrix_permdelete_rows(merges, ivec, total_joins-no_of_joins); free(ivec); IGRAPH_FINALLY_CLEAN(1); }
int igraph_i_kleinberg(const igraph_t *graph, igraph_vector_t *vector, igraph_real_t *value, igraph_bool_t scale, igraph_arpack_options_t *options, int inout) { igraph_adjlist_t myinadjlist, myoutadjlist; igraph_adjlist_t *inadjlist, *outadjlist; igraph_vector_t tmp; igraph_vector_t values; igraph_matrix_t vectors; igraph_i_kleinberg_data_t extra; long int i; options->n=igraph_vcount(graph); options->start=1; IGRAPH_VECTOR_INIT_FINALLY(&values, 0); IGRAPH_MATRIX_INIT_FINALLY(&vectors, options->n, 1); IGRAPH_VECTOR_INIT_FINALLY(&tmp, options->n); if (inout==0) { inadjlist=&myinadjlist; outadjlist=&myoutadjlist; } else if (inout==1) { inadjlist=&myoutadjlist; outadjlist=&myinadjlist; } else { /* This should not happen */ IGRAPH_ERROR("Invalid 'inout' argument, plese do not call " "this funtion directly", IGRAPH_FAILURE); } IGRAPH_CHECK(igraph_adjlist_init(graph, &myinadjlist, IGRAPH_IN)); IGRAPH_FINALLY(igraph_adjlist_destroy, &myinadjlist); IGRAPH_CHECK(igraph_adjlist_init(graph, &myoutadjlist, IGRAPH_OUT)); IGRAPH_FINALLY(igraph_adjlist_destroy, &myoutadjlist); IGRAPH_CHECK(igraph_degree(graph, &tmp, igraph_vss_all(), IGRAPH_ALL, 0)); for (i=0; i<options->n; i++) { if (VECTOR(tmp)[i] != 0) { MATRIX(vectors, i, 0) = VECTOR(tmp)[i]; } else { MATRIX(vectors, i, 0) = 1.0; } } extra.in=inadjlist; extra.out=outadjlist; extra.tmp=&tmp; options->n = igraph_vcount(graph); options->nev = 1; options->ncv = 3; options->which[0]='L'; options->which[1]='M'; options->start=1; /* no random start vector */ IGRAPH_CHECK(igraph_arpack_rssolve(igraph_i_kleinberg2, &extra, options, 0, &values, &vectors)); igraph_adjlist_destroy(&myoutadjlist); igraph_adjlist_destroy(&myinadjlist); igraph_vector_destroy(&tmp); IGRAPH_FINALLY_CLEAN(3); if (value) { *value = VECTOR(values)[0]; } if (vector) { igraph_real_t amax=0; long int which=0; long int i; IGRAPH_CHECK(igraph_vector_resize(vector, options->n)); for (i=0; i<options->n; i++) { igraph_real_t tmp; VECTOR(*vector)[i] = MATRIX(vectors, i, 0); tmp=fabs(VECTOR(*vector)[i]); if (tmp>amax) { amax=tmp; which=i; } } if (scale && amax!=0) { igraph_vector_scale(vector, 1/VECTOR(*vector)[which]); } } if (options->info) { IGRAPH_WARNING("Non-zero return code from ARPACK routine!"); } igraph_matrix_destroy(&vectors); igraph_vector_destroy(&values); IGRAPH_FINALLY_CLEAN(2); return 0; }
int main() { igraph_t g; igraph_vector_t deg; igraph_bool_t is_simple; igraph_set_error_handler(&igraph_error_handler_ignore); igraph_vector_init(°, 0); /* k-regular undirected graph, even degrees, no multiple edges */ igraph_k_regular_game(&g, 10, 4, 0, 0); igraph_degree(&g, °, igraph_vss_all(), IGRAPH_ALL, 1); igraph_vector_print(°); igraph_is_simple(&g, &is_simple); if (!is_simple) return 1; if (igraph_is_directed(&g)) return 1; igraph_destroy(&g); /* k-regular undirected graph, odd degrees, even number of vertices, no multiple edges */ igraph_k_regular_game(&g, 10, 3, 0, 0); igraph_degree(&g, °, igraph_vss_all(), IGRAPH_ALL, 1); igraph_vector_print(°); igraph_is_simple(&g, &is_simple); if (!is_simple) return 2; if (igraph_is_directed(&g)) return 2; igraph_destroy(&g); /* k-regular undirected graph, odd degrees, odd number of vertices, no multiple edges */ if (!igraph_k_regular_game(&g, 9, 3, 0, 0)) return 3; /* k-regular undirected graph, even degrees, multiple edges */ igraph_k_regular_game(&g, 10, 4, 0, 1); igraph_degree(&g, °, igraph_vss_all(), IGRAPH_ALL, 1); igraph_vector_print(°); if (igraph_is_directed(&g)) return 14; igraph_destroy(&g); /* k-regular undirected graph, odd degrees, even number of vertices, multiple edges */ igraph_k_regular_game(&g, 10, 3, 0, 1); igraph_degree(&g, °, igraph_vss_all(), IGRAPH_ALL, 1); igraph_vector_print(°); if (igraph_is_directed(&g)) return 15; igraph_destroy(&g); /* k-regular undirected graph, odd degrees, odd number of vertices, multiple edges */ if (!igraph_k_regular_game(&g, 9, 3, 0, 1)) return 4; /* k-regular directed graph, even degrees, no multiple edges */ igraph_k_regular_game(&g, 10, 4, 1, 0); igraph_degree(&g, °, igraph_vss_all(), IGRAPH_IN, 1); igraph_vector_print(°); igraph_degree(&g, °, igraph_vss_all(), IGRAPH_OUT, 1); igraph_vector_print(°); igraph_is_simple(&g, &is_simple); if (!is_simple) return 5; if (!igraph_is_directed(&g)) return 5; igraph_destroy(&g); /* k-regular directed graph, odd degrees, even number of vertices, no multiple edges */ igraph_k_regular_game(&g, 10, 3, 1, 0); igraph_degree(&g, °, igraph_vss_all(), IGRAPH_IN, 1); igraph_vector_print(°); igraph_degree(&g, °, igraph_vss_all(), IGRAPH_OUT, 1); igraph_vector_print(°); igraph_is_simple(&g, &is_simple); if (!is_simple) return 6; if (!igraph_is_directed(&g)) return 6; igraph_destroy(&g); /* k-regular directed graph, odd degrees, odd number of vertices, no multiple edges */ igraph_k_regular_game(&g, 9, 3, 1, 0); igraph_degree(&g, °, igraph_vss_all(), IGRAPH_IN, 1); igraph_vector_print(°); igraph_degree(&g, °, igraph_vss_all(), IGRAPH_OUT, 1); igraph_vector_print(°); igraph_is_simple(&g, &is_simple); if (!is_simple) return 7; if (!igraph_is_directed(&g)) return 7; igraph_destroy(&g); /* k-regular directed graph, even degrees, multiple edges */ igraph_k_regular_game(&g, 10, 4, 1, 1); igraph_degree(&g, °, igraph_vss_all(), IGRAPH_IN, 1); igraph_vector_print(°); igraph_degree(&g, °, igraph_vss_all(), IGRAPH_OUT, 1); igraph_vector_print(°); if (!igraph_is_directed(&g)) return 16; igraph_destroy(&g); /* k-regular directed graph, odd degrees, even number of vertices, multiple edges */ igraph_k_regular_game(&g, 10, 3, 1, 1); igraph_degree(&g, °, igraph_vss_all(), IGRAPH_IN, 1); igraph_vector_print(°); igraph_degree(&g, °, igraph_vss_all(), IGRAPH_OUT, 1); igraph_vector_print(°); if (!igraph_is_directed(&g)) return 17; igraph_destroy(&g); /* k-regular directed graph, odd degrees, odd number of vertices, multiple edges */ igraph_k_regular_game(&g, 9, 3, 1, 1); igraph_degree(&g, °, igraph_vss_all(), IGRAPH_IN, 1); igraph_vector_print(°); igraph_degree(&g, °, igraph_vss_all(), IGRAPH_OUT, 1); igraph_vector_print(°); if (!igraph_is_directed(&g)) return 18; igraph_destroy(&g); /* k-regular undirected graph, too large degree, no multiple edges */ if (!igraph_k_regular_game(&g, 10, 10, 0, 0)) return 8; /* k-regular directed graph, too large degree, no multiple edges */ if (!igraph_k_regular_game(&g, 10, 10, 1, 0)) return 9; /* empty graph */ if (igraph_k_regular_game(&g, 0, 0, 0, 0)) return 10; if (igraph_vcount(&g) != 0 || igraph_ecount(&g) != 0 || igraph_is_directed(&g)) return 11; igraph_destroy(&g); if (igraph_k_regular_game(&g, 0, 0, 1, 0)) return 12; if (igraph_vcount(&g) != 0 || igraph_ecount(&g) != 0 || !igraph_is_directed(&g)) return 13; igraph_destroy(&g); igraph_vector_destroy(°); return 0; }
int igraph_i_vertex_coloring_greedy_cn(const igraph_t *graph, igraph_vector_int_t *colors) { long i, vertex, maxdeg; long vc = igraph_vcount(graph); igraph_2wheap_t cn; /* indexed heap storing number of already coloured neighbours */ igraph_vector_int_t neigh_colors; igraph_adjlist_t adjlist; IGRAPH_CHECK(igraph_vector_int_resize(colors, vc)); igraph_vector_int_fill(colors, 0); /* Nothing to do for 0 or 1 vertices. * Remember that colours are integers starting from 0, * and the 'colors' vector is already 0-initialized above. */ if (vc <= 1) return IGRAPH_SUCCESS; IGRAPH_CHECK(igraph_adjlist_init(graph, &adjlist, IGRAPH_ALL)); IGRAPH_FINALLY(igraph_adjlist_destroy, &adjlist); /* find maximum degree and a corresponding vertex */ { igraph_vector_t degree; IGRAPH_CHECK(igraph_vector_init(°ree, 0)); IGRAPH_FINALLY(igraph_vector_destroy, °ree); IGRAPH_CHECK(igraph_degree(graph, °ree, igraph_vss_all(), IGRAPH_ALL, 0)); vertex = igraph_vector_which_max(°ree); maxdeg = VECTOR(degree)[vertex]; igraph_vector_destroy(°ree); IGRAPH_FINALLY_CLEAN(1); } IGRAPH_CHECK(igraph_vector_int_init(&neigh_colors, 0)); IGRAPH_CHECK(igraph_vector_int_reserve(&neigh_colors, maxdeg)); IGRAPH_FINALLY(igraph_vector_int_destroy, &neigh_colors); IGRAPH_CHECK(igraph_2wheap_init(&cn, vc)); IGRAPH_FINALLY(igraph_2wheap_destroy, &cn); for (i=0; i < vc; ++i) if (i != vertex) igraph_2wheap_push_with_index(&cn, i, 0); /* should not fail since memory was already reserved */ while (1) { igraph_vector_int_t *neighbors = igraph_adjlist_get(&adjlist, vertex); long neigh_count = igraph_vector_int_size(neighbors); /* colour current vertex */ { igraph_integer_t col; IGRAPH_CHECK(igraph_vector_int_resize(&neigh_colors, neigh_count)); for (i=0; i < neigh_count; ++i) VECTOR(neigh_colors)[i] = VECTOR(*colors)[ VECTOR(*neighbors)[i] ]; igraph_vector_int_sort(&neigh_colors); i=0; col = 0; do { while (i < neigh_count && VECTOR(neigh_colors)[i] == col) i++; col++; } while (i < neigh_count && VECTOR(neigh_colors)[i] == col); VECTOR(*colors)[vertex] = col; } /* increment number of coloured neighbours for each neighbour of vertex */ for (i=0; i < neigh_count; ++i) { long idx = VECTOR(*neighbors)[i]; if (igraph_2wheap_has_elem(&cn, idx)) igraph_2wheap_modify(&cn, idx, igraph_2wheap_get(&cn, idx) + 1); } /* stop if no more vertices left to colour */ if (igraph_2wheap_empty(&cn)) break; igraph_2wheap_delete_max_index(&cn, &vertex); IGRAPH_ALLOW_INTERRUPTION(); } /* subtract 1 from each colour value, so that colours start at 0 */ igraph_vector_int_add_constant(colors, -1); /* free data structures */ igraph_vector_int_destroy(&neigh_colors); igraph_adjlist_destroy(&adjlist); igraph_2wheap_destroy(&cn); IGRAPH_FINALLY_CLEAN(3); return IGRAPH_SUCCESS; }
int igraph_pagerank(const igraph_t *graph, igraph_vector_t *vector, igraph_real_t *value, const igraph_vs_t vids, igraph_bool_t directed, igraph_real_t damping, const igraph_vector_t *weights, igraph_arpack_options_t *options) { igraph_matrix_t values; igraph_matrix_t vectors; igraph_integer_t dirmode; igraph_vector_t outdegree; igraph_vector_t tmp; long int i; long int no_of_nodes=igraph_vcount(graph); long int no_of_edges=igraph_ecount(graph); options->n = igraph_vcount(graph); options->nev = 1; options->ncv = 3; options->which[0]='L'; options->which[1]='M'; options->start=1; /* no random start vector */ directed = directed && igraph_is_directed(graph); if (weights && igraph_vector_size(weights) != igraph_ecount(graph)) { IGRAPH_ERROR("Invalid length of weights vector when calculating " "PageRank scores", IGRAPH_EINVAL); } IGRAPH_MATRIX_INIT_FINALLY(&values, 0, 0); IGRAPH_MATRIX_INIT_FINALLY(&vectors, options->n, 1); if (directed) { dirmode=IGRAPH_IN; } else { dirmode=IGRAPH_ALL; } IGRAPH_VECTOR_INIT_FINALLY(&outdegree, options->n); IGRAPH_VECTOR_INIT_FINALLY(&tmp, options->n); RNG_BEGIN(); if (!weights) { igraph_adjlist_t adjlist; igraph_i_pagerank_data_t data = { graph, &adjlist, damping, &outdegree, &tmp }; IGRAPH_CHECK(igraph_degree(graph, &outdegree, igraph_vss_all(), directed ? IGRAPH_OUT : IGRAPH_ALL, /*loops=*/ 0)); /* Avoid division by zero */ for (i=0; i<options->n; i++) { if (VECTOR(outdegree)[i]==0) { VECTOR(outdegree)[i]=1; } MATRIX(vectors, i, 0) = VECTOR(outdegree)[i]; } IGRAPH_CHECK(igraph_adjlist_init(graph, &adjlist, dirmode)); IGRAPH_FINALLY(igraph_adjlist_destroy, &adjlist); IGRAPH_CHECK(igraph_arpack_rnsolve(igraph_i_pagerank, &data, options, 0, &values, &vectors)); igraph_adjlist_destroy(&adjlist); IGRAPH_FINALLY_CLEAN(1); } else { igraph_adjedgelist_t adjedgelist; igraph_i_pagerank_data2_t data = { graph, &adjedgelist, weights, damping, &outdegree, &tmp }; IGRAPH_CHECK(igraph_adjedgelist_init(graph, &adjedgelist, dirmode)); IGRAPH_FINALLY(igraph_adjedgelist_destroy, &adjedgelist); /* Weighted degree */ for (i=0; i<no_of_edges; i++) { long int from=IGRAPH_FROM(graph, i); long int to=IGRAPH_TO(graph, i); igraph_real_t weight=VECTOR(*weights)[i]; VECTOR(outdegree)[from] += weight; if (!directed) { VECTOR(outdegree)[to] += weight; } } /* Avoid division by zero */ for (i=0; i<options->n; i++) { if (VECTOR(outdegree)[i]==0) { VECTOR(outdegree)[i]=1; } MATRIX(vectors, i, 0) = VECTOR(outdegree)[i]; } IGRAPH_CHECK(igraph_arpack_rnsolve(igraph_i_pagerank2, &data, options, 0, &values, &vectors)); igraph_adjedgelist_destroy(&adjedgelist); IGRAPH_FINALLY_CLEAN(1); } RNG_END(); igraph_vector_destroy(&tmp); igraph_vector_destroy(&outdegree); IGRAPH_FINALLY_CLEAN(2); if (value) { *value=MATRIX(values, 0, 0); } if (vector) { long int i; igraph_vit_t vit; long int nodes_to_calc; igraph_real_t sum=0; for (i=0; i<no_of_nodes; i++) { sum += MATRIX(vectors, i, 0); } IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit)); IGRAPH_FINALLY(igraph_vit_destroy, &vit); nodes_to_calc=IGRAPH_VIT_SIZE(vit); IGRAPH_CHECK(igraph_vector_resize(vector, nodes_to_calc)); for (IGRAPH_VIT_RESET(vit), i=0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { VECTOR(*vector)[i] = MATRIX(vectors, (long int)IGRAPH_VIT_GET(vit), 0); VECTOR(*vector)[i] /= sum; } igraph_vit_destroy(&vit); IGRAPH_FINALLY_CLEAN(1); } if (options->info) { IGRAPH_WARNING("Non-zero return code from ARPACK routine!"); } igraph_matrix_destroy(&vectors); igraph_matrix_destroy(&values); IGRAPH_FINALLY_CLEAN(2); return 0; }
int igraph_eigenvector_centrality(const igraph_t *graph, igraph_vector_t *vector, igraph_real_t *value, igraph_bool_t scale, const igraph_vector_t *weights, igraph_arpack_options_t *options) { igraph_vector_t values; igraph_matrix_t vectors; igraph_vector_t degree; long int i; options->n=igraph_vcount(graph); options->start=1; /* no random start vector */ if (weights && igraph_vector_size(weights) != igraph_ecount(graph)) { IGRAPH_ERROR("Invalid length of weights vector when calculating " "eigenvector centrality", IGRAPH_EINVAL); } if (weights && igraph_is_directed(graph)) { IGRAPH_WARNING("Weighted directed graph in eigenvector centrality"); } IGRAPH_VECTOR_INIT_FINALLY(&values, 0); IGRAPH_MATRIX_INIT_FINALLY(&vectors, options->n, 1); IGRAPH_VECTOR_INIT_FINALLY(°ree, options->n); IGRAPH_CHECK(igraph_degree(graph, °ree, igraph_vss_all(), IGRAPH_ALL, /*loops=*/ 0)); for (i=0; i<options->n; i++) { if (VECTOR(degree)[i]) { MATRIX(vectors, i, 0) = VECTOR(degree)[i]; } else { MATRIX(vectors, i, 0) = 1.0; } } igraph_vector_destroy(°ree); IGRAPH_FINALLY_CLEAN(1); options->n = igraph_vcount(graph); options->nev = 1; options->ncv = 3; options->which[0]='L'; options->which[1]='A'; options->start=1; /* no random start vector */ if (!weights) { igraph_adjlist_t adjlist; IGRAPH_CHECK(igraph_adjlist_init(graph, &adjlist, IGRAPH_ALL)); IGRAPH_FINALLY(igraph_adjlist_destroy, &adjlist); IGRAPH_CHECK(igraph_arpack_rssolve(igraph_i_eigenvector_centrality, &adjlist, options, 0, &values, &vectors)); igraph_adjlist_destroy(&adjlist); IGRAPH_FINALLY_CLEAN(1); } else { igraph_adjedgelist_t adjedgelist; igraph_i_eigenvector_centrality_t data = { graph, &adjedgelist, weights }; IGRAPH_CHECK(igraph_adjedgelist_init(graph, &adjedgelist, IGRAPH_ALL)); IGRAPH_FINALLY(igraph_adjedgelist_destroy, &adjedgelist); IGRAPH_CHECK(igraph_arpack_rssolve(igraph_i_eigenvector_centrality2, &data, options, 0, &values, &vectors)); igraph_adjedgelist_destroy(&adjedgelist); IGRAPH_FINALLY_CLEAN(1); } if (value) { *value=VECTOR(values)[0]; } if (vector) { igraph_real_t amax=0; long int which=0; long int i; IGRAPH_CHECK(igraph_vector_resize(vector, options->n)); for (i=0; i<options->n; i++) { igraph_real_t tmp; VECTOR(*vector)[i] = MATRIX(vectors, i, 0); tmp=fabs(VECTOR(*vector)[i]); if (tmp>amax) { amax=tmp; which=i; } } if (scale && amax!=0) { igraph_vector_scale(vector, 1/VECTOR(*vector)[which]); } } if (options->info) { IGRAPH_WARNING("Non-zero return code from ARPACK routine!"); } igraph_matrix_destroy(&vectors); igraph_vector_destroy(&values); IGRAPH_FINALLY_CLEAN(2); return 0; }
int main() { igraph_t g; FILE *karate, *neural; igraph_real_t res; igraph_vector_t types; igraph_vector_t degree, outdegree, indegree; igraph_real_t football_types[] = { 7,0,2,3,7,3,2,8,8,7,3,10,6,2,6,2,7,9,6,1,9,8,8,7,10,0,6,9, 11,1,1,6,2,0,6,1,5,0,6,2,3,7,5,6,4,0,11,2,4,11,10,8,3,11,6, 1,9,4,11,10,2,6,9,10,2,9,4,11,8,10,9,6,3,11,3,4,9,8,8,1,5,3, 5,11,3,6,4,9,11,0,5,4,4,7,1,9,9,10,3,6,2,1,3,0,7,0,2,3,8,0, 4,8,4,9,11 }; karate=fopen("karate.gml", "r"); igraph_read_graph_gml(&g, karate); fclose(karate); igraph_vector_init(&types, 0); igraph_degree(&g, &types, igraph_vss_all(), IGRAPH_ALL, /*loops=*/ 1); igraph_assortativity_nominal(&g, &types, &res, /*directed=*/ 0); printf("%.5f\n", res); igraph_destroy(&g); /*---------------------*/ neural=fopen("celegansneural.gml", "r"); igraph_read_graph_gml(&g, neural); fclose(neural); igraph_degree(&g, &types, igraph_vss_all(), IGRAPH_ALL, /*loops=*/ 1); igraph_assortativity_nominal(&g, &types, &res, /*directed=*/ 1); printf("%.5f\n", res); igraph_assortativity_nominal(&g, &types, &res, /*directed=*/ 0); printf("%.5f\n", res); igraph_destroy(&g); igraph_vector_destroy(&types); /*---------------------*/ karate=fopen("karate.gml", "r"); igraph_read_graph_gml(&g, karate); fclose(karate); igraph_vector_init(°ree, 0); igraph_degree(&g, °ree, igraph_vss_all(), IGRAPH_ALL, /*loops=*/ 1); igraph_vector_add_constant(°ree, -1); igraph_assortativity(&g, °ree, 0, &res, /*directed=*/ 0); printf("%.5f\n", res); igraph_destroy(&g); /*---------------------*/ neural=fopen("celegansneural.gml", "r"); igraph_read_graph_gml(&g, neural); fclose(neural); igraph_degree(&g, °ree, igraph_vss_all(), IGRAPH_ALL, /*loops=*/ 1); igraph_vector_add_constant(°ree, -1); igraph_assortativity(&g, °ree, 0, &res, /*directed=*/ 1); printf("%.5f\n", res); igraph_assortativity(&g, °ree, 0, &res, /*directed=*/ 0); printf("%.5f\n", res); igraph_vector_destroy(°ree); /*---------------------*/ igraph_vector_init(&indegree, 0); igraph_vector_init(&outdegree, 0); igraph_degree(&g, &indegree, igraph_vss_all(), IGRAPH_IN, /*loops=*/ 1); igraph_degree(&g, &outdegree, igraph_vss_all(), IGRAPH_OUT, /*loops=*/ 1); igraph_vector_add_constant(&indegree, -1); igraph_vector_add_constant(&outdegree, -1); igraph_assortativity(&g, &outdegree, &indegree, &res, /*directed=*/ 1); printf("%.5f\n", res); igraph_vector_destroy(&indegree); igraph_vector_destroy(&outdegree); /*---------------------*/ igraph_assortativity_degree(&g, &res, /*directed=*/ 1); printf("%.5f\n", res); igraph_destroy(&g); /*---------------------*/ karate=fopen("karate.gml", "r"); igraph_read_graph_gml(&g, karate); fclose(karate); igraph_assortativity_degree(&g, &res, /*directed=*/ 1); printf("%.5f\n", res); igraph_destroy(&g); /*---------------------*/ igraph_small(&g, sizeof(football_types)/sizeof(igraph_real_t), IGRAPH_UNDIRECTED, 0,1,2,3,0,4,4,5,3,5,2,6,6,7,7,8,8,9,0,9,4,9,5,10,10,11,5,11, 3,11,12,13,2,13,2,14,12,14,14,15,13,15,2,15,4,16,9,16,0,16, 16,17,12,17,12,18,18,19,17,20,20,21,8,21,7,21,9,22,7,22,21, 22,8,22,22,23,9,23,4,23,16,23,0,23,11,24,24,25,1,25,3,26,12, 26,14,26,26,27,17,27,1,27,17,27,4,28,11,28,24,28,19,29,29, 30,19,30,18,31,31,32,21,32,15,32,13,32,6,32,0,33,1,33,25,33, 19,33,31,34,26,34,12,34,18,34,34,35,0,35,29,35,19,35,30,35, 18,36,12,36,20,36,19,36,36,37,1,37,25,37,33,37,18,38,16,38, 28,38,26,38,14,38,12,38,38,39,6,39,32,39,13,39,15,39,7,40,3, 40,40,41,8,41,4,41,23,41,9,41,0,41,16,41,34,42,29,42,18,42, 26,42,42,43,36,43,26,43,31,43,38,43,12,43,14,43,19,44,35,44, 30,44,44,45,13,45,33,45,1,45,37,45,25,45,21,46,46,47,22,47, 6,47,15,47,2,47,39,47,32,47,44,48,48,49,32,49,46,49,30,50, 24,50,11,50,28,50,50,51,40,51,8,51,22,51,21,51,3,52,40,52,5, 52,52,53,25,53,48,53,49,53,46,53,39,54,31,54,38,54,14,54,34, 54,18,54,54,55,31,55,6,55,35,55,29,55,19,55,30,55,27,56,56, 57,1,57,42,57,44,57,48,57,3,58,6,58,17,58,36,58,36,59,58,59, 59,60,10,60,39,60,6,60,47,60,13,60,15,60,2,60,43,61,47,61, 54,61,18,61,26,61,31,61,34,61,61,62,20,62,45,62,17,62,27,62, 56,62,27,63,58,63,59,63,42,63,63,64,9,64,32,64,60,64,2,64,6, 64,47,64,13,64,0,65,27,65,17,65,63,65,56,65,20,65,65,66,59, 66,24,66,44,66,48,66,16,67,41,67,46,67,53,67,49,67,67,68,15, 68,50,68,21,68,51,68,7,68,22,68,8,68,4,69,24,69,28,69,50,69, 11,69,69,70,43,70,65,70,20,70,56,70,62,70,27,70,60,71,18,71, 14,71,34,71,54,71,38,71,61,71,31,71,71,72,2,72,10,72,3,72, 40,72,52,72,7,73,49,73,53,73,67,73,46,73,73,74,2,74,72,74,5, 74,10,74,52,74,3,74,40,74,20,75,66,75,48,75,57,75,44,75,75, 76,27,76,59,76,20,76,70,76,66,76,56,76,62,76,73,77,22,77,7, 77,51,77,21,77,8,77,77,78,23,78,50,78,28,78,22,78,8,78,68, 78,7,78,51,78,31,79,43,79,30,79,19,79,29,79,35,79,55,79,79, 80,37,80,29,80,16,81,5,81,40,81,10,81,72,81,3,81,81,82,74, 82,39,82,77,82,80,82,30,82,29,82,7,82,53,83,81,83,69,83,73, 83,46,83,67,83,49,83,83,84,24,84,49,84,52,84,3,84,74,84,10, 84,81,84,5,84,3,84,6,85,14,85,38,85,43,85,80,85,12,85,26,85, 31,85,44,86,53,86,75,86,57,86,48,86,80,86,66,86,86,87,17,87, 62,87,56,87,24,87,20,87,65,87,49,88,58,88,83,88,69,88,46,88, 53,88,73,88,67,88,88,89,1,89,37,89,25,89,33,89,55,89,45,89, 5,90,8,90,23,90,0,90,11,90,50,90,24,90,69,90,28,90,29,91,48, 91,66,91,69,91,44,91,86,91,57,91,80,91,91,92,35,92,15,92,86, 92,48,92,57,92,61,92,66,92,75,92,0,93,23,93,80,93,16,93,4, 93,82,93,91,93,41,93,9,93,34,94,19,94,55,94,79,94,80,94,29, 94,30,94,82,94,35,94,70,95,69,95,76,95,62,95,56,95,27,95,17, 95,87,95,37,95,48,96,17,96,76,96,27,96,56,96,65,96,20,96,87, 96,5,97,86,97,58,97,11,97,59,97,63,97,97,98,77,98,48,98,84, 98,40,98,10,98,5,98,52,98,81,98,89,99,34,99,14,99,85,99,54, 99,18,99,31,99,61,99,71,99,14,99,99,100,82,100,13,100,2,100, 15,100,32,100,64,100,47,100,39,100,6,100,51,101,30,101,94, 101,1,101,79,101,58,101,19,101,55,101,35,101,29,101,100,102, 74,102,52,102,98,102,72,102,40,102,10,102,3,102,102,103,33, 103,45,103,25,103,89,103,37,103,1,103,70,103,72,104,11,104, 0,104,93,104,67,104,41,104,16,104,87,104,23,104,4,104,9,104, 89,105,103,105,33,105,62,105,37,105,45,105,1,105,80,105,25, 105,25,106,56,106,92,106,2,106,13,106,32,106,60,106,6,106, 64,106,15,106,39,106,88,107,75,107,98,107,102,107,72,107,40, 107,81,107,5,107,10,107,84,107,4,108,9,108,7,108,51,108,77, 108,21,108,78,108,22,108,68,108,79,109,30,109,63,109,1,109, 33,109,103,109,105,109,45,109,25,109,89,109,37,109,67,110, 13,110,24,110,80,110,88,110,49,110,73,110,46,110,83,110,53, 110,23,111,64,111,46,111,78,111,8,111,21,111,51,111,7,111, 108,111,68,111,77,111,52,112,96,112,97,112,57,112,66,112,63, 112,44,112,92,112,75,112,91,112,28,113,20,113,95,113,59,113, 70,113,17,113,87,113,76,113,65,113,96,113,83,114,88,114,110, 114,53,114,49,114,73,114,46,114,67,114,58,114,15,114,104,114, -1); igraph_simplify(&g, /*multiple=*/ 1, /*loops=*/ 1, /*edge_comb=*/ 0); igraph_vector_view(&types, football_types, sizeof(football_types) / sizeof(igraph_real_t)); igraph_assortativity_nominal(&g, &types, &res, /*directed=*/ 0); printf("%.5f\n", res); igraph_destroy(&g); return 0; }