/* call-seq: * graph.topological_sorting(mode) -> Array * * Calculate a possible topological sorting of the graph. A topological * sorting of a directed acyclic graph is a linear ordering of its nodes * where each node comes before all nodes to which it has edges. Every DAG * has at least one topological sort, and may have many. This function * returns a possible topological sort among them. If the graph is not * acyclic (it has at least one cycle), a partial topological sort is * returned and a warning is issued. mode specifies how to use the direction * of the edges. For IGRAPH_OUT, the sorting order ensures that each node * comes before all nodes to which it has edges, so nodes with no incoming * edges go first. For IGRAPH_IN, it is quite the opposite: each node comes * before all nodes from which it receives edges. Nodes with no outgoing * edges go first. */ VALUE cIGraph_topological_sorting(VALUE self, VALUE mode){ igraph_t *graph; igraph_vector_t res; igraph_neimode_t pmode = NUM2INT(mode); VALUE result = rb_ary_new(); int i; igraph_vector_init_int(&res,0); Data_Get_Struct(self, igraph_t, graph); igraph_topological_sorting(graph, &res, pmode); for(i=0;i<igraph_vector_size(&res);i++){ rb_ary_push(result,cIGraph_get_vertex_object(self,VECTOR(res)[i])); } igraph_vector_destroy(&res); return result; }
igraph_vector_t * ggen_analyze_longest_path(igraph_t *g) { igraph_vector_t topology; igraph_vector_t lengths; igraph_vector_t preds; igraph_vs_t vs; igraph_vit_t vit; igraph_vector_t *res = NULL; int err; unsigned long v,i,f,t; long maxv; if(g == NULL) return NULL; v = igraph_vcount(g); err = igraph_vector_init(&topology,v); if(err) return NULL; err = igraph_vector_init(&lengths,v); if(err) goto error_il; err = igraph_vector_init(&preds,v); if(err) goto error_ip; res = malloc(sizeof(igraph_vector_t)); if(res == NULL) goto cleanup; err = igraph_vector_init(res,v); if(err) goto error_ir; // sort topologically the vertices err = igraph_topological_sorting(g,&topology,IGRAPH_OUT); if(err) goto error; // igraph is stupid, it returns 0 even if the graph isn't a dag if(igraph_vector_size(&topology) != v) goto error; // find the best path incomming from every node igraph_vector_null(&lengths); igraph_vector_fill(&preds,-1); maxv = -1; for(i = 0; i < v; i++) { f = VECTOR(topology)[i]; err = igraph_vs_adj(&vs,f,IGRAPH_OUT); if(err) goto error; err = igraph_vit_create(g,vs,&vit); if(err) { igraph_vs_destroy(&vs); goto error; } for(vit; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit)) { t = IGRAPH_VIT_GET(vit); if(VECTOR(lengths)[t] < VECTOR(lengths)[f] + 1) { VECTOR(lengths)[t] = VECTOR(lengths)[f] +1; VECTOR(preds)[t] = f; } if(maxv == -1 || VECTOR(lengths)[t] > VECTOR(lengths)[maxv]) maxv = t; } igraph_vs_destroy(&vs); igraph_vit_destroy(&vit); } // build the path, using preds and maxv f = 0; while(maxv != -1) { VECTOR(*res)[f++] = maxv; maxv = VECTOR(preds)[maxv]; } // finish the path correctly, resizing and reversing the array err = igraph_vector_resize(res,f); if(err) goto error; err = igraph_vector_reverse(res); if(err) goto error; goto cleanup; error: igraph_vector_destroy(res); error_ir: free(res); res = NULL; cleanup: igraph_vector_destroy(&preds); error_ip: igraph_vector_destroy(&lengths); error_il: igraph_vector_destroy(&topology); return res; }
igraph_vector_t *ggen_analyze_lowest_single_ancestor(igraph_t *g) { unsigned long i,v,l,vid,r; int err = 0; igraph_vector_t toposort,itopo; igraph_vector_t *lsa; igraph_t tree; igraph_vs_t vs; igraph_vit_t vit; lca_metadata md; if(g == NULL) return NULL; err = igraph_vector_init(&toposort,igraph_vcount(g)); if(err) return NULL; err = igraph_topological_sorting(g,&toposort,IGRAPH_OUT); if(err) goto d_tp; /* build a reverse index of the toposort */ err = igraph_vector_init(&itopo,igraph_vcount(g)); if(err) goto d_tp; for(i = 0; i < igraph_vcount(g); i++) { v = VECTOR(toposort)[i]; VECTOR(itopo)[v] = i; } err = igraph_empty(&tree,1,IGRAPH_DIRECTED); if(err) goto d_i; lsa = calloc(1,sizeof(igraph_vector_t*)); if(lsa == NULL) goto cleanup; err = igraph_vector_init(lsa,igraph_vcount(g)); if(err) goto f_l; for(v = 1; v < igraph_vcount(g); v++) { vid = VECTOR(toposort)[v]; tree_lca_metadata_init(&tree,&md); tree_lca_preprocessing(&tree,0,&md); /* iterate over parents of v in g * The lsa of a node is the LCA of all its parents in our * special tree. */ igraph_vs_adj(&vs, vid, IGRAPH_IN); igraph_vit_create(g,vs,&vit); l = VECTOR(itopo)[IGRAPH_VIT_GET(vit)]; IGRAPH_VIT_NEXT(vit); for(vit;!IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit)) { tree_lca_query(&tree,l,VECTOR(itopo)[IGRAPH_VIT_GET(vit)],&r,&md); l = r; } igraph_vit_destroy(&vit); igraph_vs_destroy(&vs); tree_lca_metadata_free(&tree,&md); // update tree err = igraph_add_vertices(&tree,1,NULL); if(err) goto d_l; err = igraph_add_edge(&tree,l,v); if(err) goto d_l; VECTOR(*lsa)[vid] = VECTOR(toposort)[l]; } goto cleanup; d_l: igraph_vector_destroy(lsa); f_l: free(lsa); lsa = NULL; cleanup: igraph_destroy(&tree); d_i: igraph_vector_destroy(&itopo); d_tp: igraph_vector_destroy(&toposort); return lsa; }