diff --git a/ext/cIGraph.c b/ext/cIGraph.c index 9bb1aac..780c51f 100644 --- a/ext/cIGraph.c +++ b/ext/cIGraph.c @@ -171,6 +171,18 @@ VALUE cIGraph_initialize(int argc, VALUE *argv, VALUE self){ void Init_igraph(){ + //Modules + VALUE cIGraph_connectivity; + VALUE cIGraph_mincuts; + VALUE cIGraph_layout; + VALUE cIGraph_clique; + VALUE cIGraph_indyver; + VALUE cIGraph_isomor; + VALUE cIGraph_motifs; + VALUE cIGraph_sorting; + VALUE cIGraph_filewrite; + VALUE cIGraph_community; + igraph_i_set_attribute_table(&cIGraph_attribute_table); igraph_set_error_handler(cIGraph_error_handler); igraph_set_warning_handler(cIGraph_warning_handler); @@ -226,6 +238,13 @@ void Init_igraph(){ rb_define_const(cIGraph, "TREE_IN", INT2NUM(1)); rb_define_const(cIGraph, "TREE_UNDIRECTED", INT2NUM(2)); + rb_define_const(cIGraph, "VCONN_NEI_ERROR", INT2NUM(0)); + rb_define_const(cIGraph, "VCONN_NEI_INFINITY", INT2NUM(1)); + rb_define_const(cIGraph, "VCONN_NEI_IGNORE", INT2NUM(2)); + + rb_define_const(cIGraph, "SPINCOMM_UPDATE_SIMPLE", INT2NUM(0)); + rb_define_const(cIGraph, "SPINCOMM_UPDATE_CONFIG", INT2NUM(1)); + rb_define_singleton_method(cIGraph, "adjacency", cIGraph_adjacency, 2); /* in cIGraph_generators_deterministic.c */ rb_define_singleton_method(cIGraph, "star", cIGraph_star, 3); /* in cIGraph_generators_deterministic.c */ rb_define_singleton_method(cIGraph, "lattice", cIGraph_lattice, 4); /* in cIGraph_generators_deterministic.c */ @@ -348,52 +367,128 @@ void Init_igraph(){ rb_define_method(cIGraph, "cocitation", cIGraph_cocitation, 1); /* in cIGraph_other_ops.c */ rb_define_method(cIGraph, "get_adjacency", cIGraph_get_adjacency, 1); /* in cIGraph_other_ops.c */ - rb_define_method(cIGraph, "cliques", cIGraph_cliques, 2); /* in cIGraph_cliques.c */ - rb_define_method(cIGraph, "largest_cliques", cIGraph_largest_cliques, 0); /* in cIGraph_cliques.c */ - rb_define_method(cIGraph, "maximal_cliques", cIGraph_maximal_cliques, 0); /* in cIGraph_cliques.c */ - rb_define_method(cIGraph, "clique_number", cIGraph_clique_number, 0); /* in cIGraph_cliques.c */ + //cliques + cIGraph_clique = rb_define_module_under(cIGraph, "Cliques"); + rb_include_module(cIGraph, cIGraph_clique); - rb_define_method(cIGraph, "independent_vertex_sets", cIGraph_independent_vertex_sets, 2); /* in cIGraph_independent_vertex_sets.c */ - rb_define_method(cIGraph, "largest_independent_vertex_sets", cIGraph_largest_independent_vertex_sets, 0); /* in cIGraph_independent_vertex_sets.c */ - rb_define_method(cIGraph, "maximal_independent_vertex_sets", cIGraph_maximal_independent_vertex_sets, 0); /* in cIGraph_independent_vertex_sets.c */ - rb_define_method(cIGraph, "independence_number", cIGraph_independence_number, 0); /* in cIGraph_independent_vertex_sets.c */ + rb_define_method(cIGraph_clique, "cliques", cIGraph_cliques, 2); /* in cIGraph_cliques.c */ + rb_define_method(cIGraph_clique, "largest_cliques", cIGraph_largest_cliques, 0); /* in cIGraph_cliques.c */ + rb_define_method(cIGraph_clique, "maximal_cliques", cIGraph_maximal_cliques, 0); /* in cIGraph_cliques.c */ + rb_define_method(cIGraph_clique, "clique_number", cIGraph_clique_number, 0); /* in cIGraph_cliques.c */ - rb_define_method(cIGraph, "isomorphic", cIGraph_isomorphic, 1); /* in cIGraph_isomorphism.c */ - rb_define_method(cIGraph, "isomorphic_vf2", cIGraph_isomorphic_vf2, 1); /* in cIGraph_isomorphism.c */ - rb_define_method(cIGraph, "isoclass", cIGraph_isoclass, 0); /* in cIGraph_isomorphism.c */ - rb_define_method(cIGraph, "isoclass_subgraph", cIGraph_isoclass_subgraph, 1); /* in cIGraph_isomorphism.c */ + //Motifs + cIGraph_indyver = rb_define_module_under(cIGraph, "IndependentVertexSets"); + rb_include_module(cIGraph, cIGraph_indyver); + + rb_define_method(cIGraph_indyver, "independent_vertex_sets", cIGraph_independent_vertex_sets, 2); /* in cIGraph_independent_vertex_sets.c */ + rb_define_method(cIGraph_indyver, "largest_independent_vertex_sets", cIGraph_largest_independent_vertex_sets, 0); /* in cIGraph_independent_vertex_sets.c */ + rb_define_method(cIGraph_indyver, "maximal_independent_vertex_sets", cIGraph_maximal_independent_vertex_sets, 0); /* in cIGraph_independent_vertex_sets.c */ + rb_define_method(cIGraph_indyver, "independence_number", cIGraph_independence_number, 0); /* in cIGraph_independent_vertex_sets.c */ + + //Motifs + cIGraph_isomor = rb_define_module_under(cIGraph, "Isomorphism"); + rb_include_module(cIGraph, cIGraph_isomor); + + rb_define_method(cIGraph_isomor, "isomorphic", cIGraph_isomorphic, 1); /* in cIGraph_isomorphism.c */ + rb_define_method(cIGraph_isomor, "isomorphic_vf2", cIGraph_isomorphic_vf2, 1); /* in cIGraph_isomorphism.c */ + rb_define_method(cIGraph_isomor, "isoclass", cIGraph_isoclass, 0); /* in cIGraph_isomorphism.c */ + rb_define_method(cIGraph_isomor, "isoclass_subgraph", cIGraph_isoclass_subgraph, 1); /* in cIGraph_isomorphism.c */ rb_define_singleton_method(cIGraph, "isoclass_create", cIGraph_isoclass_create, 3); /* in cIGraph_isomorphism.c */ - rb_define_method(cIGraph, "motifs_randesu", cIGraph_motifs_randesu, 2); /* in cIGraph_motif.c */ - rb_define_method(cIGraph, "motifs_randesu_no", cIGraph_motifs_randesu_no, 2); /* in cIGraph_motif.c */ - rb_define_method(cIGraph, "motifs_randesu_estimate", cIGraph_motifs_randesu_estimate, 4); /* in cIGraph_motif.c */ + //Motifs + cIGraph_motifs = rb_define_module_under(cIGraph, "Motifs"); + rb_include_module(cIGraph, cIGraph_motifs); - rb_define_method(cIGraph, "topological_sorting", cIGraph_topological_sorting, 1); /* in cIGraph_topological_sort.c */ + rb_define_method(cIGraph_motifs, "motifs_randesu", cIGraph_motifs_randesu, 2); /* in cIGraph_motif.c */ + rb_define_method(cIGraph_motifs, "motifs_randesu_no", cIGraph_motifs_randesu_no, 2); /* in cIGraph_motif.c */ + rb_define_method(cIGraph_motifs, "motifs_randesu_estimate", cIGraph_motifs_randesu_estimate, 4); /* in cIGraph_motif.c */ + + //File write + cIGraph_sorting = rb_define_module_under(cIGraph, "Sorting"); + rb_include_module(cIGraph, cIGraph_sorting); + + rb_define_method(cIGraph_sorting, "topological_sorting", cIGraph_topological_sorting, 1); /* in cIGraph_topological_sort.c */ + + //File read rb_define_singleton_method(cIGraph, "read_graph_edgelist", cIGraph_read_graph_edgelist, 2); /* in cIGraph_file.c */ - rb_define_singleton_method(cIGraph, "read_graph_graphml", cIGraph_read_graph_graphml, 2); /* in cIGraph_file.c */ - rb_define_singleton_method(cIGraph, "read_graph_pajek", cIGraph_read_graph_pajek, 2); /* in cIGraph_file.c */ - rb_define_method(cIGraph, "write_graph_edgelist", cIGraph_write_graph_edgelist, 1); /* in cIGraph_file.c */ - rb_define_method(cIGraph, "write_graph_graphml", cIGraph_write_graph_graphml, 1); /* in cIGraph_file.c */ - rb_define_method(cIGraph, "write_graph_pajek", cIGraph_write_graph_pajek, 1); /* in cIGraph_file.c */ + rb_define_singleton_method(cIGraph, "read_graph_graphml", cIGraph_read_graph_graphml, 2); /* in cIGraph_file.c */ + rb_define_singleton_method(cIGraph, "read_graph_ncol", cIGraph_read_graph_ncol, 5); /* in cIGraph_file.c */ + rb_define_singleton_method(cIGraph, "read_graph_lgl", cIGraph_read_graph_lgl, 3); /* in cIGraph_file.c */ + rb_define_singleton_method(cIGraph, "read_graph_dimacs", cIGraph_read_graph_dimacs, 2); /* in cIGraph_file.c */ + rb_define_singleton_method(cIGraph, "read_graph_graphdb", cIGraph_read_graph_graphdb, 2); /* in cIGraph_file.c */ + rb_define_singleton_method(cIGraph, "read_graph_gml", cIGraph_read_graph_gml, 1); /* in cIGraph_file.c */ + rb_define_singleton_method(cIGraph, "read_graph_pajek", cIGraph_read_graph_pajek, 2); /* in cIGraph_file.c */ + + //File write + cIGraph_filewrite = rb_define_module_under(cIGraph, "FileWrite"); + rb_include_module(cIGraph, cIGraph_filewrite); - rb_define_method(cIGraph, "layout_random", cIGraph_layout_random, 0); /* in cIGraph_layout.c */ - rb_define_method(cIGraph, "layout_circle", cIGraph_layout_circle, 0); /* in cIGraph_layout.c */ - rb_define_method(cIGraph, "layout_fruchterman_reingold", cIGraph_layout_fruchterman_reingold, 6); /* in cIGraph_layout.c */ - rb_define_method(cIGraph, "layout_kamada_kawai", cIGraph_layout_kamada_kawai, 5); /* in cIGraph_layout.c */ - rb_define_method(cIGraph, "layout_reingold_tilford", cIGraph_layout_reingold_tilford, 1); /* in cIGraph_layout.c */ - rb_define_method(cIGraph, "layout_reingold_tilford_circular", cIGraph_layout_reingold_tilford_circular, 1); /* in cIGraph_layout.c */ - rb_define_method(cIGraph, "layout_grid_fruchterman_reingold", cIGraph_layout_grid_fruchterman_reingold, 7); /* in cIGraph_layout.c */ - rb_define_method(cIGraph, "layout_lgl", cIGraph_layout_lgl, 7); /* in cIGraph_layout.c */ + rb_define_method(cIGraph_filewrite, "write_graph_edgelist", cIGraph_write_graph_edgelist, 1); /* in cIGraph_file.c */ + rb_define_method(cIGraph_filewrite, "write_graph_graphml", cIGraph_write_graph_graphml, 1); /* in cIGraph_file.c */ + rb_define_method(cIGraph_filewrite, "write_graph_gml", cIGraph_write_graph_gml, 1); /* in cIGraph_file.c */ + rb_define_method(cIGraph_filewrite, "write_graph_ncol", cIGraph_write_graph_ncol, 3); /* in cIGraph_file.c */ + rb_define_method(cIGraph_filewrite, "write_graph_lgl", cIGraph_write_graph_lgl, 4); /* in cIGraph_file.c */ + rb_define_method(cIGraph_filewrite, "write_graph_dimacs", cIGraph_write_graph_dimacs, 4); /* in cIGraph_file.c */ + rb_define_method(cIGraph_filewrite, "write_graph_pajek", cIGraph_write_graph_pajek, 1); /* in cIGraph_file.c */ - rb_define_method(cIGraph, "layout_random_3d", cIGraph_layout_random_3d, 0); /* in cIGraph_layout3d.c */ - rb_define_method(cIGraph, "layout_sphere", cIGraph_layout_sphere, 0); /* in cIGraph_layout3d.c */ - rb_define_method(cIGraph, "layout_fruchterman_reingold_3d", cIGraph_layout_fruchterman_reingold_3d, 6); /* in cIGraph_layout3d.c */ - rb_define_method(cIGraph, "layout_kamada_kawai_3d", cIGraph_layout_kamada_kawai_3d, 5); /* in cIGraph_layout3d.c */ + //Layouts + cIGraph_layout = rb_define_module_under(cIGraph, "Layout"); + rb_include_module(cIGraph, cIGraph_layout); + rb_define_method(cIGraph_layout, "layout_random", cIGraph_layout_random, 0); /* in cIGraph_layout.c */ + rb_define_method(cIGraph_layout, "layout_circle", cIGraph_layout_circle, 0); /* in cIGraph_layout.c */ + rb_define_method(cIGraph_layout, "layout_fruchterman_reingold", cIGraph_layout_fruchterman_reingold, 6); /* in cIGraph_layout.c */ + rb_define_method(cIGraph_layout, "layout_kamada_kawai", cIGraph_layout_kamada_kawai, 5); /* in cIGraph_layout.c */ + rb_define_method(cIGraph_layout, "layout_reingold_tilford", cIGraph_layout_reingold_tilford, 1); /* in cIGraph_layout.c */ + rb_define_method(cIGraph_layout, "layout_reingold_tilford_circular", cIGraph_layout_reingold_tilford_circular, 1); /* in cIGraph_layout.c */ + rb_define_method(cIGraph_layout, "layout_grid_fruchterman_reingold", cIGraph_layout_grid_fruchterman_reingold, 7); /* in cIGraph_layout.c */ + rb_define_method(cIGraph_layout, "layout_lgl", cIGraph_layout_lgl, 7); /* in cIGraph_layout.c */ + + rb_define_method(cIGraph_layout, "layout_random_3d", cIGraph_layout_random_3d, 0); /* in cIGraph_layout3d.c */ + rb_define_method(cIGraph_layout, "layout_sphere", cIGraph_layout_sphere, 0); /* in cIGraph_layout3d.c */ + rb_define_method(cIGraph_layout, "layout_fruchterman_reingold_3d", cIGraph_layout_fruchterman_reingold_3d, 6); /* in cIGraph_layout3d.c */ + rb_define_method(cIGraph_layout, "layout_kamada_kawai_3d", cIGraph_layout_kamada_kawai_3d, 5); /* in cIGraph_layout3d.c */ rb_define_singleton_method(cIGraph, "layout_merge_dla", cIGraph_layout_merge_dla, 2); /* in cIGraph_layout.c */ + //Min cuts + cIGraph_mincuts = rb_define_module_under(cIGraph, "MinimumCuts"); + rb_include_module(cIGraph, cIGraph_mincuts); + + rb_define_method(cIGraph_mincuts, "maxflow_value", cIGraph_maxflow_value, 3); /* in cIGraph_min_cuts.c */ + rb_define_method(cIGraph_mincuts, "st_mincut_value", cIGraph_st_mincut_value, 3); /* in cIGraph_min_cuts.c */ + rb_define_method(cIGraph_mincuts, "mincut_value", cIGraph_mincut_value, 1); /* in cIGraph_min_cuts.c */ + rb_define_method(cIGraph_mincuts, "mincut", cIGraph_mincut, 1); /* in cIGraph_min_cuts.c */ + + //Connectivity + cIGraph_connectivity = rb_define_module_under(cIGraph, "Connectivity"); + rb_include_module(cIGraph, cIGraph_connectivity); + + rb_define_method(cIGraph_connectivity, "st_edge_connectivity", cIGraph_st_edge_connectivity, 2); /* in cIGraph_connectivity.c */ + rb_define_method(cIGraph_connectivity, "edge_connectivity", cIGraph_edge_connectivity, 0); /* in cIGraph_connectivity.c */ + rb_define_method(cIGraph_connectivity, "st_vertex_connectivity", cIGraph_st_vertex_connectivity, 3); /* in cIGraph_connectivity.c */ + rb_define_method(cIGraph_connectivity, "vertex_connectivity", cIGraph_vertex_connectivity, 0); /* in cIGraph_connectivity.c */ + rb_define_method(cIGraph_connectivity, "edge_disjoint_paths", cIGraph_edge_disjoint_paths, 2); /* in cIGraph_connectivity.c */ + rb_define_method(cIGraph_connectivity, "vertex_disjoint_paths", cIGraph_vertex_disjoint_paths, 2); /* in cIGraph_connectivity.c */ + rb_define_method(cIGraph_connectivity, "adhesion", cIGraph_adhesion, 0); /* in cIGraph_connectivity.c */ + rb_define_method(cIGraph_connectivity, "cohesion", cIGraph_cohesion, 0); /* in cIGraph_connectivity.c */ + + //Community + cIGraph_community = rb_define_module_under(cIGraph, "Community"); + rb_include_module(cIGraph, cIGraph_community); + + rb_define_method(cIGraph_community, "modularity", cIGraph_modularity, 1); /* in cIGraph_community.c */ + rb_define_method(cIGraph_community, "community_to_membership", cIGraph_community_to_membership, 2); /* in cIGraph_community.c */ + rb_define_method(cIGraph_community, "community_spinglass", cIGraph_community_spinglass, 8); /* in cIGraph_community.c */ + rb_define_method(cIGraph_community, "community_spinglass_single", cIGraph_community_spinglass_single, 5); /* in cIGraph_community.c */ + rb_define_method(cIGraph_community, "community_leading_eigenvector", cIGraph_community_leading_eigenvector, 1); /* in cIGraph_community.c */ + rb_define_method(cIGraph_community, "community_leading_eigenvector_naive", cIGraph_community_leading_eigenvector_naive, 1); /* in cIGraph_community.c */ + rb_define_method(cIGraph_community, "community_leading_eigenvector_step", cIGraph_community_leading_eigenvector_step, 2); /* in cIGraph_community.c */ //rb_define_method(cIGraph_community, "community_walktrap", cIGraph_community_walktrap, 2); /* in cIGraph_community.c */ + //rb_define_method(cIGraph_community, "community_edge_betweenness", cIGraph_community_edge_betweenness, 1); /* in cIGraph_community.c */ + //rb_define_method(cIGraph_community, "community_eb_get_merges", cIGraph_community_eb_get_merges, 1); /* in cIGraph_community.c */ + //rb_define_method(cIGraph_community, "community_fastgreedy", cIGraph_community_fastgreedy, 0); /* in cIGraph_community.c */ + //Matrix class cIGraphMatrix = rb_define_class("IGraphMatrix", rb_cObject); diff --git a/ext/cIGraph.h b/ext/cIGraph.h index f280a6e..7980b5d 100644 --- a/ext/cIGraph.h +++ b/ext/cIGraph.h @@ -200,8 +200,17 @@ VALUE cIGraph_motifs_randesu_estimate(VALUE self, VALUE size, VALUE cuts, //File handling VALUE cIGraph_read_graph_edgelist (VALUE self, VALUE file, VALUE mode); VALUE cIGraph_write_graph_edgelist(VALUE self, VALUE file); +VALUE cIGraph_read_graph_ncol (VALUE self, VALUE file, VALUE predefnames, VALUE names, VALUE weights, VALUE directed); +VALUE cIGraph_write_graph_ncol (VALUE self, VALUE file, VALUE names, VALUE weights); +VALUE cIGraph_read_graph_lgl (VALUE self, VALUE file, VALUE names, VALUE weights); +VALUE cIGraph_write_graph_lgl (VALUE self, VALUE file, VALUE names, VALUE weights, VALUE isolates); +VALUE cIGraph_read_graph_dimacs (VALUE self, VALUE file, VALUE directed); +VALUE cIGraph_write_graph_dimacs (VALUE self, VALUE file, VALUE source, VALUE target, VALUE capacity); +VALUE cIGraph_read_graph_graphdb (VALUE self, VALUE file, VALUE directed); VALUE cIGraph_read_graph_graphml (VALUE self, VALUE file, VALUE index); VALUE cIGraph_write_graph_graphml (VALUE self, VALUE file); +VALUE cIGraph_read_graph_gml (VALUE self, VALUE file); +VALUE cIGraph_write_graph_gml (VALUE self, VALUE file); VALUE cIGraph_read_graph_pajek (VALUE self, VALUE file); VALUE cIGraph_write_graph_pajek (VALUE self, VALUE file); @@ -260,6 +269,45 @@ VALUE cIGraph_layout_kamada_kawai_3d (VALUE self, VALUE cIGraph_layout_merge_dla(VALUE self, VALUE graphs, VALUE layouts); +//Min cuts +VALUE cIGraph_maxflow_value (VALUE self, VALUE source, VALUE target, VALUE capacity); +VALUE cIGraph_st_mincut_value(VALUE self, VALUE source, VALUE target, VALUE capacity); +VALUE cIGraph_mincut_value (VALUE self, VALUE capacity); +VALUE cIGraph_mincut (VALUE self, VALUE capacity); + +//Connectivity +VALUE cIGraph_st_edge_connectivity (VALUE self, VALUE source, VALUE target); +VALUE cIGraph_edge_connectivity (VALUE self); +VALUE cIGraph_st_vertex_connectivity(VALUE self, VALUE source, VALUE target, VALUE neighbours); +VALUE cIGraph_vertex_connectivity (VALUE self); +VALUE cIGraph_edge_disjoint_paths (VALUE self, VALUE source, VALUE target); +VALUE cIGraph_vertex_disjoint_paths (VALUE self, VALUE source, VALUE target); +VALUE cIGraph_adhesion(VALUE self); +VALUE cIGraph_cohesion(VALUE self); + +//Community +VALUE cIGraph_modularity (VALUE self, VALUE groups); +VALUE cIGraph_community_to_membership (VALUE self, VALUE merge, + VALUE steps); +VALUE cIGraph_community_spinglass (VALUE self, VALUE weights, + VALUE spins, + VALUE parupdate, + VALUE starttemp, + VALUE stoptemp, + VALUE coolfact, + VALUE update_rule, + VALUE gamma); +VALUE cIGraph_community_spinglass_single (VALUE self, VALUE weights, + VALUE vertex, + VALUE spins, + VALUE update_rule, + VALUE gamma); +VALUE cIGraph_community_leading_eigenvector (VALUE self, VALUE steps); +VALUE cIGraph_community_leading_eigenvector_naive(VALUE self, VALUE steps); +VALUE cIGraph_community_leading_eigenvector_step (VALUE self, + VALUE membership, + VALUE steps); + //Attributes int cIGraph_attribute_init(igraph_t *graph, igraph_vector_ptr_t *attr); diff --git a/ext/cIGraph_attribute_handler.c b/ext/cIGraph_attribute_handler.c index 9d7cace..4423a4c 100644 --- a/ext/cIGraph_attribute_handler.c +++ b/ext/cIGraph_attribute_handler.c @@ -497,9 +497,9 @@ igraph_bool_t cIGraph_attribute_has_attr(const igraph_t *graph, VALUE obj; switch (type) { - case IGRAPH_ATTRIBUTE_GRAPH: attrnum=0; break; - case IGRAPH_ATTRIBUTE_VERTEX: attrnum=1; break; - case IGRAPH_ATTRIBUTE_EDGE: attrnum=2; break; + case IGRAPH_ATTRIBUTE_GRAPH: attrnum = 2; break; + case IGRAPH_ATTRIBUTE_VERTEX: attrnum = 0; break; + case IGRAPH_ATTRIBUTE_EDGE: attrnum = 1; break; default: return 0; break; } @@ -507,14 +507,14 @@ igraph_bool_t cIGraph_attribute_has_attr(const igraph_t *graph, if (attrnum != 2) obj = RARRAY(obj)->ptr[0]; - if(rb_funcall(obj,rb_intern("include?"), 1, rb_str_new2(name))){ + if(TYPE(obj) == T_HASH && rb_funcall(obj,rb_intern("include?"), 1, rb_str_new2(name))){ res = 1; } #ifdef DEBUG printf("Leaving cIGraph_attribute_has_attr\n"); #endif - + return res; } @@ -533,9 +533,9 @@ int cIGraph_attribute_get_type(const igraph_t *graph, VALUE val; switch (elemtype) { - case IGRAPH_ATTRIBUTE_GRAPH: attrnum=0; break; - case IGRAPH_ATTRIBUTE_VERTEX: attrnum=1; break; - case IGRAPH_ATTRIBUTE_EDGE: attrnum=2; break; + case IGRAPH_ATTRIBUTE_GRAPH: attrnum = 2; break; + case IGRAPH_ATTRIBUTE_VERTEX: attrnum = 0; break; + case IGRAPH_ATTRIBUTE_EDGE: attrnum = 1; break; default: return 0; break; } @@ -543,7 +543,9 @@ int cIGraph_attribute_get_type(const igraph_t *graph, if (attrnum != 2) obj = RARRAY(obj)->ptr[0]; - if(rb_funcall(obj,rb_intern("includes"), rb_str_new2(name))){ + rb_funcall(obj,rb_intern("include?"), 1, rb_str_new2(name)); + + if(rb_funcall(obj,rb_intern("include?"), 1, rb_str_new2(name))){ val = rb_hash_aref(obj,rb_str_new2(name)); if (TYPE(val) == T_STRING){ *type = IGRAPH_ATTRIBUTE_STRING; @@ -552,7 +554,9 @@ int cIGraph_attribute_get_type(const igraph_t *graph, } else { *type = IGRAPH_ATTRIBUTE_PY_OBJECT; } - } + } else { + *type = IGRAPH_ATTRIBUTE_PY_OBJECT; + } #ifdef DEBUG printf("Leaving cIGraph_attribute_get_type\n"); @@ -736,7 +740,7 @@ int cIGraph_get_string_edge_attr(const igraph_t *graph, #endif VALUE array = ((VALUE*)graph->attr)[1]; - VALUE val, vertex; + VALUE val, edge; igraph_eit_t it; int i=0; @@ -745,10 +749,16 @@ int cIGraph_get_string_edge_attr(const igraph_t *graph, IGRAPH_CHECK(igraph_strvector_resize(value, IGRAPH_EIT_SIZE(it))); while(!IGRAPH_EIT_END(it)){ - vertex = RARRAY(array)->ptr[(int)IGRAPH_EIT_GET(it)]; - val = rb_hash_aref(vertex,rb_str_new2(name)); + edge = RARRAY(array)->ptr[(int)IGRAPH_EIT_GET(it)]; + + val = rb_hash_aref(edge,rb_str_new2(name)); + if(val == Qnil) val = rb_str_new2(""); + + //Fix for floats when required by ncol write + val = rb_funcall(val,rb_intern("to_s"),0); + igraph_strvector_set(value,i,RSTRING(val)->ptr); IGRAPH_EIT_NEXT(it); i++; diff --git a/ext/cIGraph_file.c b/ext/cIGraph_file.c index 9426af2..de221a1 100644 --- a/ext/cIGraph_file.c +++ b/ext/cIGraph_file.c @@ -89,6 +89,414 @@ VALUE cIGraph_write_graph_edgelist(VALUE self, VALUE file){ } +VALUE cIGraph_read_graph_ncol(VALUE self, VALUE file, VALUE predefnames, VALUE names, VALUE weights, VALUE directed){ + + VALUE string; + FILE *stream; + VALUE new_graph; + VALUE v_ary; + VALUE e_ary; + VALUE new_ary; + + igraph_t *graph; + igraph_strvector_t names_vec; + igraph_bool_t directed_b = 0; + igraph_bool_t weights_b = 0; + igraph_bool_t names_b = 0; + + int i; + + if(directed) + directed_b = 1; + + if(names) + names_b = 1; + + if(weights) + weights_b = 1; + + new_graph = cIGraph_alloc(cIGraph); + Data_Get_Struct(new_graph, igraph_t, graph); + + igraph_strvector_init(&names_vec,RARRAY(predefnames)->len); + + for(i=0;ilen;i++){ + igraph_strvector_set(&names_vec, i, RSTRING(RARRAY(predefnames)->ptr[i])->ptr); + } + + string = rb_funcall(file, rb_intern("read"), 0); + stream = fmemopen(RSTRING(string)->ptr,RSTRING(string)->len, "r"); + + if (RARRAY(predefnames)->len == 0){ + igraph_read_graph_ncol(graph, stream, NULL, names_b, weights_b, directed_b); + } else { + igraph_read_graph_ncol(graph, stream, &names_vec, names_b, weights_b, directed_b); + } + + fclose(stream); + + //Convert the Hash of names to Strings instead + if(names){ + v_ary = ((VALUE*)graph->attr)[0]; + new_ary = rb_ary_new(); + for(i=0;ilen;i++){ + rb_ary_push(new_ary, rb_hash_aref(RARRAY(v_ary)->ptr[i], rb_str_new2("name"))); + } + ((VALUE*)graph->attr)[0] = new_ary; + } + //Convert the Hash of weights to floats instead + if(weights){ + e_ary = ((VALUE*)graph->attr)[1]; + new_ary = rb_ary_new(); + for(i=0;ilen;i++){ + rb_ary_push(new_ary, rb_hash_aref(RARRAY(e_ary)->ptr[i], rb_str_new2("weight"))); + } + ((VALUE*)graph->attr)[1] = new_ary; + } + + igraph_strvector_destroy(&names_vec); + + return new_graph; + +} + +VALUE cIGraph_write_graph_ncol(VALUE self, VALUE file, VALUE names, VALUE weights){ + + char *buf; + size_t size; + FILE *stream; + igraph_t *graph; + int e, i; + + VALUE v_ary; + VALUE e_ary; + VALUE new_v_ary; + VALUE new_e_ary; + + VALUE vertex_h; + VALUE edge_h; + + char *weights_b = "0"; + char *names_b = "0"; + + if(names) + names_b = "name"; + + if(weights) + weights_b = "weight"; + + Data_Get_Struct(self, igraph_t, graph); + + //Convert each object to it's String representation and each edge to + //it's Float + if(names){ + v_ary = ((VALUE*)graph->attr)[0]; + new_v_ary = rb_ary_new(); + for(i=0;ilen;i++){ + vertex_h = rb_hash_new(); + rb_hash_aset(vertex_h, rb_str_new2("name"), StringValue(RARRAY(v_ary)->ptr[i])); + rb_ary_push(new_v_ary, vertex_h); + } + ((VALUE*)graph->attr)[0] = new_v_ary; + } + if(weights){ + e_ary = ((VALUE*)graph->attr)[1]; + new_e_ary = rb_ary_new(); + for(i=0;ilen;i++){ + edge_h = rb_hash_new(); + rb_hash_aset(edge_h, rb_str_new2("weight"), rb_funcall(RARRAY(e_ary)->ptr[i],rb_intern("to_f"),0)); + rb_ary_push(new_e_ary, edge_h); + } + ((VALUE*)graph->attr)[1] = new_e_ary; + } + + stream = open_memstream(&buf,&size); + e = igraph_write_graph_ncol(graph, stream, names_b, weights_b); + fflush(stream); + rb_funcall(file, rb_intern("write"), 1, rb_str_new(buf,size)); + fclose(stream); + + //Replace initital vertices and edges + if(names){ + ((VALUE*)graph->attr)[0] = v_ary; + } + if(weights){ + ((VALUE*)graph->attr)[0] = e_ary; + } + + return e; + +} + +VALUE cIGraph_read_graph_lgl(VALUE self, VALUE file, VALUE names, VALUE weights){ + + VALUE string; + FILE *stream; + VALUE new_graph; + VALUE v_ary; + VALUE e_ary; + VALUE new_ary; + + igraph_t *graph; + igraph_bool_t weights_b = 0; + igraph_bool_t names_b = 0; + + int i; + + if(names) + names_b = 1; + + if(weights) + weights_b = 1; + + new_graph = cIGraph_alloc(cIGraph); + Data_Get_Struct(new_graph, igraph_t, graph); + + string = rb_funcall(file, rb_intern("read"), 0); + stream = fmemopen(RSTRING(string)->ptr,RSTRING(string)->len, "r"); + + igraph_read_graph_lgl(graph, stream, names_b, weights_b); + + fclose(stream); + + //Convert the Hash of names to Strings instead + if(names){ + v_ary = ((VALUE*)graph->attr)[0]; + new_ary = rb_ary_new(); + for(i=0;ilen;i++){ + rb_ary_push(new_ary, rb_hash_aref(RARRAY(v_ary)->ptr[i], rb_str_new2("name"))); + } + ((VALUE*)graph->attr)[0] = new_ary; + } + //Convert the Hash of weights to floats instead + if(weights){ + e_ary = ((VALUE*)graph->attr)[1]; + new_ary = rb_ary_new(); + for(i=0;ilen;i++){ + rb_ary_push(new_ary, rb_hash_aref(RARRAY(e_ary)->ptr[i], rb_str_new2("weight"))); + } + ((VALUE*)graph->attr)[1] = new_ary; + } + + return new_graph; + +} + +VALUE cIGraph_write_graph_lgl(VALUE self, VALUE file, VALUE names, VALUE weights, VALUE isolates){ + + char *buf; + size_t size; + FILE *stream; + igraph_t *graph; + int e, i; + + VALUE v_ary; + VALUE e_ary; + VALUE new_v_ary; + VALUE new_e_ary; + + VALUE vertex_h; + VALUE edge_h; + + char *weights_b = "0"; + char *names_b = "0"; + + igraph_bool_t isolates_b; + + if(names) + names_b = "name"; + + if(weights) + weights_b = "weight"; + + if(isolates) + isolates_b = 1; + + Data_Get_Struct(self, igraph_t, graph); + + //Convert each object to it's String representation and each edge to + //it's Float + if(names){ + v_ary = ((VALUE*)graph->attr)[0]; + new_v_ary = rb_ary_new(); + for(i=0;ilen;i++){ + vertex_h = rb_hash_new(); + rb_hash_aset(vertex_h, rb_str_new2("name"), StringValue(RARRAY(v_ary)->ptr[i])); + rb_ary_push(new_v_ary, vertex_h); + } + ((VALUE*)graph->attr)[0] = new_v_ary; + } + if(weights){ + e_ary = ((VALUE*)graph->attr)[1]; + new_e_ary = rb_ary_new(); + for(i=0;ilen;i++){ + edge_h = rb_hash_new(); + rb_hash_aset(edge_h, rb_str_new2("weight"), rb_funcall(RARRAY(e_ary)->ptr[i],rb_intern("to_f"),0)); + rb_ary_push(new_e_ary, edge_h); + } + ((VALUE*)graph->attr)[1] = new_e_ary; + } + + stream = open_memstream(&buf,&size); + e = igraph_write_graph_lgl(graph, stream, names_b, weights_b, isolates); + fflush(stream); + rb_funcall(file, rb_intern("write"), 1, rb_str_new(buf,size)); + fclose(stream); + + //Replace initital vertices and edges + if(names){ + ((VALUE*)graph->attr)[0] = v_ary; + } + if(weights){ + ((VALUE*)graph->attr)[0] = e_ary; + } + + return e; + +} + +VALUE cIGraph_read_graph_dimacs(VALUE self, VALUE file, VALUE directed){ + + VALUE string; + FILE *stream; + VALUE new_graph; + + igraph_integer_t source; + igraph_integer_t target; + igraph_vector_t capacity; + + igraph_t *graph; + igraph_bool_t directed_b = 0; + + igraph_vs_t vs; + igraph_vit_t vit; + + VALUE v_ary; + VALUE g_hsh; + + int i; + int vid; + + if(directed) + directed_b = 1; + + igraph_vector_init(&capacity, 0); + + new_graph = cIGraph_alloc(cIGraph); + Data_Get_Struct(new_graph, igraph_t, graph); + + string = rb_funcall(file, rb_intern("read"), 0); + stream = fmemopen(RSTRING(string)->ptr,RSTRING(string)->len, "r"); + + igraph_read_graph_dimacs(graph, stream, &source, &target, &capacity, directed_b); + + fclose(stream); + + igraph_vs_all(&vs); + igraph_vit_create(graph, vs, &vit); + + //Push Integer onto vertex array + v_ary = ((VALUE*)graph->attr)[0]; + + while (!IGRAPH_VIT_END(vit)) { + vid = IGRAPH_VIT_GET(vit); + rb_ary_push(v_ary,INT2NUM(vid)); + IGRAPH_VIT_NEXT(vit); + } + + g_hsh = ((VALUE*)graph->attr)[2]; + + rb_hash_aset(g_hsh, rb_str_new2("source"), INT2NUM(source)); + rb_hash_aset(g_hsh, rb_str_new2("target"), INT2NUM(target)); + rb_hash_aset(g_hsh, rb_str_new2("capacity"), rb_ary_new()); + + for(i=0;ilen;i++){ + igraph_vector_push_back(&capacity_v,NUM2DBL(RARRAY(capacity)->ptr[i])); + } + + stream = open_memstream(&buf,&size); + e = igraph_write_graph_dimacs(graph, stream, NUM2INT(source), NUM2INT(target), &capacity_v); + fflush(stream); + rb_funcall(file, rb_intern("write"), 1, rb_str_new(buf,size)); + fclose(stream); + + return e; + +} + +VALUE cIGraph_read_graph_graphdb(VALUE self, VALUE file, VALUE directed){ + + VALUE string; + FILE *stream; + VALUE new_graph; + + VALUE v_ary; + + igraph_t *graph; + igraph_bool_t directed_b = 0; + + igraph_vs_t vs; + igraph_vit_t vit; + + int vid; + + if(directed) + directed_b = 1; + + new_graph = cIGraph_alloc(cIGraph); + Data_Get_Struct(new_graph, igraph_t, graph); + + string = rb_funcall(file, rb_intern("read"), 0); + stream = fmemopen(RSTRING(string)->ptr,RSTRING(string)->len, "r"); + + igraph_read_graph_graphdb(graph, stream, directed_b); + + fclose(stream); + + igraph_vs_all(&vs); + igraph_vit_create(graph, vs, &vit); + + //Push Integer onto vertex array + v_ary = ((VALUE*)graph->attr)[0]; + + while (!IGRAPH_VIT_END(vit)) { + vid = IGRAPH_VIT_GET(vit); + rb_ary_push(v_ary,INT2NUM(vid)); + IGRAPH_VIT_NEXT(vit); + } + + igraph_vit_destroy(&vit); + igraph_vs_destroy(&vs); + + return new_graph; + +} + /* call-seq: * IGraph.read_graph_graphml(file,index) -> IGraph * @@ -155,6 +563,49 @@ VALUE cIGraph_write_graph_graphml(VALUE self, VALUE file){ } +VALUE cIGraph_read_graph_gml(VALUE self, VALUE file){ + + VALUE string; + FILE *stream; + VALUE new_graph; + igraph_t *graph; + + new_graph = cIGraph_alloc(cIGraph); + Data_Get_Struct(new_graph, igraph_t, graph); + + string = rb_funcall(file, rb_intern("read"), 0); + stream = fmemopen(RSTRING(string)->ptr,RSTRING(string)->len, "r"); + + igraph_read_graph_gml(graph, stream); + + fclose(stream); + + return new_graph; + +} + +VALUE cIGraph_write_graph_gml(VALUE self, VALUE file){ + + char *buf; + size_t size; + FILE *stream; + igraph_t *graph; + int e; + + Data_Get_Struct(self, igraph_t, graph); + + stream = open_memstream(&buf,&size); + e = igraph_write_graph_gml(graph, stream, NULL, 0); + fflush(stream); + + rb_funcall(file, rb_intern("write"), 1, rb_str_new(buf,size)); + + fclose(stream); + + return e; + +} + /* call-seq: * IGraph.read_graph_pajek(file) -> IGraph * diff --git a/test/tc_file_read_write.rb b/test/tc_file_read_write.rb index 617c026..489947d 100644 --- a/test/tc_file_read_write.rb +++ b/test/tc_file_read_write.rb @@ -21,6 +21,93 @@ class TestGraph < Test::Unit::TestCase assert_equal "0 1\n2 3\n", s.read end + def test_ncol_read + g = nil + assert_nothing_raised{ + g = IGraph.read_graph_ncol(StringIO.new("0 1\n2 3\n"),[], + false,false,false) + } + assert_instance_of IGraph, g + assert_equal 4, g.vcount + assert g.are_connected?(0,1) + + assert_nothing_raised{ + g = IGraph.read_graph_ncol(StringIO.new("A B\nC D\n"),[], + true,false,false) + } + assert_instance_of IGraph, g + assert_equal 4, g.vcount + assert g.are_connected?('A','B') + + assert_nothing_raised{ + g = IGraph.read_graph_ncol(StringIO.new("A B 1\nC D 2\n"),[], + true,true,false) + } + assert_instance_of IGraph, g + assert_equal 4, g.vcount + assert g.are_connected?('A','B') + assert_equal 1, g['A','B'] + end + + def test_ncol_write + g = IGraph.new(["A","B","C","D"],true,[1,2]) + s = StringIO.new("") + str = g.write_graph_ncol(s,true,true) + s.rewind + assert_equal "A B 1.0\nC D 2.0\n", s.read + end + + def test_lgl_read + g = nil + assert_nothing_raised{ + g = IGraph.read_graph_lgl(StringIO.new("#A\nB\n#C\nD\n"), + false,false) + } + assert_instance_of IGraph, g + assert_equal 4, g.vcount + assert g.are_connected?(0,1) + + assert_nothing_raised{ + g = IGraph.read_graph_lgl(StringIO.new("#A\nB 1\n#C\nD 1\n"), + true,true) + } + assert_instance_of IGraph, g + assert_equal 4, g.vcount + assert g.are_connected?('A','B') + assert_equal 1, g['A','B'] + end + + def test_lgl_write + g = IGraph.new(["A","B","C","D"],true,[1,2]) + s = StringIO.new("") + str = g.write_graph_lgl(s,true,true,false) + s.rewind + assert_equal "# A\nB 1.0\n# C\nD 2.0\n", s.read + end + + def test_dimacs_read + g = nil + assert_nothing_raised{ + s = StringIO.new("c com\np min 4 2\nn 1 s\nn 2 t\na 1 2 1\na 3 4 2\n") + g = IGraph.read_graph_dimacs(s, + false) + } + assert_instance_of IGraph, g + assert_equal 4, g.vcount + assert g.are_connected?(0,1) + assert_equal 0, g.attributes['source'] + assert_equal 1, g.attributes['target'] + assert_equal [1,2], g.attributes['capacity'] + end + + def test_dimacs_write + g = IGraph.new(["A","B","C","D"],true,[1,2]) + s = StringIO.new("") + str = g.write_graph_dimacs(s,0,1,[1,2]) + s.rewind + assert_equal "c created by igraph\np max 4 2\nn 1 s\nn 2 t\na 1 2 1\na 3 4 2\n", s.read + end + def test_graphml_read g = nil g = IGraph.read_graph_graphml(StringIO.new(Graphml),0) @@ -46,6 +133,28 @@ class TestGraph < Test::Unit::TestCase assert_equal Graphml_out, s.read end + def test_gml_read + g = IGraph.read_graph_gml(StringIO.new(Gml)) + assert_instance_of IGraph, g + end + + def test_gml_write + g = IGraph.new([{'id'=>0,'name'=>'a','type' => 4.0}, + {'id'=>1,'name'=>'b','type' => 5}, + {'id'=>2,'type' => 6}, + {'id'=>3,'name'=>'d'}], + true, + [{'eid'=>'e1'}, + {'eid'=>'e2'}]) + g.attributes['date'] = 'Friday' + s = StringIO.new("") + str = g.write_graph_gml(s) + s.rewind + s = s.read + s = s.split(/\n/)[1..-1].join("\n") + assert_equal Gml_out, s + end + def test_pajek_read_write g = nil g = IGraph.read_graph_pajek(StringIO.new(Pajek),0) @@ -158,4 +267,85 @@ awing.org/xmlns/1.0/graphml.xsd"> 2 3 2 } + Gml = %q{graph [ + comment "This is a sample graph" + directed 1 + id 42 + label "Hello, I am a graph" + node [ + id 1 + label "Node 1" + thisIsASampleAttribute 42 + ] + node [ + id 2 + label "node 2" + thisIsASampleAttribute 43 + ] + node [ + id 3 + label "node 3" + thisIsASampleAttribute 44 + ] + edge [ + source 1 + target 2 + label "Edge from node 1 to node 2" + ] + edge [ + source 2 + target 3 + label "Edge from node 2 to node 3" + ] + edge [ + source 3 + target 1 + label "Edge from node 3 to node 1" + ] +] +} + + Gml_out = %q{Version 1 +graph +[ + directed 0 + date "Friday" + node + [ + id 0 + name "a" + type 4 + ] + node + [ + id 1 + name "b" + type 5 + ] + node + [ + id 2 + name "" + type 6 + ] + node + [ + id 3 + name "d" + type nan + ] + edge + [ + source 0 + target 1 + eid "e1" + ] + edge + [ + source 2 + target 3 + eid "e2" + ] +]} + end diff --git a/test/test_all.rb b/test/test_all.rb index cad7e43..0ee300a 100644 --- a/test/test_all.rb +++ b/test/test_all.rb @@ -9,7 +9,9 @@ require 'tc_add_delete' require 'tc_basic_query' require 'tc_basic_properties' require 'tc_centrality' +require 'tc_community' require 'tc_components' +require 'tc_connectivity' require 'tc_copy' require 'tc_cores' require 'tc_dijkstra' @@ -24,6 +26,7 @@ require 'tc_iterators' require 'tc_layout' require 'tc_layout3d' require 'tc_matrix' +require 'tc_mincuts' require 'tc_motif' require 'tc_other_ops' require 'tc_randomisation'