From 3396ee6c787a64a7e0867304b1d9a49ebcb585ad Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Tue, 25 Jun 2013 12:41:12 -0400 Subject: [PATCH 01/73] Adding a #define for INDDGO_INFINITY (used in shortest path calcs) --- lib_graphd/inc/Graph.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib_graphd/inc/Graph.h b/lib_graphd/inc/Graph.h index 90ee634..be6f227 100644 --- a/lib_graphd/inc/Graph.h +++ b/lib_graphd/inc/Graph.h @@ -35,6 +35,8 @@ using namespace std; +#define INDDGO_INFINITY INT_MAX + namespace Graph { class Graph : public GraphInterface { From f3f417c8f455cb3b991e7c2f73641005e23c04af Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Tue, 25 Jun 2013 12:41:35 -0400 Subject: [PATCH 02/73] Adding avg shortest path length calculation; updating djikstra stuff to use INDDGO_INFINITY --- lib_graphd/inc/GraphProperties.h | 5 +++++ lib_graphd/src/GraphProperties.cpp | 26 +++++++++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/lib_graphd/inc/GraphProperties.h b/lib_graphd/inc/GraphProperties.h index d7d860f..4990835 100644 --- a/lib_graphd/inc/GraphProperties.h +++ b/lib_graphd/inc/GraphProperties.h @@ -112,6 +112,11 @@ namespace Graph { */ void avg_degree(Graph *g, float &ad); + /** + * \brief Calculates the average shortest path length of the specified graph + */ + void avg_path_length(Graph *g, double &pl); + /** * \brief Calculates the degree distribution of the specified graph */ diff --git a/lib_graphd/src/GraphProperties.cpp b/lib_graphd/src/GraphProperties.cpp index c68b805..436d613 100644 --- a/lib_graphd/src/GraphProperties.cpp +++ b/lib_graphd/src/GraphProperties.cpp @@ -686,7 +686,7 @@ namespace Graph { */ void GraphProperties::paths_dijkstra_all(Graph *g, vector< vector > &pAll){ - int inf = INT_MAX; + int inf = INDDGO_INFINITY; int minD = inf; const int n = g->get_num_nodes(); @@ -890,6 +890,30 @@ namespace Graph { ad = (2.0 * E) / V; } + void GraphProperties::avg_path_length(Graph *g, double &pl){ + const int n = g->get_num_nodes(); + const vector< vector > short_paths = g->get_shortest_path_dist_ref(); + double sum = 0; + double intermediate = 0.0; + int i, j; + + #pragma omp parallel for schedule(dynamic, 16) default(none) private(j) reduction(+:sum) + for(i=0; i Date: Tue, 25 Jun 2013 12:42:05 -0400 Subject: [PATCH 03/73] Adding avg_path_length to graph_stats driver --- util/src/graph_stats.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/util/src/graph_stats.cpp b/util/src/graph_stats.cpp index 75590d5..bb44cf1 100644 --- a/util/src/graph_stats.cpp +++ b/util/src/graph_stats.cpp @@ -41,7 +41,7 @@ void print_time(string prefix, ORB_t start, ORB_t end){ cout << prefix + ": " << ORB_seconds(end, start) << "\n"; } -const string allowed_methods ("edge_density,avg_degree,degree_dist,global_cc,avg_cc,local_ccs,shortest_paths,assortativity,eccentricity,eccentricity_dist,expansion"); +const string allowed_methods ("edge_density,avg_degree,degree_dist,global_cc,avg_cc,local_ccs,shortest_paths,assortativity,eccentricity,eccentricity_dist,expansion,avg_shortest_path"); /** * Creates a map from a comma-separated string @@ -151,6 +151,8 @@ int main(int argc, char **argv){ vector local_cc, freq_ecc, norm_hops; float edge_density, avg_degree; vector deg_dist, ecc; + double avg_path_length; + vector< vector > shortest_path_distances; outfile.open(outfilename.c_str()); @@ -248,6 +250,14 @@ int main(int argc, char **argv){ ORB_read(t2); print_time("Time(expansion)",t1,t2); } + if(req_methods["avg_shortest_path"] == true){ + cout << "Calculating average shortest path length\n"; + ORB_read(t1); + gp.avg_path_length(&g, avg_path_length); + ORB_read(t2); + print_time("Time(avg_path_length)", t1, t2); + outfile << "avg_path_length " << avg_path_length << endl; + } outfile.close(); exit(0); From bca2a6dfd935c820ae9378ad999958e3aaf0c498 Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Tue, 25 Jun 2013 12:42:57 -0400 Subject: [PATCH 04/73] cleaning up code --- lib_graphd/src/GraphProperties.cpp | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/lib_graphd/src/GraphProperties.cpp b/lib_graphd/src/GraphProperties.cpp index 436d613..dd716ff 100644 --- a/lib_graphd/src/GraphProperties.cpp +++ b/lib_graphd/src/GraphProperties.cpp @@ -897,22 +897,18 @@ namespace Graph { double intermediate = 0.0; int i, j; - #pragma omp parallel for schedule(dynamic, 16) default(none) private(j) reduction(+:sum) - for(i=0; i Date: Thu, 27 Jun 2013 11:14:23 -0400 Subject: [PATCH 05/73] fixing icc error --- lib_graphd/src/GraphReader.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib_graphd/src/GraphReader.cpp b/lib_graphd/src/GraphReader.cpp index 1f25781..328ff31 100644 --- a/lib_graphd/src/GraphReader.cpp +++ b/lib_graphd/src/GraphReader.cpp @@ -136,6 +136,7 @@ namespace Graph { } } } + return 0; } // read_adjlist /** From bc963b78aec4d8676516cc595b579f333b0910fb Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Thu, 27 Jun 2013 11:27:32 -0400 Subject: [PATCH 06/73] output the input filename in the stats file --- util/src/graph_stats.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/util/src/graph_stats.cpp b/util/src/graph_stats.cpp index bb44cf1..3a60367 100644 --- a/util/src/graph_stats.cpp +++ b/util/src/graph_stats.cpp @@ -169,8 +169,9 @@ int main(int argc, char **argv){ ORB_read(t2); print_time("Time(make_simple)", t1, t2); - outfile << "num_nodes " << g.get_num_nodes() << "\n"; - outfile << "num_edges " << g.get_num_edges() << "\n"; + outfile << "filename" << infile << endl; + outfile << "num_nodes " << g.get_num_nodes() << endl; + outfile << "num_edges " << g.get_num_edges() << endl; if(req_methods["edge_density"] == true){ cout << "Calculating edge density\n"; From 8e6bdf13b7abd3de7af530a420a4951c820ac23f Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Thu, 27 Jun 2013 12:10:06 -0400 Subject: [PATCH 07/73] change \n to endl for better monitoring of progress during batch jobs --- util/src/graph_stats.cpp | 58 ++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/util/src/graph_stats.cpp b/util/src/graph_stats.cpp index 3a60367..7a9a4b9 100644 --- a/util/src/graph_stats.cpp +++ b/util/src/graph_stats.cpp @@ -38,7 +38,7 @@ using namespace std; void print_time(string prefix, ORB_t start, ORB_t end){ - cout << prefix + ": " << ORB_seconds(end, start) << "\n"; + cout << prefix + ": " << ORB_seconds(end, start) << endl; } const string allowed_methods ("edge_density,avg_degree,degree_dist,global_cc,avg_cc,local_ccs,shortest_paths,assortativity,eccentricity,eccentricity_dist,expansion,avg_shortest_path"); @@ -57,9 +57,9 @@ void create_map(string list, map &outmap){ } void print_usage(char **argv){ - cerr << "Usage: " << argv[0] << " [-h] -i infile [-t input-type] [-o outfile] [-p output-prefix] [-m methods]\n"; - cerr << "Allowed methods: " << allowed_methods << "\n"; - cerr << "Input type should be one of: edge, adjlist, adjmatrix, dimacs\n"; + cerr << "Usage: " << argv[0] << " [-h] -i infile [-t input-type] [-o outfile] [-p output-prefix] [-m methods]" << endl; + cerr << "Allowed methods: " << allowed_methods << endl; + cerr << "Input type should be one of: edge, adjlist, adjmatrix, dimacs" << endl; } /** @@ -118,10 +118,10 @@ int main(int argc, char **argv){ // we'd like higher precision when printing values std::cout.precision(10); - cout << "done parsing options\n"; - cout << "Input file: " << infile << "\n"; - cout << "Input type: " << intype << "\n"; - cout << "Output file: " << outfilename << "\n"; + cout << "done parsing options" << endl; + cout << "Input file: " << infile << endl; + cout << "Input type: " << intype << endl; + cout << "Output file: " << outfilename << endl; cout << "Methods :"; for(map::iterator it = req_methods.begin(); it != req_methods.end(); ++it){ cout << " " << it->first; @@ -129,8 +129,8 @@ int main(int argc, char **argv){ cerr << "Error: " << it->first << " is not a valid method! " << endl; } } - cout << "\n"; - cout << "Calibrating timers\n"; + cout << endl; + cout << "Calibrating timers" << endl; ORB_calibrate(); // let's do some calculations @@ -139,7 +139,7 @@ int main(int argc, char **argv){ Graph::GraphReader gr; Graph::GraphProperties gp; - cout << "Reading graph\n"; + cout << "Reading graph" << endl; ORB_read(t1); if(gr.read_graph(&g, infile, intype, false) == -1){ exit(1); @@ -157,13 +157,13 @@ int main(int argc, char **argv){ outfile.open(outfilename.c_str()); if(!outfile.is_open()){ - cerr << "Error opening " << outfilename << " for writing, exiting\n"; + cerr << "Error opening " << outfilename << " for writing, exiting" << endl; exit(1); } outfile.precision(16); - cout << "Simplifying graph\n"; + cout << "Simplifying graph" << endl; ORB_read(t1); gp.make_simple(&g); ORB_read(t2); @@ -174,85 +174,85 @@ int main(int argc, char **argv){ outfile << "num_edges " << g.get_num_edges() << endl; if(req_methods["edge_density"] == true){ - cout << "Calculating edge density\n"; + cout << "Calculating edge density" << endl; ORB_read(t1); gp.edge_density(&g, edge_density); ORB_read(t2); print_time("Time(edge_density)", t1, t2); - outfile << "edge_density " << edge_density << "\n"; + outfile << "edge_density " << edge_density << endl; } if(req_methods["avg_degree"] == true){ - cout << "Calculating average degree\n"; + cout << "Calculating average degree" << endl; ORB_read(t1); gp.avg_degree(&g, avg_degree); ORB_read(t2); print_time("Time(average_degree)", t1, t2); - outfile << "avg_degree " << avg_degree << "\n"; + outfile << "avg_degree " << avg_degree << endl; } if(req_methods["degree_dist"] == true){ - cout << "Calculating degree distribution\n"; + cout << "Calculating degree distribution" << endl; ORB_read(t1); gp.deg_dist(&g, deg_dist); ORB_read(t2); print_time("Time(degree_distribution)", t1, t2); string of = outprefix + ".deg_dist"; write_degree_distribution(of, deg_dist); - outfile << "degree_distribution " << of << "\n"; + outfile << "degree_distribution " << of << endl; } if(req_methods["assortativity"] == true){ - cout << "Calculating degree assortativity\n"; + cout << "Calculating degree assortativity" << endl; ORB_read(t1); gp.deg_assortativity(&g, assortativity); ORB_read(t2); print_time("Time(assortativity)", t1, t2); - outfile << "assortativity " << assortativity << "\n"; + outfile << "assortativity " << assortativity << endl; } if((req_methods["global_cc"] == true) || (req_methods["local_ccs"] == true) || (req_methods["avg_cc"] == true)){ - cout << "Calculating clustering coefficients\n"; + cout << "Calculating clustering coefficients" << endl; ORB_read(t1); gp.clustering_coefficients(&g, global_cc, avg_cc, local_cc); ORB_read(t2); print_time("Time(clustering_coeffecients)", t1, t2); if(req_methods["global_cc"] == true){ - outfile << "global_clustering_coefficient " << global_cc << "\n"; + outfile << "global_clustering_coefficient " << global_cc << endl; } if(req_methods["avg_cc"] == true){ - outfile << "average_clustering_coefficient " << avg_cc << "\n"; + outfile << "average_clustering_coefficient " << avg_cc << endl; } if(req_methods["local_ccs"] == true){ } } if(req_methods["shortest_paths"] == true){ - cout << "Calculating shortest paths\n"; + cout << "Calculating shortest paths" << endl; ORB_read(t1); gp.paths_dijkstra_all(&g, shortest_path_distances); ORB_read(t2); print_time("Time(shortest_paths_dijkstra)", t1, t2); } if(req_methods["eccentricity"] == true){ - cout << "Calculating eccentricities\n"; + cout << "Calculating eccentricities" << endl; ORB_read(t1); gp.eccentricity(&g, ecc); ORB_read(t2); print_time("Time(eccentricity)",t1,t2); } if(req_methods["eccentricity_dist"] == true){ - cout << "Calculating distribution of eccentricities\n"; + cout << "Calculating distribution of eccentricities" << endl; ORB_read(t1); gp.eccentricity_dist(&g, ecc, freq_ecc); ORB_read(t2); print_time("Time(eccentricity distribution)",t1,t2); } if(req_methods["expansion"] == true){ - cout << "Calculating normalized expansion (distance distribution) - no self loops allowed\n"; + cout << "Calculating normalized expansion (distance distribution) - no self loops allowed" << endl; ORB_read(t1); gp.expansion(&g, norm_hops); ORB_read(t2); print_time("Time(expansion)",t1,t2); } if(req_methods["avg_shortest_path"] == true){ - cout << "Calculating average shortest path length\n"; + cout << "Calculating average shortest path length" << endl; ORB_read(t1); gp.avg_path_length(&g, avg_path_length); ORB_read(t2); From 68c4a5d2e60e489ef80825860e06cb698e7ad319 Mon Sep 17 00:00:00 2001 From: Matt Baker Date: Tue, 2 Jul 2013 11:13:03 -0400 Subject: [PATCH 08/73] Add Petsc and Slepc options to build system --- lib_graphd/src/Makefile | 4 ++-- lib_ptreed/Makefile | 4 ++-- lib_treed/Makefile | 4 ++-- make.inc.parallel | 46 ++++++++++++++++++++++++++++++++++++----- max_wis/Makefile | 4 ++-- util/Makefile | 4 ++-- viz/Makefile | 4 ++-- 7 files changed, 53 insertions(+), 17 deletions(-) diff --git a/lib_graphd/src/Makefile b/lib_graphd/src/Makefile index 3f42b36..79b144a 100644 --- a/lib_graphd/src/Makefile +++ b/lib_graphd/src/Makefile @@ -10,9 +10,9 @@ LIBNAME = libgraphd.a GVIZ=../bin/gviz # include directories -INCLUDES = -I../inc/ -I/usr/local/include $(METIS_INCLUDES) $(SSPARSE_INCDIR) $(PARMETIS_INCDIR) +INCLUDES = -I../inc/ -I/usr/local/include $(METIS_INCLUDES) $(SSPARSE_INCDIR) $(PARMETIS_INCDIR) $(PETSC_INCDIR) $(SLEPC_INCDIR) # libraries -LIBS = -L/usr/local/lib $(INDDGO_LIB) $(SSPARSE_LIB) -lm $(METIS_LIB) $(PARMETIS_LIB) +LIBS = -L/usr/local/lib $(INDDGO_LIB) $(SSPARSE_LIB) -lm $(METIS_LIB) $(PARMETIS_LIB) $(PETSC_LIB) $(SLEPC_LIB) # source SRC := Log.cpp GraphReader.cpp Node.cpp \ GraphCreator.cpp GraphCreatorFile.cpp Graph.cpp VertexWeightedGraph.cpp GraphProperties.cpp \ diff --git a/lib_ptreed/Makefile b/lib_ptreed/Makefile index 6c4afc0..fdc9156 100644 --- a/lib_ptreed/Makefile +++ b/lib_ptreed/Makefile @@ -3,9 +3,9 @@ include ../make.inc DOX_DIR = ./doc/ DOXYFILE = ./Doxyfile -INC_DIR= -I./inc -I$(GRAPH)/inc -I$(TREE)/inc $(METIS_INCLUDES) $(SSPARSE_INCDIR) $(UTHASH_INCDIR) $(MADNESS_INCDIR) $(GMP_INCDIR) $(PARMETIS_INCDIR) +INC_DIR= -I./inc -I$(GRAPH)/inc -I$(TREE)/inc $(METIS_INCLUDES) $(SSPARSE_INCDIR) $(UTHASH_INCDIR) $(MADNESS_INCDIR) $(GMP_INCDIR) $(PARMETIS_INCDIR) $(SLEPC_INCDIR) $(PETSC_INCDIR) -LIBS = -lm $(INDDGO_LIB) -ltreed -lgraphd $(METIS_LIB) $(SSPARSE_LIB) $(ARPACK_LIB) $(MPILIBS) $(MADNESS_LIB) $(GMP_LIB) $(PARMETIS_LIB) +LIBS = -lm $(INDDGO_LIB) -ltreed -lgraphd $(METIS_LIB) $(SSPARSE_LIB) $(ARPACK_LIB) $(MPILIBS) $(MADNESS_LIB) $(GMP_LIB) $(PARMETIS_LIB) $(SLEPC_LIB) $(PETSC_LIB) PTD_LIB_NAME = libptreed.a diff --git a/lib_treed/Makefile b/lib_treed/Makefile index cabb11e..9867a07 100644 --- a/lib_treed/Makefile +++ b/lib_treed/Makefile @@ -4,9 +4,9 @@ include ../make.inc DOX_DIR = ./doc/ DOXYFILE = ./Doxyfile -INC_DIR= -I./inc -I$(GRAPH)/inc $(METIS_INCLUDES) $(SSPARSE_INCDIR) $(UTHASH_INCDIR) $(MADNESS_INCDIR) $(GMP_INCDIR) $(PARMETIS_INCDIR) +INC_DIR= -I./inc -I$(GRAPH)/inc $(METIS_INCLUDES) $(SSPARSE_INCDIR) $(UTHASH_INCDIR) $(MADNESS_INCDIR) $(GMP_INCDIR) $(PARMETIS_INCDIR) $(SLEPC_INCDIR) $(PETSC_INCDIR) -LIBS = -L./lib -lm -L$(GRAPH)/lib -lgraphd $(INDDGO_LIB) $(METIS_LIB) $(SSPARSE_LIB) $(ARPACK_LIB) $(MPILIBS) $(MADNESS_LIB) $(GMP_LIB) $(PARMETIS_LIB) +LIBS = -L./lib -lm -L$(GRAPH)/lib -lgraphd $(INDDGO_LIB) $(METIS_LIB) $(SSPARSE_LIB) $(ARPACK_LIB) $(MPILIBS) $(MADNESS_LIB) $(GMP_LIB) $(PARMETIS_LIB) $(SLEPC_LIB) $(PETSC_LIB) TD_LIB_NAME = libtreed.a diff --git a/make.inc.parallel b/make.inc.parallel index a4d72de..6b8e960 100644 --- a/make.inc.parallel +++ b/make.inc.parallel @@ -26,6 +26,9 @@ HAS_METIS = 1 HAS_IGRAPH = 0 HAS_GMP = 0 HAS_GTEST = 0 +#Slepc is needed if you want eigen values +HAS_PETSC = 1 +HAS_SLEPC = 1 # Set whether serial or parallel version is desired for WIS. IS_PARALLEL = 1 HAS_MADNESS = 1 @@ -42,19 +45,22 @@ LOG_ENABLED = 1 ARPACK = #directory containing SuiteSparse installation. This includes AMD and SuiteSparse_config/UFconfig. -SUITESPARSE = #FILL IN +SUITESPARSE = #NOTE: the build directory is usually platform dependent. -PARMETIS_SRC_DIR = #FILL IN -PARMETIS_LIB_DIR = #FILL IN +PARMETIS_SRC_DIR = +PARMETIS_LIB_DIR = METIS_SRC_DIR = $(PARMETIS_SRC_DIR)/metis -METIS_LIB_DIR = #FILL IN +METIS_LIB_DIR = $(PARMETIS_SRC_DIR)/metis/build/Linux-x86_64/libmetis/ IGRAPH = IGRAPH_INSTALL_DIR = $(IGRAPH)/deploy GMP = +PETSC_DIR = +SLEPC_DIR = + #---------------------------------------------------------------- # # Compilers, Flags and System Tools @@ -80,7 +86,7 @@ CFLAGS := $(CFLAGS) -D__MADNESS__ -D_OLDGCC -Wno-strict-aliasing -Wno-deprecated endif ifeq ($(OLDGCC), 0) CPPFLAGS := $(CPPFLAGS) -std=c++0x -CFLAGS := $(CFLAGS) -D__MADNESS__ -std=c++0x -Wno-strict-aliasing -Wno-deprecated -ffast-math -march=native +CFLAGS := $(CFLAGS) -D__MADNESS__ -std=c++0x -Wno-strict-aliasing -Wno-deprecated -ffast-math endif endif @@ -176,6 +182,21 @@ $(error When HAS_METIS = 1, you must define the METIS_SRC_DIR directory variable endif endif +ifeq ($(HAS_SLEPC),1) +ifeq ($(HAS_PETSC),0) +$(error When HAS_SLEPC = 1, HAS_PETSC must also be 1) +endif +ifeq ($(SLEPC_DIR), ) +$(error When HAS_SLEPC = 1, you must define the SLEPC_DIR directory variable) +endif +endif + +ifeq ($(HAS_METIS),1) +ifeq ($(PETSC_DIR), ) +$(error When HAS_PETSC = 1, you must define the PETSC_DIR directory variable) +endif +endif + ifeq ($(HAS_IGRAPH),1) ifeq ($(IGRAPH), ) $(error When HAS_IGRAPH = 1, you must define the IGRAPH directory variable) @@ -323,3 +344,18 @@ IGRAPH_LIB= -L $(IGRAPH_INSTALL_DIR)/lib -ligraph IGRAPH_INCDIR = -I $(IGRAPH_INSTALL_DIR)/include/igraph endif +PETSC_INCDIR= +PETSC_LIB= +ifeq ($(HAS_PETSC),1) +CFLAGS := $(CFLAGS) -DHAS_PETSC +PETSC_INCDIR = -I $(PETSC_DIR)/include +PETSC_LIB = -L $(PETSC_DIR)/lib -lpetsc -llapack -lblas -lX11 +endif + +SLEPC_INCDIR= +SLEPC_LIB= +ifeq ($(HAS_SLEPC),1) +CFLAGS := $(CFLAGS) -DHAS_SLEPC +SLEPC_INCDIR = -I $(SLEPC_DIR)/include +SLEPC_LIB = -L $(SLEPC_DIR)/lib -lslepc +endif \ No newline at end of file diff --git a/max_wis/Makefile b/max_wis/Makefile index ef87cb5..1b8e918 100644 --- a/max_wis/Makefile +++ b/max_wis/Makefile @@ -3,9 +3,9 @@ include ../make.inc # Optimal WIS for this one is 79 TEST_GRAPH = $(SRC_DIR)/sample_graphs/pkt.200.70.75_0.dimacs -INC_DIR= -I./inc -I$(GRAPH)/inc -I$(TREE)/inc/ $(METIS_INCLUDES) $(SSPARSE_INCDIR) $(UTHASH_INCDIR) $(MADNESS_INCDIR) $(GMP_INCDIR) $(PARMETIS_INCDIR) -I$(PTREE)/inc/ +INC_DIR= -I./inc -I$(GRAPH)/inc -I$(TREE)/inc/ $(METIS_INCLUDES) $(SSPARSE_INCDIR) $(UTHASH_INCDIR) $(MADNESS_INCDIR) $(GMP_INCDIR) $(PARMETIS_INCDIR) -I$(PTREE)/inc/ $(SLEPC_INCDIR) $(PETSC_INCDIR) -LIBS = -lm $(INDDGO_LIB) -ltreed -lgraphd $(SSPARSE_LIB) $(ARPACK_LIB) $(MPILIBS) $(MADNESS_LIB) $(GMP_LIB) $(METIS_LIB) +LIBS = -lm $(INDDGO_LIB) -ltreed -lgraphd $(SSPARSE_LIB) $(ARPACK_LIB) $(MPILIBS) $(MADNESS_LIB) $(GMP_LIB) $(METIS_LIB) $(SLEPC_LIB) $(PETSC_LIB) WEIGHTED_IND_SET_SRC = ./src/weighted_ind_set.cpp ./src/main.cpp WEIGHTED_IND_SET_EXE = $(INDDGO_BIN)/serial_wis diff --git a/util/Makefile b/util/Makefile index f421ac7..a39a219 100644 --- a/util/Makefile +++ b/util/Makefile @@ -2,9 +2,9 @@ include ../make.inc DOX_DIR = ./doc/ DOXYFILE = ./Doxyfile -INC_DIR = -I./inc -I$(GRAPH)/inc -I$(TREE)/inc $(METIS_INCLUDES) $(SSPARSE_INCDIR) $(UTHASH_INCDIR) $(MADNESS_INCDIR) $(GMP_INCDIR) $(PARMETIS_INCDIR) +INC_DIR = -I./inc -I$(GRAPH)/inc -I$(TREE)/inc $(METIS_INCLUDES) $(SSPARSE_INCDIR) $(UTHASH_INCDIR) $(MADNESS_INCDIR) $(GMP_INCDIR) $(PARMETIS_INCDIR) $(SLEPC_INCDIR) $(PETSC_INCDIR) -LIBS = -lm $(INDDGO_LIB) -ltreed -lgraphd $(SSPARSE_LIB) $(ARPACK_LIB) $(GMP_LIB) $(PARMETIS_LIB) $(METIS_LIB) +LIBS = -lm $(INDDGO_LIB) -ltreed -lgraphd $(SSPARSE_LIB) $(ARPACK_LIB) $(GMP_LIB) $(PARMETIS_LIB) $(METIS_LIB) $(SLEPC_LIB) $(PETSC_LIB) PKT_SRCS = ./src/gen_pkt.cpp PKT_OBJ = src/orbtimer.o $(PKT_SRCS:.cpp=.o) diff --git a/viz/Makefile b/viz/Makefile index ea3fc83..37fe59e 100644 --- a/viz/Makefile +++ b/viz/Makefile @@ -3,9 +3,9 @@ include ../make.inc VIZ_SRC = ./src/viz_main.cpp ./src/viz.cpp VIZ_EXE = $(INDDGO_BIN)/td_viz -INC_DIR= -I./inc -I$(GRAPH)/inc -I$(TREE)/inc $(METIS_INCLUDES) $(SSPARSE_INCDIR) $(UTHASH_INCDIR) $(GMP_INCDIR) $(MADNESS_INCDIR) $(PARMETIS_INCDIR) +INC_DIR= -I./inc -I$(GRAPH)/inc -I$(TREE)/inc $(METIS_INCLUDES) $(SSPARSE_INCDIR) $(UTHASH_INCDIR) $(GMP_INCDIR) $(MADNESS_INCDIR) $(PARMETIS_INCDIR) $(SLEPC_INCDIR) $(PETSC_INCDIR) -LIBS = -lm $(INDDGO_LIB) -ltreed -lgraphd $(SSPARSE_LIB) $(ARPACK_LIB) $(GMP_LIB) $(PARMETIS_LIB) $(METIS_LIB) +LIBS = -lm $(INDDGO_LIB) -ltreed -lgraphd $(SSPARSE_LIB) $(ARPACK_LIB) $(GMP_LIB) $(PARMETIS_LIB) $(METIS_LIB) $(SLEPC_LIB) $(PETSC_LIB) VIZ_OBJ=$(VIZ_SRC:.cpp=.o) From 7b011cbf441fef01958cc2af5df76baf4f98228f Mon Sep 17 00:00:00 2001 From: Matt Baker Date: Tue, 2 Jul 2013 15:30:09 -0400 Subject: [PATCH 09/73] Initial version of eigen spectrum solver --- lib_graphd/inc/Graph.h | 8 +++++++ lib_graphd/inc/GraphProperties.h | 4 ++++ lib_graphd/inc/GraphUtil.h | 3 +++ lib_graphd/src/GraphProperties.cpp | 30 +++++++++++++++++++++++ lib_graphd/src/GraphUtil.cpp | 38 ++++++++++++++++++++++++++++++ util/src/graph_stats.cpp | 38 ++++++++++++++++++++++++++++-- 6 files changed, 119 insertions(+), 2 deletions(-) diff --git a/lib_graphd/inc/Graph.h b/lib_graphd/inc/Graph.h index 90ee634..195a0b3 100644 --- a/lib_graphd/inc/Graph.h +++ b/lib_graphd/inc/Graph.h @@ -29,6 +29,10 @@ #define omp_get_thread_num() 0 #endif +#ifdef HAS_PETSC +#include +#endif + #include "GraphInterface.h" #include "Node.h" #include @@ -58,6 +62,10 @@ namespace Graph { vector adj_vec; vector< vector > apsp_dist; +#ifdef HAS_PETSC + Mat PetscMat; +#endif + public: Graph(); Graph(int n); diff --git a/lib_graphd/inc/GraphProperties.h b/lib_graphd/inc/GraphProperties.h index d7d860f..6afbcf6 100644 --- a/lib_graphd/inc/GraphProperties.h +++ b/lib_graphd/inc/GraphProperties.h @@ -121,6 +121,10 @@ namespace Graph { * \brief Returns the degree assortativity coefficient of a graph */ void deg_assortativity(Graph *g, double &coeff); + /** + * \brief Calculates the eign spectrum. By default it does the top 5 and bottom 5. + */ + void eigen_spectrum(Graph *g, vector eigen_values, int spread = 5); }; } diff --git a/lib_graphd/inc/GraphUtil.h b/lib_graphd/inc/GraphUtil.h index 3deb122..ba5ec26 100644 --- a/lib_graphd/inc/GraphUtil.h +++ b/lib_graphd/inc/GraphUtil.h @@ -84,6 +84,9 @@ namespace Graph { //Calculate the maximum distance between nodes within a subset of vertices //given as a list int subset_max_dist(Graph *g, vector subset); + void populate_PetscMat(Graph* g); + void free_PetscMat(Graph* g); + }; void create_largestcomponent_graph(char *graph_file, VertexWeightedGraph *&G); diff --git a/lib_graphd/src/GraphProperties.cpp b/lib_graphd/src/GraphProperties.cpp index 0efeab7..610f420 100644 --- a/lib_graphd/src/GraphProperties.cpp +++ b/lib_graphd/src/GraphProperties.cpp @@ -25,6 +25,9 @@ #include #include +#ifdef HAS_SLEPC +#include +#endif namespace Graph { GraphProperties::GraphProperties(){ @@ -941,4 +944,31 @@ namespace Graph { coeff = (n1 - n2) / (de - n2); } // deg_assortativity + + void GraphProperties::eigen_spectrum(Graph *g, vector eigen_values, int spread) { +#ifndef HAS_SLEPC + fatal_error("Called SLEPC eigen solvers without HAS_SLEPC.\n"); +#else + GraphUtil graph_util; + graph_util.populate_PetscMat(g); + EPS eps; + PetscInt nconv; + PetscScalar kr,ki; + EPSCreate(PETSC_COMM_WORLD, &eps); + EPSSetOperators(eps,g->PetscMat,PETSC_NULL); + EPSSetLeftVectorsWanted(eps,PETSC_TRUE); + EPSSetFromOptions(eps); + EPSSetDimensions(eps,spread*2,spread*8,spread*8); + EPSSolve(eps); + EPSGetConverged(eps,&nconv); + //memset(eigen_values,'\0',spread*sizeof(double)); + EPSGetConverged(eps,&nconv); + for(int idx=0; idx < nconv; idx++) { + EPSGetEigenvalue(eps,idx,&kr,&ki); + eigen_values[idx] = kr; + } + EPSDestroy(&eps); + +#endif + } } diff --git a/lib_graphd/src/GraphUtil.cpp b/lib_graphd/src/GraphUtil.cpp index 3bcc992..42e073f 100644 --- a/lib_graphd/src/GraphUtil.cpp +++ b/lib_graphd/src/GraphUtil.cpp @@ -498,6 +498,44 @@ namespace Graph { g->adjncy.clear(); } + void GraphUtil::populate_PetscMat(Graph *g){ + if(g->adjncy.size() == 0) { + populate_CRS(g); + } + int start, end; + + //Matrix is g->PetscMat + PetscErrorCode ierror; + ierror=MatCreate(PETSC_COMM_WORLD,&(g->PetscMat));CHKERRABORT(PETSC_COMM_WORLD,ierror); + ierror=MatSetSizes(g->PetscMat,PETSC_DECIDE,PETSC_DECIDE,g->num_nodes,g->num_nodes);CHKERRABORT(PETSC_COMM_WORLD,ierror); + ierror=MatSetFromOptions(g->PetscMat);CHKERRABORT(PETSC_COMM_WORLD,ierror); + ierror=MatSetUp(g->PetscMat);CHKERRABORT(PETSC_COMM_WORLD,ierror); + int row, col, size; + const PetscScalar one_val = 1; + + for(int node=0; node < g->num_nodes; node++){ + start = g->xadj[node]; + end = g->xadj[node+1]; + size = 1 + end - start; + row = node; + PetscScalar ones[size]; + PetscInt columns[size]; + for(int idx=0; idx < size; idx++) { + ones[idx]=1.0; + columns[idx]=g->adjncy[start+idx]; + } + ierror=MatSetValues(g->PetscMat, 1, &row, size, columns, ones, INSERT_VALUES);CHKERRABORT(PETSC_COMM_WORLD,ierror); + } + + ierror=MatAssemblyBegin(g->PetscMat,MAT_FINAL_ASSEMBLY);CHKERRABORT(PETSC_COMM_WORLD,ierror); + ierror=MatAssemblyEnd(g->PetscMat,MAT_FINAL_ASSEMBLY);CHKERRABORT(PETSC_COMM_WORLD,ierror); + + } + + void GraphUtil::free_PetscMat(Graph *g) { + PetscErrorCode ierror=MatDestroy(&(g->PetscMat));CHKERRABORT(PETSC_COMM_WORLD,ierror); + } + /** * Non-recursive function that fills the members vector with the * lists of nodes belonging to the components. The members vector diff --git a/util/src/graph_stats.cpp b/util/src/graph_stats.cpp index 881e3fb..1254482 100644 --- a/util/src/graph_stats.cpp +++ b/util/src/graph_stats.cpp @@ -35,13 +35,17 @@ #include "orbconfig.h" #include "orbtimer.h" +#ifdef HAS_SLEPC +#include +#endif + using namespace std; void print_time(string prefix, ORB_t start, ORB_t end){ cout << prefix + ": " << ORB_seconds(end, start) << "\n"; } -const string allowed_methods ("edge_density,avg_degree,degree_dist,global_cc,avg_cc,local_ccs,shortest_paths,assortativity,eccentricity,eccentricity_dist"); +const string allowed_methods ("edge_density,avg_degree,degree_dist,global_cc,avg_cc,local_ccs,shortest_paths,assortativity,eccentricity,eccentricity_dist,eigen_spectrum"); /** * Creates a map from a comma-separated string @@ -133,6 +137,15 @@ int main(int argc, char **argv){ cout << "Calibrating timers\n"; ORB_calibrate(); + //If petsc/slepc are present, initalize those. + //If MPI support is added in the future, init MPI before Petsc. Petsc will do it's own MPI + //init if MPI isn't already inited. + #ifdef HAS_SLEPC + SlepcInitialize(&argc,&argv,PETSC_NULL,PETSC_NULL); + #elif HAVE_PETSC + PetscInitialize(&argc,&argv,PETSC_NULL,PETSC_NULL); + #endif + // let's do some calculations Graph::Graph g; @@ -148,10 +161,11 @@ int main(int argc, char **argv){ print_time("Time(read_graph)", t1, t2); double global_cc, avg_cc, assortativity; - vector local_cc, freq_ecc; + vector local_cc, freq_ecc, eigen_spectrum; float edge_density, avg_degree; vector deg_dist, ecc; vector< vector > shortest_path_distances; + int spectrum_spread; outfile.open(outfilename.c_str()); if(!outfile.is_open()){ @@ -241,8 +255,28 @@ int main(int argc, char **argv){ ORB_read(t2); print_time("Time(eccentricity distribution)",t1,t2); } + if(req_methods["eigen_spectrum"] == true){ + spectrum_spread = 3; + cout << "Calculating adjacency matrix eign spectrum\n"; + ORB_read(t1); + gp.eigen_spectrum(&g, eigen_spectrum, spectrum_spread); + ORB_read(t2); + print_time("Time(eign spectrum)",t1,t2); + //outfile << "eigen_spectrum" << eigen_spectrum << "\n"; + outfile << "eigen_spectrum "; + for(int idx=0; idx < eigen_spectrum.size(); idx++){ + outfile << eigen_spectrum[idx]; + } + outfile << "\n"; + } outfile.close(); + + #ifdef HAS_SLEPC + SlepcFinalize(); + #elif HAVE_PETSC + PetscFinalize(); + #endif exit(0); } // main From ee53b1bef1ecbbb310b19237085b24e54474b786 Mon Sep 17 00:00:00 2001 From: Matt Baker Date: Wed, 3 Jul 2013 14:36:51 -0400 Subject: [PATCH 10/73] Bug fixes. --- lib_graphd/inc/GraphProperties.h | 2 +- lib_graphd/src/GraphProperties.cpp | 5 ++-- lib_graphd/src/GraphUtil.cpp | 2 -- lib_graphd/src/Makefile | 2 +- util/src/graph_stats.cpp | 37 ++++++++++++++++-------------- 5 files changed, 25 insertions(+), 23 deletions(-) diff --git a/lib_graphd/inc/GraphProperties.h b/lib_graphd/inc/GraphProperties.h index 6afbcf6..7478e55 100644 --- a/lib_graphd/inc/GraphProperties.h +++ b/lib_graphd/inc/GraphProperties.h @@ -124,7 +124,7 @@ namespace Graph { /** * \brief Calculates the eign spectrum. By default it does the top 5 and bottom 5. */ - void eigen_spectrum(Graph *g, vector eigen_values, int spread = 5); + void eigen_spectrum(Graph *g, vector &eigen_values, int spread = 5); }; } diff --git a/lib_graphd/src/GraphProperties.cpp b/lib_graphd/src/GraphProperties.cpp index 610f420..4894a0d 100644 --- a/lib_graphd/src/GraphProperties.cpp +++ b/lib_graphd/src/GraphProperties.cpp @@ -945,7 +945,7 @@ namespace Graph { coeff = (n1 - n2) / (de - n2); } // deg_assortativity - void GraphProperties::eigen_spectrum(Graph *g, vector eigen_values, int spread) { + void GraphProperties::eigen_spectrum(Graph *g, vector &eigen_values, int spread) { #ifndef HAS_SLEPC fatal_error("Called SLEPC eigen solvers without HAS_SLEPC.\n"); #else @@ -955,14 +955,15 @@ namespace Graph { PetscInt nconv; PetscScalar kr,ki; EPSCreate(PETSC_COMM_WORLD, &eps); + EPSSetType(eps, EPSPOWER); EPSSetOperators(eps,g->PetscMat,PETSC_NULL); EPSSetLeftVectorsWanted(eps,PETSC_TRUE); EPSSetFromOptions(eps); EPSSetDimensions(eps,spread*2,spread*8,spread*8); EPSSolve(eps); EPSGetConverged(eps,&nconv); - //memset(eigen_values,'\0',spread*sizeof(double)); EPSGetConverged(eps,&nconv); + eigen_values.resize(nconv); for(int idx=0; idx < nconv; idx++) { EPSGetEigenvalue(eps,idx,&kr,&ki); eigen_values[idx] = kr; diff --git a/lib_graphd/src/GraphUtil.cpp b/lib_graphd/src/GraphUtil.cpp index 42e073f..8a5f8ff 100644 --- a/lib_graphd/src/GraphUtil.cpp +++ b/lib_graphd/src/GraphUtil.cpp @@ -512,7 +512,6 @@ namespace Graph { ierror=MatSetUp(g->PetscMat);CHKERRABORT(PETSC_COMM_WORLD,ierror); int row, col, size; const PetscScalar one_val = 1; - for(int node=0; node < g->num_nodes; node++){ start = g->xadj[node]; end = g->xadj[node+1]; @@ -529,7 +528,6 @@ namespace Graph { ierror=MatAssemblyBegin(g->PetscMat,MAT_FINAL_ASSEMBLY);CHKERRABORT(PETSC_COMM_WORLD,ierror); ierror=MatAssemblyEnd(g->PetscMat,MAT_FINAL_ASSEMBLY);CHKERRABORT(PETSC_COMM_WORLD,ierror); - } void GraphUtil::free_PetscMat(Graph *g) { diff --git a/lib_graphd/src/Makefile b/lib_graphd/src/Makefile index 79b144a..d3077ca 100644 --- a/lib_graphd/src/Makefile +++ b/lib_graphd/src/Makefile @@ -12,7 +12,7 @@ GVIZ=../bin/gviz # include directories INCLUDES = -I../inc/ -I/usr/local/include $(METIS_INCLUDES) $(SSPARSE_INCDIR) $(PARMETIS_INCDIR) $(PETSC_INCDIR) $(SLEPC_INCDIR) # libraries -LIBS = -L/usr/local/lib $(INDDGO_LIB) $(SSPARSE_LIB) -lm $(METIS_LIB) $(PARMETIS_LIB) $(PETSC_LIB) $(SLEPC_LIB) +LIBS = -L/usr/local/lib $(INDDGO_LIB) $(SSPARSE_LIB) -lm $(METIS_LIB) $(PARMETIS_LIB) $(SLEPC_LIB) $(PETSC_LIB) # source SRC := Log.cpp GraphReader.cpp Node.cpp \ GraphCreator.cpp GraphCreatorFile.cpp Graph.cpp VertexWeightedGraph.cpp GraphProperties.cpp \ diff --git a/util/src/graph_stats.cpp b/util/src/graph_stats.cpp index 1254482..eecca1f 100644 --- a/util/src/graph_stats.cpp +++ b/util/src/graph_stats.cpp @@ -61,7 +61,7 @@ void create_map(string list, map &outmap){ } void print_usage(char **argv){ - cerr << "Usage: " << argv[0] << " [-h] -i infile [-t input-type] [-o outfile] [-p output-prefix] [-m methods]\n"; + cerr << "Usage: " << argv[0] << " [-h] -i infile [-t input-type] [-o outfile] [-p output-prefix] [-m methods] [-s eigen spectrum size]\n"; cerr << "Allowed methods: " << allowed_methods << "\n"; cerr << "Input type should be one of: edge, adjlist, adjmatrix, dimacs\n"; } @@ -75,9 +75,10 @@ void print_usage(char **argv){ * \param[out] outfilename file to write output to * \param[out] methods list of methods we want to run. Valid values currently: edge_density,avg_degree,degree_dist,global_cc, avg_cc, local_ccs */ -int parse_options(int argc, char **argv, string& infile, string& intype, string& outfilename, string &outprefix, std::map& methods){ + +int parse_options(int argc, char **argv, string& infile, string& intype, string& outfilename, string &outprefix, std::map& methods, int *spectrum_spread){ int flags, opt; - while((opt = getopt(argc, argv, "hi:t:o:m:p:")) != -1){ + while((opt = getopt(argc, argv, "hi:t:o:m:p:s:")) != -1){ switch(opt){ case 'h': print_usage(argv); @@ -97,6 +98,10 @@ int parse_options(int argc, char **argv, string& infile, string& intype, string& case 'm': create_map(optarg, methods); break; + case 's': + cout << "optarg=" << optarg << endl; + *spectrum_spread = atoi(optarg); + break; } } @@ -112,9 +117,9 @@ int main(int argc, char **argv){ std::map req_methods; std::map val_methods; ORB_t t1, t2; - + int spectrum_spread=0; create_map(allowed_methods, val_methods); - parse_options(argc, argv, infile, intype, outfilename, outprefix, req_methods); + parse_options(argc, argv, infile, intype, outfilename, outprefix, req_methods, &spectrum_spread); if(outprefix.length() == 0){ outprefix = infile; } @@ -137,15 +142,6 @@ int main(int argc, char **argv){ cout << "Calibrating timers\n"; ORB_calibrate(); - //If petsc/slepc are present, initalize those. - //If MPI support is added in the future, init MPI before Petsc. Petsc will do it's own MPI - //init if MPI isn't already inited. - #ifdef HAS_SLEPC - SlepcInitialize(&argc,&argv,PETSC_NULL,PETSC_NULL); - #elif HAVE_PETSC - PetscInitialize(&argc,&argv,PETSC_NULL,PETSC_NULL); - #endif - // let's do some calculations Graph::Graph g; @@ -165,7 +161,6 @@ int main(int argc, char **argv){ float edge_density, avg_degree; vector deg_dist, ecc; vector< vector > shortest_path_distances; - int spectrum_spread; outfile.open(outfilename.c_str()); if(!outfile.is_open()){ @@ -256,13 +251,21 @@ int main(int argc, char **argv){ print_time("Time(eccentricity distribution)",t1,t2); } if(req_methods["eigen_spectrum"] == true){ - spectrum_spread = 3; + //If petsc/slepc are present, initalize those. + //If MPI support is added in the future, init MPI before Petsc. Petsc will do it's own MPI + //init if MPI isn't already inited. + #ifdef HAS_SLEPC + SlepcInitializeNoArguments(); + #elif HAVE_PETSC + PetscInitializeNoArguments(); + #endif + if(spectrum_spread == 0) spectrum_spread = 3; + cout << "Calculating adjacency matrix eign spectrum\n"; ORB_read(t1); gp.eigen_spectrum(&g, eigen_spectrum, spectrum_spread); ORB_read(t2); print_time("Time(eign spectrum)",t1,t2); - //outfile << "eigen_spectrum" << eigen_spectrum << "\n"; outfile << "eigen_spectrum "; for(int idx=0; idx < eigen_spectrum.size(); idx++){ outfile << eigen_spectrum[idx]; From 7ef2a5d7974a58d80d36d44b7a1b615eaddd8b9c Mon Sep 17 00:00:00 2001 From: Matt Baker Date: Wed, 3 Jul 2013 14:40:04 -0400 Subject: [PATCH 11/73] spelling errors --- util/src/graph_stats.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/util/src/graph_stats.cpp b/util/src/graph_stats.cpp index eecca1f..7e53d6e 100644 --- a/util/src/graph_stats.cpp +++ b/util/src/graph_stats.cpp @@ -261,11 +261,11 @@ int main(int argc, char **argv){ #endif if(spectrum_spread == 0) spectrum_spread = 3; - cout << "Calculating adjacency matrix eign spectrum\n"; + cout << "Calculating adjacency matrix eigen spectrum\n"; ORB_read(t1); gp.eigen_spectrum(&g, eigen_spectrum, spectrum_spread); ORB_read(t2); - print_time("Time(eign spectrum)",t1,t2); + print_time("Time(eigen spectrum)",t1,t2); outfile << "eigen_spectrum "; for(int idx=0; idx < eigen_spectrum.size(); idx++){ outfile << eigen_spectrum[idx]; From 30cf19a1ed7bd5febd591128b152a55e365ec8e2 Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Fri, 5 Jul 2013 11:22:37 -0400 Subject: [PATCH 12/73] in-progress changes for dijkstra-heap --- lib_graphd/inc/Graph.h | 12 +++- lib_graphd/inc/GraphProperties.h | 10 ++++ lib_graphd/src/GraphProperties.cpp | 92 +++++++++++++++++++++++++++++- util/src/graph_stats.cpp | 10 +++- util/src/shortest-paths.cpp | 17 ++++-- 5 files changed, 131 insertions(+), 10 deletions(-) diff --git a/lib_graphd/inc/Graph.h b/lib_graphd/inc/Graph.h index be6f227..54e79d8 100644 --- a/lib_graphd/inc/Graph.h +++ b/lib_graphd/inc/Graph.h @@ -31,11 +31,13 @@ #include "GraphInterface.h" #include "Node.h" +#include "GraphException.h" +#include "Log.h" #include using namespace std; -#define INDDGO_INFINITY INT_MAX +#define INDDGO_INFINITY INT_MAX - 16 namespace Graph { class Graph : public GraphInterface @@ -139,6 +141,14 @@ namespace Graph { /** \brief get shortest path distances from vertex u to all **/ const vector &get_u_shortest_path_dist(int u); + inline Node *get_node_inline(int i){ + if(i > capacity){ + FERROR("%s: element is out of bounds", __FUNCTION__); + throw GraphException("element is out of bounds\n"); + } + return &nodes[i]; + } + friend class GraphUtil; friend class GraphProperties; friend class GraphDisplay; diff --git a/lib_graphd/inc/GraphProperties.h b/lib_graphd/inc/GraphProperties.h index 4990835..2fbe6e4 100644 --- a/lib_graphd/inc/GraphProperties.h +++ b/lib_graphd/inc/GraphProperties.h @@ -72,11 +72,21 @@ namespace Graph { */ void paths_dijkstra_single(Graph *g, vector &p, int source); + /** + * \brief returns shortest paths from source to all other nodes + */ + void paths_dijkstra_heap_single(Graph *g, vector &dists, int source); + /** * \brief returns shortest paths from all nodes to all nodes */ void paths_dijkstra_all(Graph *g, vector< vector > &p); + /** + * \brief returns shortest paths from all nodes to all nodes + */ + void paths_dijkstra_heap_all(Graph *g, vector< vector > &p); + /** * \brief returns eccentricity for all nodes */ diff --git a/lib_graphd/src/GraphProperties.cpp b/lib_graphd/src/GraphProperties.cpp index dd716ff..379b7ca 100644 --- a/lib_graphd/src/GraphProperties.cpp +++ b/lib_graphd/src/GraphProperties.cpp @@ -20,9 +20,11 @@ */ #include "GraphDecomposition.h" +#include "Log.h" #include #include #include +#include "binomial-heap/iheap.h" #include @@ -616,6 +618,59 @@ namespace Graph { global_cc = (double)num_triangles / (double)total_possible_triangles; } // clustering_coefficients + /** + * We assume that edge weights are all 1 + * + * \param[in] g input graph + * \param[in] source node id + * \param[out] p path distances from source to all other vertices + */ + void GraphProperties::paths_dijkstra_heap_single(Graph *g, vector &dists, int source){ + struct iheap heap; + struct iheap_node *hn; + const int n = g->get_num_nodes(); + struct iheap_node **heapnodes; + int j, k; + long i; + + dists.resize(n,INDDGO_INFINITY); + dists[source] = 0; + + iheap_init(&heap); + + heapnodes = (struct iheap_node **)malloc(n * sizeof(iheap_node *)); + + for(i = 0; i < n; i++){ // insert all of our nodes into the heap + heapnodes[i] = (struct iheap_node *)malloc(sizeof(struct iheap_node)); + hn = heapnodes[i]; + iheap_node_init(hn, dists[i], (void *)(i)); + iheap_insert(&heap, hn); + //iheap_node_init(hn, dist[n], g->get_node(i)); + } + + // now, keep finding the vertex with the smallest dist[] + // and recompute paths to update all shortest paths + list::const_iterator lcit; + Node *u; + int d; + for(k = 0; k < n; k++){ + hn = iheap_take(&heap); + i = (long)(hn->value); + d = hn->key; + // trying this for speed + u = &(g->nodes[i]); + dists[i] = d; + + const list &nbrs = u->get_nbrs_ref(); + for(lcit = nbrs.begin(); lcit != nbrs.end(); ++lcit){ + hn = heapnodes[*lcit]; + if(d + 1 < hn->key){ + iheap_decrease(&heap, hn, d + 1); + } + } + } + } // paths_dijkstra_heap_single + /** * \param[in] g input graph * \param[in] source node id @@ -694,7 +749,7 @@ namespace Graph { pAll.resize(n); //#pragma omp parallel for default(none) shared(g, inf, pAll) private(nvisiting, nVisited, nv) firstprivate(dist, minD, visited) - #pragma omp parallel for default(none) shared(g, inf, pAll) + #pragma omp parallel for schedule(dynamic, 8) default(none) shared(g, inf, pAll) //loop over all vertices for(int v = 0; v < n; v++){ //0; v < n; v++){ //reset all distances to INF and mark all vertices as unvisited @@ -715,6 +770,41 @@ namespace Graph { //printf("\n"); } //paths_dijkstra_all + /** + * All pairs shortest paths using heaps + * \param[in] g input graph + * \param[out] p multidimentional list of all pairs shortest paths + */ + + void GraphProperties::paths_dijkstra_heap_all(Graph *g, vector< vector > &pAll){ + int inf = INDDGO_INFINITY; + + int minD = inf; + const int n = g->get_num_nodes(); + + pAll.resize(n); + + //#pragma omp parallel for default(none) shared(g, inf, pAll) private(nvisiting, nVisited, nv) firstprivate(dist, minD, visited) + #pragma omp parallel for schedule(dynamic, 8) default(none) shared(g, inf, pAll) + //loop over all vertices + for(int v = 0; v < n; v++){ //0; v < n; v++){ + //reset all distances to INF and mark all vertices as unvisited + fill(pAll[v].begin(),pAll[v].end(),inf); + paths_dijkstra_heap_single(g, pAll[v], v); //stores shortest paths from this vertex to all in pAll[v] + } //end loop over vertices + + //store the results + g->set_shortest_path_dist(pAll); + + //print out results + //for(int i = 0; i < n; i++){ + // for (int j = 0; j < n; j++) { + // printf("%d, ",pAll[i][j]); + // } + // printf("\n"); + //} + //printf("\n"); + } //paths_dijkstra_all /** * Calcuates the eccentricity for each vertex (max dist to any other vertex) * \param[in] g input graph diff --git a/util/src/graph_stats.cpp b/util/src/graph_stats.cpp index 7a9a4b9..41af83d 100644 --- a/util/src/graph_stats.cpp +++ b/util/src/graph_stats.cpp @@ -41,7 +41,7 @@ void print_time(string prefix, ORB_t start, ORB_t end){ cout << prefix + ": " << ORB_seconds(end, start) << endl; } -const string allowed_methods ("edge_density,avg_degree,degree_dist,global_cc,avg_cc,local_ccs,shortest_paths,assortativity,eccentricity,eccentricity_dist,expansion,avg_shortest_path"); +const string allowed_methods ("edge_density,avg_degree,degree_dist,global_cc,avg_cc,local_ccs,shortest_paths,assortativity,eccentricity,eccentricity_dist,expansion,avg_shortest_path,shortest_paths_heap"); /** * Creates a map from a comma-separated string @@ -222,7 +222,13 @@ int main(int argc, char **argv){ if(req_methods["local_ccs"] == true){ } } - + if(req_methods["shortest_paths_heap"] == true){ + cout << "Calculating shortest paths (heap)" << endl; + ORB_read(t1); + gp.paths_dijkstra_heap_all(&g, shortest_path_distances); + ORB_read(t2); + print_time("Time(shortest_paths_dijkstra_heap)", t1, t2); + } if(req_methods["shortest_paths"] == true){ cout << "Calculating shortest paths" << endl; ORB_read(t1); diff --git a/util/src/shortest-paths.cpp b/util/src/shortest-paths.cpp index 8f3daca..1af6eaa 100644 --- a/util/src/shortest-paths.cpp +++ b/util/src/shortest-paths.cpp @@ -65,21 +65,26 @@ int main(int argc, char **argv){ //compute shortest paths from source node begin = clock(); //for each node run it - int source = 0; + int source = 8; vector onePaths; printf("\nRunning Dijsktra for source %d\n",source); prop.paths_dijkstra_single(g, onePaths, source); end = clock(); + + int i; + for(i = 0; i < onePaths.size(); i++){ + printf("%d: %d\n", i, onePaths[i]); + } printf("Alg Time (single): %f\n", double(end - begin) / CLOCKS_PER_SEC); //compute all pairs shortest paths begin = clock(); - vector< vector > allPaths; +// vector< vector > allPaths; - printf("\nRunning Dijsktra for all pairs \n"); - prop.paths_dijkstra_all(g,allPaths); //alternate: vector< vector > pt2 = g->get_shortest_path_dist_ref(); - end = clock(); - printf("Alg Time (all): %f\n", double(end - begin) / CLOCKS_PER_SEC); + // printf("\nRunning Dijsktra for all pairs \n"); + // prop.paths_dijkstra_all(g,allPaths); //alternate: vector< vector > pt2 = g->get_shortest_path_dist_ref(); + // end = clock(); + //printf("Alg Time (all): %f\n", double(end - begin) / CLOCKS_PER_SEC); } // main From 7fdfd0cb4c8996c62531c96b40f6cb233e56ba1c Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Fri, 5 Jul 2013 15:05:29 -0400 Subject: [PATCH 13/73] Clean up new k-core code --- lib_graphd/inc/GraphUtil.h | 2 +- lib_graphd/src/GraphUtil.cpp | 118 +++++++++++++++++------------------ 2 files changed, 60 insertions(+), 60 deletions(-) diff --git a/lib_graphd/inc/GraphUtil.h b/lib_graphd/inc/GraphUtil.h index 2dc8107..f0298a0 100644 --- a/lib_graphd/inc/GraphUtil.h +++ b/lib_graphd/inc/GraphUtil.h @@ -81,7 +81,7 @@ namespace Graph { //Find the eccentricity of each vertex and store it in ecc. void find_ecc(Graph *g, vector *ecc); - //Find the k-core number of each vertex and store it in kcore. + //Find the k-core number of each vertex and store it in kcore. //Return degeneracy. int find_kcore(Graph *g, vector *kcore); diff --git a/lib_graphd/src/GraphUtil.cpp b/lib_graphd/src/GraphUtil.cpp index 50a4b15..3528997 100644 --- a/lib_graphd/src/GraphUtil.cpp +++ b/lib_graphd/src/GraphUtil.cpp @@ -764,66 +764,66 @@ namespace Graph { return max; } // subset_max_dist - /** - * Calculates the k-core number of every vertex and stores in kcore vector - * Return value is degeneracy (maximum non-empty k-core). - * Uses algorithm of Batagelj and Zaversnik (2003) - * Implemented by Timothy Goodrich and Matthew Farrell (2013) - */ - int GraphUtil::find_kcore(Graph *g, vector *kcore) { - int n = g->num_nodes; - int k = 0; - int last_deg = 0; - kcore->resize(n); - - vector deg_lookup(n); - int max_deg = 0; - for(int i = 0; i < deg_lookup.size(); i++) { - deg_lookup[i] = g->degree[i]; - if(deg_lookup[i] > max_deg) - max_deg = deg_lookup[i]; - } - vector D[max_deg+1]; - int depth[n]; - //can also create an L output list for coloring number optimal ordering - - for(int i = 0; i < n; i++) { - deg_lookup[i] = g->degree[i]; - D[deg_lookup[i]].push_back(i); - depth[i] = D[deg_lookup[i]].size()-1; - } - - for(int i = 0; i < n; i++) { - int v; - for(int j = last_deg; j <= max_deg; j++) { - if(D[j].size() != 0) { - v = D[j].back(); - D[j].pop_back(); - break; - } - } - - (*kcore)[v] = k = max(k,deg_lookup[v]); - last_deg = max(0, deg_lookup[v]-1); - deg_lookup[v] = -1; - - //shift each of v's neighbors down one degree - list * nbrs = g->nodes[v].get_nbrs_ptr(); - list::const_iterator it; - for(it = nbrs->begin(); it != nbrs->end(); it++) { - if(deg_lookup[*it] != -1) { - int it_deg = deg_lookup[*it]--; - D[it_deg][depth[*it]] = D[it_deg][D[it_deg].size()-1]; - depth[D[it_deg][depth[*it]]] = depth[*it]; - D[it_deg].pop_back(); - D[it_deg-1].push_back(*it); - depth[*it] = D[it_deg-1].size()-1; - } - } - } - return k; - } // find_degen + /** + * Calculates the k-core number of every vertex and stores in kcore vector + * Return value is degeneracy (maximum non-empty k-core). + * Uses algorithm of Batagelj and Zaversnik (2003) + * Implemented by Timothy Goodrich and Matthew Farrell (2013) + */ + int GraphUtil::find_kcore(Graph *g, vector *kcore){ + int n = g->num_nodes; + int k = 0; + int last_deg = 0; + kcore->resize(n); + + vector deg_lookup(n); + int max_deg = 0; + for(int i = 0; i < deg_lookup.size(); i++){ + deg_lookup[i] = g->degree[i]; + if(deg_lookup[i] > max_deg){ + max_deg = deg_lookup[i]; + } + } + vector D[max_deg + 1]; + int depth[n]; + //can also create an L output list for coloring number optimal ordering + + for(int i = 0; i < n; i++){ + deg_lookup[i] = g->degree[i]; + D[deg_lookup[i]].push_back(i); + depth[i] = D[deg_lookup[i]].size() - 1; + } + + for(int i = 0; i < n; i++){ + int v; + for(int j = last_deg; j <= max_deg; j++){ + if(D[j].size() != 0){ + v = D[j].back(); + D[j].pop_back(); + break; + } + } + (*kcore)[v] = k = max(k,deg_lookup[v]); + last_deg = max(0, deg_lookup[v] - 1); + deg_lookup[v] = -1; + + //shift each of v's neighbors down one degree + list *nbrs = g->nodes[v].get_nbrs_ptr(); + list::const_iterator it; + for(it = nbrs->begin(); it != nbrs->end(); it++){ + if(deg_lookup[*it] != -1){ + int it_deg = deg_lookup[*it]--; + D[it_deg][depth[*it]] = D[it_deg][D[it_deg].size() - 1]; + depth[D[it_deg][depth[*it]]] = depth[*it]; + D[it_deg].pop_back(); + D[it_deg - 1].push_back(*it); + depth[*it] = D[it_deg - 1].size() - 1; + } + } + } + return k; + } // find_degen } using namespace std; /** From b127388e7abac9324910a302bbbb630d25f46e93 Mon Sep 17 00:00:00 2001 From: Jonathan Schrock Date: Wed, 10 Jul 2013 14:36:46 -0400 Subject: [PATCH 14/73] Power law fitting added to GraphProperties --- lib_graphd/inc/GraphProperties.h | 6 ++ lib_graphd/src/GraphProperties.cpp | 128 +++++++++++++++++++++++++++-- 2 files changed, 126 insertions(+), 8 deletions(-) diff --git a/lib_graphd/inc/GraphProperties.h b/lib_graphd/inc/GraphProperties.h index 4990835..7e66390 100644 --- a/lib_graphd/inc/GraphProperties.h +++ b/lib_graphd/inc/GraphProperties.h @@ -22,6 +22,7 @@ #ifndef GRAPHPROPERTIES_H_ #define GRAPHPROPERTIES_H_ #include "GraphDecomposition.h" +#include using namespace std; @@ -122,6 +123,11 @@ namespace Graph { */ void deg_dist(Graph *g, vector &dist); + /** + * \brief Fits the degree distribution of the specified graph to a power law distribution + */ + void powerlaw(Graph *g, double start, double inc, double end, int &xmin, double &alpha, double &KS ){ + /** * \brief Returns the degree assortativity coefficient of a graph */ diff --git a/lib_graphd/src/GraphProperties.cpp b/lib_graphd/src/GraphProperties.cpp index dd716ff..215b269 100644 --- a/lib_graphd/src/GraphProperties.cpp +++ b/lib_graphd/src/GraphProperties.cpp @@ -807,16 +807,14 @@ namespace Graph { */ void GraphProperties::diameter(Graph *g, int &diam){ int i, j, size, temp; - vector< vector > dist_mat; - - paths_dijkstra_all(g, dist_mat); + vector< vector > dist_mat = g->get_shortest_path_dist_ref(); //computes if not already size = dist_mat.size(); diam = dist_mat[0][0]; for(i = 0; i < size; i++){ for(j = 0; j < i; j++){ temp = dist_mat[i][j]; - if((temp > diam) && (temp < INT_MAX)){ + if((temp > diam) && (temp < INDDGO_INFINITY)){ diam = temp; } } @@ -833,16 +831,14 @@ namespace Graph { int i, j, d, size, temp, diam = 0; int n0, numer, tot_con_pairs = 0; float gd; - vector< vector > dist_mat; + vector< vector > dist_mat = g->get_shortest_path_dist_ref(); //computes if not already vector bins (g->num_nodes, 0); - paths_dijkstra_all(g, dist_mat); - size = dist_mat.size(); for(i = 0; i < size; i++){ for(j = 0; j < i; j++){ temp = dist_mat[i][j]; - if(temp < INT_MAX){ + if(temp < INDDGO_INFINITY){ tot_con_pairs++; if(temp > diam){ diam = temp; @@ -928,6 +924,122 @@ namespace Graph { } } + /** + * Fits the degree distribution of g to a power law distribution + * \param[in] g Pointer to a graph + * \param[in] start Lower bound for exponent, defaults to 1.5 + * \param[in] inc Determines granularity of the exponent search range, defaults to 0.01 + * \param[in] end Upper bound for exponent, defaults to 3.5 + * \param[out] xmin Integer value holding the degree at which the data begins behaving like a power law + * \param[out] alpha Double holding the most likely value for the exponent + * \param[out] KS Double holding the Kolmogorov-Smirnov statistic + */ + void GraphProperties::powerlaw(Graph *g, double start, double inc, double end, int &xmin, double &alpha, double &KS ){ + int xm, i, k, n, I; + int prev, pprev; + int size = 1 + (int)(end - start)/inc; + double slogz, L, MLE; + double znorm, denom; + double f, fn, D, tD; + double exp; + + vector x; + deg_dist(g, x); + + //Holds the possible \alpha values from start to end with a delta of increment + vector< double > vec( size ); + //Holds the zeta of the \alpha values, since it is used a lot, no need to keep calculating + vector< double > zvec( size ); + f = start; + for (i = 0; i < size; i++ ){ + vec[i] = f; + zvec[i] = boost::math::zeta(f); + f += increment; + } + + sort(x.begin(), x.end()); + + KS = -1; + prev = 0; + for ( xm = 0; xm < x.size(); xm++ ){ + if(x[xm] == prev){ + continue; + } + + n = x.size() - xm; + + slogz = 0; + for(i=xm; i MLE){ + MLE = L; I = k; + } + } else { + MLE = L; I = k; + } + } + + //compute KS statistic + exp = vec[I]; + + znorm = 0; + for(i=1; i D){ + D = tD; + } + + pprev = x[i]; + } + + if(KS > -1){ + if(D < KS){ + KS = D; xmin = x[xm]; alpha = exp; + } + } else { + KS = D; xmin = x[xm]; alpha = exp; + } + + prev = x[xm]; + } + } + /** * Calculates the degree assortativity of a graph g * \param[in] g input graph From 67a31c17eea0d7ed60eeb6df57827040d0a0bcf6 Mon Sep 17 00:00:00 2001 From: Matt Baker Date: Wed, 10 Jul 2013 15:05:33 -0400 Subject: [PATCH 15/73] create a self tester for eigen solver, requres a define at compile time --- lib_graphd/src/GraphProperties.cpp | 52 ++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/lib_graphd/src/GraphProperties.cpp b/lib_graphd/src/GraphProperties.cpp index d07678d..da11f28 100644 --- a/lib_graphd/src/GraphProperties.cpp +++ b/lib_graphd/src/GraphProperties.cpp @@ -969,6 +969,50 @@ namespace Graph { coeff = (n1 - n2) / (de - n2); } // deg_assortativity + + /** + * Built in self tester for the eigen solver. Looks at Ax - yx and looks for the + * largest magnitude of error. + */ + void check_eigen_values(Mat A, Vec eigen_vec, PetscScalar eigen_val) { + Vec xr, xi, xr2, result1, result2; + MatGetVecs(A, PETSC_NULL, &xr2); + MatGetVecs(A, PETSC_NULL, &result1); + MatGetVecs(A, PETSC_NULL, &result2); + + cout << "Eigen vector is:\n"; + VecView(eigen_vec,PETSC_VIEWER_STDOUT_SELF); + cout << "Eigen value is: " << eigen_val << endl; + + MatMult(A,eigen_vec,result1); + VecSet(xr2,eigen_val); + VecPointwiseMult(result2,xr2,eigen_vec); + cout << "Ax = " << endl; + VecView(result1,PETSC_VIEWER_STDOUT_SELF); + cout << "yx = " << endl; + VecView(result1,PETSC_VIEWER_STDOUT_SELF); + PetscScalar *a; + PetscScalar *b; + VecGetArray(result1, &a); + VecGetArray(result2, &b); + PetscInt size; + VecGetLocalSize(result1, &size); + double max = 0.0,current; + for(int idx=0; idx < size; idx++) { + current = fabs(a[idx] - b[idx]); + max = current > max ? current : max; + } + cout << "Magnitude of greatest error is: " << max << endl; + VecRestoreArray(result1, &a); + VecRestoreArray(result2, &b); + } + + /** + * looks for eigen values in the adjacency matrix + * \param[in] g input graph + * \param[out] eigen_values vector of eigen values found + * \param[in] spread the number of values wanted, spread high values and spred low values, so eigen_values can be upto 2*spread in size + */ void GraphProperties::eigen_spectrum(Graph *g, vector &eigen_values, int spread) { #ifndef HAS_SLEPC fatal_error("Called SLEPC eigen solvers without HAS_SLEPC.\n"); @@ -991,6 +1035,14 @@ namespace Graph { for(int idx=0; idx < nconv; idx++) { EPSGetEigenvalue(eps,idx,&kr,&ki); eigen_values[idx] = kr; +#ifdef EIGENSOLVER_SELFTEST + //built in self tester. Don't use in production runs. + Vec xr, xi; + MatGetVecs(g->PetscMat, PETSC_NULL, &xr); + MatGetVecs(g->PetscMat, PETSC_NULL, &xi); + EPSGetEigenpair(eps,idx,&kr,&ki, xr, xi); + check_eigen_values(g->PetscMat, xr, kr); +#endif } EPSDestroy(&eps); From fdab34c4a9513ed65c457df6f9818185edba1ffc Mon Sep 17 00:00:00 2001 From: Jonathan Schrock Date: Wed, 10 Jul 2013 15:29:57 -0400 Subject: [PATCH 16/73] Power Law fitting added to GraphProperties and compiles. Added a gtest, but currently doesn't work. --- lib_graphd/inc/GraphDecomposition.h | 3 +++ lib_graphd/inc/GraphProperties.h | 4 ++-- lib_graphd/src/GraphProperties.cpp | 13 ++++++------- lib_graphd/test/GraphPropertyTest.cpp | 9 +++++++++ 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/lib_graphd/inc/GraphDecomposition.h b/lib_graphd/inc/GraphDecomposition.h index 5437c3a..54906ae 100644 --- a/lib_graphd/inc/GraphDecomposition.h +++ b/lib_graphd/inc/GraphDecomposition.h @@ -46,6 +46,9 @@ #include #include #include + +#include + #include #include #include diff --git a/lib_graphd/inc/GraphProperties.h b/lib_graphd/inc/GraphProperties.h index 7e66390..7706e7f 100644 --- a/lib_graphd/inc/GraphProperties.h +++ b/lib_graphd/inc/GraphProperties.h @@ -22,7 +22,6 @@ #ifndef GRAPHPROPERTIES_H_ #define GRAPHPROPERTIES_H_ #include "GraphDecomposition.h" -#include using namespace std; @@ -126,7 +125,8 @@ namespace Graph { /** * \brief Fits the degree distribution of the specified graph to a power law distribution */ - void powerlaw(Graph *g, double start, double inc, double end, int &xmin, double &alpha, double &KS ){ + //void powerlaw(Graph *g, double start = 1.5, double inc = 0.01, double end = 3.5, int &xmin, double &alpha, double &KS ); + void powerlaw(Graph *g, int &xmin, double &alpha, double &KS, double start = 1.5, double inc = 0.01, double end = 3.5); /** * \brief Returns the degree assortativity coefficient of a graph diff --git a/lib_graphd/src/GraphProperties.cpp b/lib_graphd/src/GraphProperties.cpp index 215b269..6738e67 100644 --- a/lib_graphd/src/GraphProperties.cpp +++ b/lib_graphd/src/GraphProperties.cpp @@ -927,14 +927,14 @@ namespace Graph { /** * Fits the degree distribution of g to a power law distribution * \param[in] g Pointer to a graph - * \param[in] start Lower bound for exponent, defaults to 1.5 - * \param[in] inc Determines granularity of the exponent search range, defaults to 0.01 - * \param[in] end Upper bound for exponent, defaults to 3.5 * \param[out] xmin Integer value holding the degree at which the data begins behaving like a power law * \param[out] alpha Double holding the most likely value for the exponent * \param[out] KS Double holding the Kolmogorov-Smirnov statistic + * \param[in] start Lower bound for exponent, defaults to 1.5 + * \param[in] inc Determines granularity of the exponent search range, defaults to 0.01 + * \param[in] end Upper bound for exponent, defaults to 3.5 */ - void GraphProperties::powerlaw(Graph *g, double start, double inc, double end, int &xmin, double &alpha, double &KS ){ + void GraphProperties::powerlaw(Graph *g, int &xmin, double &alpha, double &KS, double start, double inc, double end){ int xm, i, k, n, I; int prev, pprev; int size = 1 + (int)(end - start)/inc; @@ -946,7 +946,7 @@ namespace Graph { vector x; deg_dist(g, x); - //Holds the possible \alpha values from start to end with a delta of increment + //Holds the possible \alpha values from start to end with a delta of inc vector< double > vec( size ); //Holds the zeta of the \alpha values, since it is used a lot, no need to keep calculating vector< double > zvec( size ); @@ -954,7 +954,7 @@ namespace Graph { for (i = 0; i < size; i++ ){ vec[i] = f; zvec[i] = boost::math::zeta(f); - f += increment; + f += inc; } sort(x.begin(), x.end()); @@ -987,7 +987,6 @@ namespace Graph { L = -exp * slogz - n * log( zvec[k] - znorm ); - //TODO: try to make these more compact or unneeded if(MLE != -1){ if(L > MLE){ MLE = L; I = k; diff --git a/lib_graphd/test/GraphPropertyTest.cpp b/lib_graphd/test/GraphPropertyTest.cpp index 369e43b..0e90c2e 100644 --- a/lib_graphd/test/GraphPropertyTest.cpp +++ b/lib_graphd/test/GraphPropertyTest.cpp @@ -174,3 +174,12 @@ TEST_F(GraphPropertyTest, testDegDist){ properties.deg_dist(mg, dist); EXPECT_EQ(4, dist[33]); } + +TEST_F(GraphPropertyTest, testPowerLaw){ + int xmin; + double alpha, KS; + properties.powerlaw(mg, xmin, alpha, KS); + EXPECT_EQ(18, xmin); + EXPECT_EQ(3.5, alpha); + EXPECT_EQ(0.470626, KS); +} From 07a645d87da7c7a1d2cb29d0b99ad29f991fa157 Mon Sep 17 00:00:00 2001 From: Jonathan Schrock Date: Thu, 11 Jul 2013 16:38:49 -0400 Subject: [PATCH 17/73] Power law fitting has been added as well as a gtest for it. Need boost/math/special_functions/zeta.hpp and accompanying headers to compile. Also, the directory holding these headers needs to be included in lib_graphd/src/Makefile --- lib_graphd/src/GraphProperties.cpp | 61 +++++++++++++++------------ lib_graphd/test/GraphPropertyTest.cpp | 7 ++- 2 files changed, 39 insertions(+), 29 deletions(-) diff --git a/lib_graphd/src/GraphProperties.cpp b/lib_graphd/src/GraphProperties.cpp index 6738e67..ac2716f 100644 --- a/lib_graphd/src/GraphProperties.cpp +++ b/lib_graphd/src/GraphProperties.cpp @@ -935,23 +935,22 @@ namespace Graph { * \param[in] end Upper bound for exponent, defaults to 3.5 */ void GraphProperties::powerlaw(Graph *g, int &xmin, double &alpha, double &KS, double start, double inc, double end){ - int xm, i, k, n, I; - int prev, pprev; - int size = 1 + (int)(end - start)/inc; + int xm, i, k, n, I; + int prev, pprev; + int size = 1 + (int)(end - start) / inc; double slogz, L, MLE; - double znorm, denom; + double znorm, denom; double f, fn, D, tD; - double exp; + double exp; - vector x; - deg_dist(g, x); + vector x(g->degree); //Holds the possible \alpha values from start to end with a delta of inc vector< double > vec( size ); //Holds the zeta of the \alpha values, since it is used a lot, no need to keep calculating vector< double > zvec( size ); f = start; - for (i = 0; i < size; i++ ){ + for(i = 0; i < size; i++ ){ vec[i] = f; zvec[i] = boost::math::zeta(f); f += inc; @@ -961,7 +960,7 @@ namespace Graph { KS = -1; prev = 0; - for ( xm = 0; xm < x.size(); xm++ ){ + for( xm = 0; xm < x.size(); xm++ ){ if(x[xm] == prev){ continue; } @@ -969,30 +968,33 @@ namespace Graph { n = x.size() - xm; slogz = 0; - for(i=xm; i MLE){ - MLE = L; I = k; + MLE = L; + I = k; } - } else { - MLE = L; I = k; + } + else { + MLE = L; + I = k; } } @@ -1000,7 +1002,7 @@ namespace Graph { exp = vec[I]; znorm = 0; - for(i=1; i D){ @@ -1027,17 +1029,22 @@ namespace Graph { pprev = x[i]; } - if(KS > -1){ + if(KS > -1){ if(D < KS){ - KS = D; xmin = x[xm]; alpha = exp; + KS = D; + xmin = x[xm]; + alpha = exp; } - } else { - KS = D; xmin = x[xm]; alpha = exp; + } + else { + KS = D; + xmin = x[xm]; + alpha = exp; } prev = x[xm]; } - } + } // powerlaw /** * Calculates the degree assortativity of a graph g diff --git a/lib_graphd/test/GraphPropertyTest.cpp b/lib_graphd/test/GraphPropertyTest.cpp index 0e90c2e..89cf67d 100644 --- a/lib_graphd/test/GraphPropertyTest.cpp +++ b/lib_graphd/test/GraphPropertyTest.cpp @@ -19,6 +19,8 @@ */ +#include + #include "Log.h" #include "GraphCreatorFile.h" #include "Graph.h" @@ -171,6 +173,7 @@ TEST_F(GraphPropertyTest, testAvgDegree){ TEST_F(GraphPropertyTest, testDegDist){ vector dist; + properties.deg_dist(mg, dist); EXPECT_EQ(4, dist[33]); } @@ -180,6 +183,6 @@ TEST_F(GraphPropertyTest, testPowerLaw){ double alpha, KS; properties.powerlaw(mg, xmin, alpha, KS); EXPECT_EQ(18, xmin); - EXPECT_EQ(3.5, alpha); - EXPECT_EQ(0.470626, KS); + EXPECT_LT(abs(3.5 - alpha), 0.1); + EXPECT_LT(abs(0.470626 - KS), 0.000001); } From 807ebc1ab00808a23c6f4e86f7b7a04baa922dba Mon Sep 17 00:00:00 2001 From: Matthew Baker Date: Mon, 15 Jul 2013 13:44:08 -0400 Subject: [PATCH 18/73] Log macros are broken in some configurations. Disable them for now. --- make.inc.parallel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make.inc.parallel b/make.inc.parallel index 6b8e960..f71a380 100644 --- a/make.inc.parallel +++ b/make.inc.parallel @@ -35,7 +35,7 @@ HAS_MADNESS = 1 # madness is included in the INDDGO distribution, and is required to be compiled for successful parallel execution of WIS. #use this to turn logging on/off -LOG_ENABLED = 1 +LOG_ENABLED = 0 #---------------------------------------------------------------- # OPTIONAL USER-SUPPLIED DIRECTORY VARIABLES From ba459d03cfdb6a7fd8d11c019b25d0ec15d50b9d Mon Sep 17 00:00:00 2001 From: Matthew Baker Date: Mon, 15 Jul 2013 13:56:47 -0400 Subject: [PATCH 19/73] add macosx option --- make.inc.parallel | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/make.inc.parallel b/make.inc.parallel index f71a380..55c395f 100644 --- a/make.inc.parallel +++ b/make.inc.parallel @@ -33,6 +33,8 @@ HAS_SLEPC = 1 IS_PARALLEL = 1 HAS_MADNESS = 1 # madness is included in the INDDGO distribution, and is required to be compiled for successful parallel execution of WIS. +MAC_OSX = 0 +#some compiler flags cause problems on MacOSX. Set this to 1 if you're having problems compiling on OSX. #use this to turn logging on/off LOG_ENABLED = 0 @@ -82,7 +84,7 @@ endif ifeq ($(HAS_MADNESS),1) CXX = mpicxx ifeq ($(OLDGCC), 1) -CFLAGS := $(CFLAGS) -D__MADNESS__ -D_OLDGCC -Wno-strict-aliasing -Wno-deprecated -ffast-math +CFLAGS := $(CFLAGS) -D__MADNESS__ -D_OLDGCC -Wno-strict-aliasing -Wno-deprecated -ffast-math endif ifeq ($(OLDGCC), 0) CPPFLAGS := $(CPPFLAGS) -std=c++0x @@ -90,6 +92,10 @@ CFLAGS := $(CFLAGS) -D__MADNESS__ -std=c++0x -Wno-strict-aliasing -Wno-deprecate endif endif +ifneq ($(MAC_OSX),1) +CFLAGS := $(CFLAGS) -march=native +endif + ifeq ($(IS_PARALLEL),1) CXX = mpicxx CFLAGS := $(CFLAGS) -D__PARALLEL__ -D__OPENMP__ -fopenmp From d191b21548ef56e4cce35bab743f25cf03704561 Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Tue, 16 Jul 2013 17:47:40 -0400 Subject: [PATCH 20/73] starting to add in boost shortest paths --- lib_graphd/inc/Graph.h | 22 +++++++++++ lib_graphd/inc/GraphProperties.h | 18 +++++++++ lib_graphd/inc/GraphUtil.h | 9 +++++ lib_graphd/src/GraphProperties.cpp | 61 +++++++++++++++++++++++++++++- lib_graphd/src/GraphUtil.cpp | 37 ++++++++++++++++++ util/src/graph_stats.cpp | 15 +++++++- 6 files changed, 160 insertions(+), 2 deletions(-) diff --git a/lib_graphd/inc/Graph.h b/lib_graphd/inc/Graph.h index 54e79d8..e6d9c99 100644 --- a/lib_graphd/inc/Graph.h +++ b/lib_graphd/inc/Graph.h @@ -35,10 +35,27 @@ #include "Log.h" #include +#ifdef HAS_BOOST + #include + #include + #include + + #include "boost/graph/adjacency_list.hpp" + #include "boost/graph/topological_sort.hpp" + #include +#endif + using namespace std; #define INDDGO_INFINITY INT_MAX - 16 +#ifdef HAS_BOOST + typedef boost::property EdgeWeightProperty; + typedef boost::adjacency_list BoostUndirected; + typedef boost::graph_traits < BoostUndirected >::vertex_descriptor vertex_descriptor; + typedef boost::graph_traits < BoostUndirected >::edge_descriptor edge_descriptor; +#endif //HAS_BOOST + namespace Graph { class Graph : public GraphInterface { @@ -62,6 +79,11 @@ namespace Graph { vector adj_vec; vector< vector > apsp_dist; + #ifdef HAS_BOOST + BoostUndirected *boost_graph; + #endif //HAS_BOOST + + public: Graph(); Graph(int n); diff --git a/lib_graphd/inc/GraphProperties.h b/lib_graphd/inc/GraphProperties.h index 2fbe6e4..ee370ef 100644 --- a/lib_graphd/inc/GraphProperties.h +++ b/lib_graphd/inc/GraphProperties.h @@ -23,6 +23,12 @@ #define GRAPHPROPERTIES_H_ #include "GraphDecomposition.h" +#ifdef HAS_BOOST + #include "boost/graph/adjacency_list.hpp" + #include "boost/graph/topological_sort.hpp" +#endif + + using namespace std; namespace Graph { @@ -72,6 +78,18 @@ namespace Graph { */ void paths_dijkstra_single(Graph *g, vector &p, int source); + #ifdef HAS_BOOST + /** + * \brief returns shortest paths from source to all other nodes + */ + void paths_dijkstra_boost_single(Graph *g, vector &dists, int source); + + /** + * \brief returns shortest paths from all nodes to all nodes + */ + void paths_dijkstra_boost_all(Graph *g, vector< vector > &p); + #endif + /** * \brief returns shortest paths from source to all other nodes */ diff --git a/lib_graphd/inc/GraphUtil.h b/lib_graphd/inc/GraphUtil.h index 3deb122..1491f02 100644 --- a/lib_graphd/inc/GraphUtil.h +++ b/lib_graphd/inc/GraphUtil.h @@ -64,6 +64,15 @@ namespace Graph { void populate_CRS(Graph *g); void free_CRS(Graph *g); + #ifdef HAS_BOOST + /** + * \brief Populate the boost version of the graph + */ + void populate_boost(Graph *g); + #endif + + + //uses V as a vertex separator of G. Returns the number of components in G\V, and fills in members with their vertex lists.. int vertex_separator(Graph *g, list *V, vector *> *members); diff --git a/lib_graphd/src/GraphProperties.cpp b/lib_graphd/src/GraphProperties.cpp index 379b7ca..dc01a2e 100644 --- a/lib_graphd/src/GraphProperties.cpp +++ b/lib_graphd/src/GraphProperties.cpp @@ -618,6 +618,61 @@ namespace Graph { global_cc = (double)num_triangles / (double)total_possible_triangles; } // clustering_coefficients + #ifdef HAS_BOOST + /** + * We assume that edge weights are all 1 + * + * \param[in] g input graph + * \param[in] source node id + * \param[out] p path distances from source to all other vertices + */ + void GraphProperties::paths_dijkstra_boost_single(Graph *g, vector &dists, int source){ + BoostUndirected *bg = g->boost_graph; + std::vector p(boost::num_vertices(*bg)); + dists.resize(g->get_num_nodes()); + //std::vector d(boost::num_vertices(*bg)); + vertex_descriptor s = vertex(source, *bg); + boost::dijkstra_shortest_paths(*bg, s, boost::predecessor_map(&p[0]).distance_map(&dists[0])); + + } + /** + * All pairs shortest paths + * \param[in] g input graph + * \param[out] p multidimentional list of all pairs shortest paths + */ + + void GraphProperties::paths_dijkstra_boost_all(Graph *g, vector< vector > &pAll){ + int inf = INDDGO_INFINITY; + + int minD = inf; + const int n = g->get_num_nodes(); + + pAll.resize(n); + + //#pragma omp parallel for default(none) shared(g, inf, pAll) private(nvisiting, nVisited, nv) firstprivate(dist, minD, visited) + #pragma omp parallel for schedule(dynamic, 8) default(none) shared(g, inf, pAll) + //loop over all vertices + for(int v = 0; v < n; v++){ //0; v < n; v++){ + //reset all distances to INF and mark all vertices as unvisited + fill(pAll[v].begin(),pAll[v].end(),inf); + paths_dijkstra_boost_single(g, pAll[v], v); //stores shortest paths from this vertex to all in pAll[v] + } //end loop over vertices + + //store the results + g->set_shortest_path_dist(pAll); + // + //print out results + //for(int i = 0; i < n; i++){ + // for (int j = 0; j < n; j++) { + // printf("%d, ",pAll[i][j]); + // } + // printf("\n"); + //} + //printf("\n"); + } + + #endif + /** * We assume that edge weights are all 1 * @@ -653,6 +708,7 @@ namespace Graph { list::const_iterator lcit; Node *u; int d; + fprintf(stderr, "Entering for loop, k=0->%d\n",n); for(k = 0; k < n; k++){ hn = iheap_take(&heap); i = (long)(hn->value); @@ -660,11 +716,13 @@ namespace Graph { // trying this for speed u = &(g->nodes[i]); dists[i] = d; + fprintf(stderr, "d is: %d\n",d); const list &nbrs = u->get_nbrs_ref(); for(lcit = nbrs.begin(); lcit != nbrs.end(); ++lcit){ hn = heapnodes[*lcit]; if(d + 1 < hn->key){ + fprintf(stderr,"running decrease on node %d\n",k); iheap_decrease(&heap, hn, d + 1); } } @@ -804,7 +862,8 @@ namespace Graph { // printf("\n"); //} //printf("\n"); - } //paths_dijkstra_all + } //paths_dijkstra_heap_all + /** * Calcuates the eccentricity for each vertex (max dist to any other vertex) * \param[in] g input graph diff --git a/lib_graphd/src/GraphUtil.cpp b/lib_graphd/src/GraphUtil.cpp index 3bcc992..51747e5 100644 --- a/lib_graphd/src/GraphUtil.cpp +++ b/lib_graphd/src/GraphUtil.cpp @@ -19,8 +19,18 @@ */ +#include "GraphUtil.h" #include "GraphDecomposition.h" +#ifdef HAS_BOOST + #include + #include + #include + + #include "boost/graph/adjacency_list.hpp" + #include "boost/graph/topological_sort.hpp" +#endif + namespace Graph { GraphUtil::GraphUtil(){ } @@ -498,6 +508,33 @@ namespace Graph { g->adjncy.clear(); } + #ifdef HAS_BOOST + /** + * Populates the boost_graph member of g + * \param[in] g the input graph + */ + void GraphUtil::populate_boost(Graph *g){ + const int n = g->get_num_nodes(); + int v; + boost::graph_traits < BoostUndirected >::vertex_descriptor a, b; + list::const_iterator it; + g->boost_graph = new BoostUndirected(n); + BoostUndirected *bg = g->boost_graph; + for(v=0;v &nbrs = g->get_node(v)->get_nbrs_ref(); + for(it=nbrs.begin(); it!=nbrs.end(); ++it){ + if(v<*it){ + a = boost::vertex(v, *bg); + b = boost::vertex(*it, *bg); + boost::add_edge(a, b, 1, *bg); + } + } + } + } + + #endif //HAS_BOOST + + /** * Non-recursive function that fills the members vector with the * lists of nodes belonging to the components. The members vector diff --git a/util/src/graph_stats.cpp b/util/src/graph_stats.cpp index 41af83d..9f8dfb9 100644 --- a/util/src/graph_stats.cpp +++ b/util/src/graph_stats.cpp @@ -41,7 +41,7 @@ void print_time(string prefix, ORB_t start, ORB_t end){ cout << prefix + ": " << ORB_seconds(end, start) << endl; } -const string allowed_methods ("edge_density,avg_degree,degree_dist,global_cc,avg_cc,local_ccs,shortest_paths,assortativity,eccentricity,eccentricity_dist,expansion,avg_shortest_path,shortest_paths_heap"); +const string allowed_methods ("edge_density,avg_degree,degree_dist,global_cc,avg_cc,local_ccs,shortest_paths,assortativity,eccentricity,eccentricity_dist,expansion,avg_shortest_path,shortest_paths_heap,shortest_paths_boost"); /** * Creates a map from a comma-separated string @@ -138,6 +138,7 @@ int main(int argc, char **argv){ Graph::Graph g; Graph::GraphReader gr; Graph::GraphProperties gp; + Graph::GraphUtil gu; cout << "Reading graph" << endl; ORB_read(t1); @@ -236,6 +237,18 @@ int main(int argc, char **argv){ ORB_read(t2); print_time("Time(shortest_paths_dijkstra)", t1, t2); } + if(req_methods["shortest_paths_boost"] == true){ + cout << "Creating BOOST representation of g" << endl; + ORB_read(t1); + gu.populate_boost(&g); + ORB_read(t2); + print_time("Time(populate_boost)", t1, t2); + cout << "Calculating shortest paths (boost)" << endl; + ORB_read(t1); + gp.paths_dijkstra_boost_all(&g, shortest_path_distances); + ORB_read(t2); + print_time("Time(shortest_paths_dijkstra_boost)", t1, t2); + } if(req_methods["eccentricity"] == true){ cout << "Calculating eccentricities" << endl; ORB_read(t1); From fedb98de03e346a29072869f207cbd3510246faf Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Wed, 17 Jul 2013 13:02:15 -0400 Subject: [PATCH 21/73] clean up code; final boost changes --- lib_graphd/inc/Graph.h | 23 +++++++------- lib_graphd/inc/GraphProperties.h | 5 ++- lib_graphd/inc/GraphUtil.h | 2 -- lib_graphd/src/GraphProperties.cpp | 33 +++++++++++--------- lib_graphd/src/GraphUtil.cpp | 49 +++++++++++++++--------------- 5 files changed, 55 insertions(+), 57 deletions(-) diff --git a/lib_graphd/inc/Graph.h b/lib_graphd/inc/Graph.h index e6d9c99..1695092 100644 --- a/lib_graphd/inc/Graph.h +++ b/lib_graphd/inc/Graph.h @@ -36,13 +36,13 @@ #include #ifdef HAS_BOOST - #include - #include - #include + #include + #include + #include - #include "boost/graph/adjacency_list.hpp" - #include "boost/graph/topological_sort.hpp" - #include + #include "boost/graph/adjacency_list.hpp" + #include "boost/graph/topological_sort.hpp" + #include #endif using namespace std; @@ -50,10 +50,10 @@ using namespace std; #define INDDGO_INFINITY INT_MAX - 16 #ifdef HAS_BOOST - typedef boost::property EdgeWeightProperty; - typedef boost::adjacency_list BoostUndirected; - typedef boost::graph_traits < BoostUndirected >::vertex_descriptor vertex_descriptor; - typedef boost::graph_traits < BoostUndirected >::edge_descriptor edge_descriptor; +typedef boost::property EdgeWeightProperty; +typedef boost::adjacency_list BoostUndirected; +typedef boost::graph_traits < BoostUndirected >::vertex_descriptor vertex_descriptor; +typedef boost::graph_traits < BoostUndirected >::edge_descriptor edge_descriptor; #endif //HAS_BOOST namespace Graph { @@ -80,10 +80,9 @@ namespace Graph { vector< vector > apsp_dist; #ifdef HAS_BOOST - BoostUndirected *boost_graph; + BoostUndirected *boost_graph; #endif //HAS_BOOST - public: Graph(); Graph(int n); diff --git a/lib_graphd/inc/GraphProperties.h b/lib_graphd/inc/GraphProperties.h index ee370ef..d227ce4 100644 --- a/lib_graphd/inc/GraphProperties.h +++ b/lib_graphd/inc/GraphProperties.h @@ -24,11 +24,10 @@ #include "GraphDecomposition.h" #ifdef HAS_BOOST - #include "boost/graph/adjacency_list.hpp" - #include "boost/graph/topological_sort.hpp" + #include "boost/graph/adjacency_list.hpp" + #include "boost/graph/topological_sort.hpp" #endif - using namespace std; namespace Graph { diff --git a/lib_graphd/inc/GraphUtil.h b/lib_graphd/inc/GraphUtil.h index 1491f02..2f938bd 100644 --- a/lib_graphd/inc/GraphUtil.h +++ b/lib_graphd/inc/GraphUtil.h @@ -71,8 +71,6 @@ namespace Graph { void populate_boost(Graph *g); #endif - - //uses V as a vertex separator of G. Returns the number of components in G\V, and fills in members with their vertex lists.. int vertex_separator(Graph *g, list *V, vector *> *members); diff --git a/lib_graphd/src/GraphProperties.cpp b/lib_graphd/src/GraphProperties.cpp index dc01a2e..d7e954c 100644 --- a/lib_graphd/src/GraphProperties.cpp +++ b/lib_graphd/src/GraphProperties.cpp @@ -633,8 +633,8 @@ namespace Graph { //std::vector d(boost::num_vertices(*bg)); vertex_descriptor s = vertex(source, *bg); boost::dijkstra_shortest_paths(*bg, s, boost::predecessor_map(&p[0]).distance_map(&dists[0])); - } + /** * All pairs shortest paths * \param[in] g input graph @@ -660,18 +660,9 @@ namespace Graph { //store the results g->set_shortest_path_dist(pAll); - // - //print out results - //for(int i = 0; i < n; i++){ - // for (int j = 0; j < n; j++) { - // printf("%d, ",pAll[i][j]); - // } - // printf("\n"); - //} - //printf("\n"); - } + } // paths_dijkstra_boost_all - #endif + #endif // ifdef HAS_BOOST /** * We assume that edge weights are all 1 @@ -691,6 +682,8 @@ namespace Graph { dists.resize(n,INDDGO_INFINITY); dists[source] = 0; + fprintf(stderr, "Running paths_dijkstra_heap_single on with source node %d\n", source); + fprintf(stderr, "INDDGO_INFINITY is %d\n",INDDGO_INFINITY); iheap_init(&heap); heapnodes = (struct iheap_node **)malloc(n * sizeof(iheap_node *)); @@ -698,7 +691,7 @@ namespace Graph { for(i = 0; i < n; i++){ // insert all of our nodes into the heap heapnodes[i] = (struct iheap_node *)malloc(sizeof(struct iheap_node)); hn = heapnodes[i]; - iheap_node_init(hn, dists[i], (void *)(i)); + iheap_node_init_ref(&hn, dists[i], (void *)(i)); iheap_insert(&heap, hn); //iheap_node_init(hn, dist[n], g->get_node(i)); } @@ -710,23 +703,33 @@ namespace Graph { int d; fprintf(stderr, "Entering for loop, k=0->%d\n",n); for(k = 0; k < n; k++){ + //if(k == source){ + // continue; + //} hn = iheap_take(&heap); i = (long)(hn->value); + fprintf(stderr, " Iteration %d ", k); + fprintf(stderr, " Got i: %lu\n",i); d = hn->key; // trying this for speed u = &(g->nodes[i]); dists[i] = d; - fprintf(stderr, "d is: %d\n",d); + fprintf(stderr, " d is: %d\n",d); const list &nbrs = u->get_nbrs_ref(); for(lcit = nbrs.begin(); lcit != nbrs.end(); ++lcit){ + fprintf(stderr," Looking at edge (%d,%d)\n", i, *lcit); hn = heapnodes[*lcit]; if(d + 1 < hn->key){ - fprintf(stderr,"running decrease on node %d\n",k); + fprintf(stderr," running decrease on node %d, new key should be %d\n",hn->value, d + 1); iheap_decrease(&heap, hn, d + 1); } } } + fprintf(stderr,"Distances: \n"); + for(k = 0; k < n; k++){ + fprintf(stderr, "%d: %d\n",k, dists[k]); + } } // paths_dijkstra_heap_single /** diff --git a/lib_graphd/src/GraphUtil.cpp b/lib_graphd/src/GraphUtil.cpp index 51747e5..18fbc38 100644 --- a/lib_graphd/src/GraphUtil.cpp +++ b/lib_graphd/src/GraphUtil.cpp @@ -23,12 +23,12 @@ #include "GraphDecomposition.h" #ifdef HAS_BOOST - #include - #include - #include + #include + #include + #include - #include "boost/graph/adjacency_list.hpp" - #include "boost/graph/topological_sort.hpp" + #include "boost/graph/adjacency_list.hpp" + #include "boost/graph/topological_sort.hpp" #endif namespace Graph { @@ -509,32 +509,31 @@ namespace Graph { } #ifdef HAS_BOOST - /** - * Populates the boost_graph member of g - * \param[in] g the input graph - */ - void GraphUtil::populate_boost(Graph *g){ - const int n = g->get_num_nodes(); - int v; - boost::graph_traits < BoostUndirected >::vertex_descriptor a, b; - list::const_iterator it; - g->boost_graph = new BoostUndirected(n); - BoostUndirected *bg = g->boost_graph; - for(v=0;v &nbrs = g->get_node(v)->get_nbrs_ref(); - for(it=nbrs.begin(); it!=nbrs.end(); ++it){ - if(v<*it){ - a = boost::vertex(v, *bg); - b = boost::vertex(*it, *bg); - boost::add_edge(a, b, 1, *bg); - } + /** + * Populates the boost_graph member of g + * \param[in] g the input graph + */ + void GraphUtil::populate_boost(Graph *g){ + const int n = g->get_num_nodes(); + int v; + boost::graph_traits < BoostUndirected >::vertex_descriptor a, b; + list::const_iterator it; + g->boost_graph = new BoostUndirected(n); + BoostUndirected *bg = g->boost_graph; + for(v = 0; v < n; v++){ + const list &nbrs = g->get_node(v)->get_nbrs_ref(); + for(it = nbrs.begin(); it != nbrs.end(); ++it){ + if(v < *it){ + a = boost::vertex(v, *bg); + b = boost::vertex(*it, *bg); + boost::add_edge(a, b, 1, *bg); } } } + } // populate_boost #endif //HAS_BOOST - /** * Non-recursive function that fills the members vector with the * lists of nodes belonging to the components. The members vector From ae4dada76dd70f2c5b2676ef21797374eefb79b3 Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Wed, 17 Jul 2013 13:06:14 -0400 Subject: [PATCH 22/73] adding binomial heap libs --- lib_graphd/inc/binomial-heap/Makefile | 15 + lib_graphd/inc/binomial-heap/bh.py | 434 ++++++++++++++++++ lib_graphd/inc/binomial-heap/heap.h | 381 +++++++++++++++ lib_graphd/inc/binomial-heap/htest | Bin 0 -> 13284 bytes lib_graphd/inc/binomial-heap/htest.c | 125 +++++ lib_graphd/inc/binomial-heap/iheap.h | 385 ++++++++++++++++ lib_graphd/inc/binomial-heap/iheap.h.noinline | 385 ++++++++++++++++ lib_graphd/inc/binomial-heap/iheap.h.orig | 385 ++++++++++++++++ lib_graphd/inc/binomial-heap/ihtest | Bin 0 -> 13145 bytes lib_graphd/inc/binomial-heap/ihtest.c | 116 +++++ 10 files changed, 2226 insertions(+) create mode 100644 lib_graphd/inc/binomial-heap/Makefile create mode 100644 lib_graphd/inc/binomial-heap/bh.py create mode 100644 lib_graphd/inc/binomial-heap/heap.h create mode 100755 lib_graphd/inc/binomial-heap/htest create mode 100644 lib_graphd/inc/binomial-heap/htest.c create mode 100644 lib_graphd/inc/binomial-heap/iheap.h create mode 100644 lib_graphd/inc/binomial-heap/iheap.h.noinline create mode 100644 lib_graphd/inc/binomial-heap/iheap.h.orig create mode 100755 lib_graphd/inc/binomial-heap/ihtest create mode 100644 lib_graphd/inc/binomial-heap/ihtest.c diff --git a/lib_graphd/inc/binomial-heap/Makefile b/lib_graphd/inc/binomial-heap/Makefile new file mode 100644 index 0000000..a0fe929 --- /dev/null +++ b/lib_graphd/inc/binomial-heap/Makefile @@ -0,0 +1,15 @@ + +CFLAGS = -Wall -Wextra -Werror -ansi -std=c99 -pedantic + +ALL = htest ihtest + +.PHONY: clean all + +all: ${ALL} + +clean: + rm -f ${ALL} *.pyc + +htest: htest.c + +ihtest: ihtest.c diff --git a/lib_graphd/inc/binomial-heap/bh.py b/lib_graphd/inc/binomial-heap/bh.py new file mode 100644 index 0000000..6559897 --- /dev/null +++ b/lib_graphd/inc/binomial-heap/bh.py @@ -0,0 +1,434 @@ +#!/usr/bin/env python +# +# Copyright (c) 2008, Bjoern B. Brandenburg +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the copyright holder nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +"""An implementation of Binomial Heaps. + +From Wikipedia: + A binomial heap is a heap similar to a binary heap but also supporting the + operation of merging two heaps quickly. This is achieved by using a special + tree structure. + + All of the following operations work in O(log n) time on a binomial heap with + n elements: + - Insert a new element to the heap + - Find the element with minimum key + - Delete the element with minimum key from the heap + - Decrease key of a given element + - Delete given element from the heap + - Merge two given heaps to one heap + + More details: http://en.wikipedia.org/wiki/Binomial_heap + +This implementation is based on the description in CLRS. +""" + +class ItemRef(object): + """Reference to an item in the heap. Used for decreasing keys and deletion. + Do not use this class directly; only use instances returned by + BinomialHeap.insert()! + + You should only use ItemRef.delete() and ItemRef.decrease(new_priority). + """ + def __init__(self, node, get_heap): + self.ref = node + self.get_heap = get_heap + self.in_tree = True + + def __str__(self): + if self.in_tree: + return "" % str(self.ref.val) + else: + return "" + + def decrease(self, new_key): + "Update the priority of the referenced item to a lower value." + assert self.in_tree + assert self.ref.ref == self + self.ref.decrease(new_key) + + def delete(self): + """Remove the referenced item from the heap. + """ + self.decrease(self) + v = self.get_heap().extract_min() + assert not self.in_tree + assert v is self.ref.val + + def in_heap(self, heap): + """Returns True if the referenced item is part of the BinomialHeap 'heap'; + False otherwise. + """ + return self.in_tree and self.get_heap() == heap + + def __lt__(self, other): + "Behaves like negative infinity: always True." + return True + + def __gt__(self, other): + "Behaves like negative infinity: always False." + return False + + +class BinomialHeap(object): + """Usage: + > H1 = BinomialHeap() + > H1.insert(40, "fast.") + > H1.insert(10, "Merging") + > H2 = BinomialHeap([(30, "quite"), (20, "is")]) + > H1 += H2 + > for x in H1: + > print x, + => "Merging is quite fast." + + """ + + class Node(object): + "Internal node of the heap. Don't use directly." + def __init__(self, get_heap, key, val=None): + self.degree = 0 + self.parent = None + self.next = None + self.child = None + self.key = key + self.ref = ItemRef(self, get_heap) + if val == None: + val = key + self.val = val + + def __str__(self): + k = lambda x: str(x.key) if x else 'NIL' + return '(%s, c:%s, n:%s)' % (k(self), k(self.child), k(self.next)) + + def link(self, other): + "Makes other a subtree of self." + other.parent = self + other.next = self.child + self.child = other + self.degree += 1 + + def decrease(self, new_key): + node = self + assert new_key < node.key + node.key = new_key + cur = node + parent = cur.parent + while parent and cur.key < parent.key: + # need to bubble up + # swap refs + parent.ref.ref, cur.ref.ref = cur, parent + parent.ref, cur.ref = cur.ref, parent.ref + # now swap keys and payload + parent.key, cur.key = cur.key, parent.key + parent.val, cur.val = cur.val, parent.val + # step up + cur = parent + parent = cur.parent + + @staticmethod + def roots_merge(h1, h2): + """Merge two lists of heap roots, sorted by degree. + Returns the new head. + """ + if not h1: + return h2 + if not h2: + return h1 + if h1.degree < h2.degree: + h = h1 + h1 = h.next + else: + h = h2 + h2 = h2.next + p = h + while h2 and h1: + if h1.degree < h2.degree: + p.next = h1 + h1 = h1.next + else: + p.next = h2 + h2 = h2.next + p = p.next + if h2: + p.next = h2 + else: + p.next = h1 + return h + + @staticmethod + def roots_reverse(h): + """Reverse the heap root list. + Returns the new head. Also clears parent references. + """ + if not h: + return None + tail = None + next = h + h.parent = None + while h.next: + next = h.next + h.next = tail + tail = h + h = next + h.parent = None + h.next = tail + return h + + class __Ref(object): + def __init__(self, h): + self.heap = h + self.ref = None + def get_heap_ref(self): + if not self.ref: + return self + else: + # compact + self.ref = self.ref.get_heap_ref() + return self.ref + def get_heap(self): + return self.get_heap_ref().heap + + def __init__(self, lst=[]): + """Populate a new heap with the (key, value) pairs in 'lst'. + If the elements of lst are not subscriptable, then they are treated as + opaque elements and inserted into the heap themselves. + """ + self.head = None + self.size = 0 + self.ref = BinomialHeap.__Ref(self) + for x in lst: + try: + self.insert(x[0], x[1]) + except TypeError: + self.insert(x) + + def insert(self, key, value=None): + """Insert 'value' in to the heap with priority 'key'. If 'value' is omitted, + then 'key' is used as the value. + Returns a reference (of type ItemRef) to the internal node in the tree. + Use this reference to delete the key or to change its priority. + """ + n = BinomialHeap.Node(self.ref.get_heap, key, value) + self.__union(n) + self.size += 1 + return n.ref + + def union(self, other): + """Merge 'other' into 'self'. Returns None. + Note: This is a destructive operation; 'other' is an empty heap afterwards. + """ + self.size = self.size + other.size + h2 = other.head + self.__union(h2) + other.ref.ref = self.ref + other.__init__() + + def min(self): + """Returns the value with the minimum key (= highest priority) in the heap + without removing it, or None if the heap is empty. + """ + pos = self.__min() + return pos[0].val if pos else None + + def extract_min(self): + """Returns the value with the minimum key (= highest priority) in the heap + AND removes it from the heap, or None if the heap is empty. + """ + # find mininum + pos = self.__min() + if not pos: + return None + else: + (x, prev) = pos + # remove from list + if prev: + prev.next = x.next + else: + self.head = x.next + kids = BinomialHeap.Node.roots_reverse(x.child) + self.__union(kids) + x.ref.in_tree = False + self.size -= 1 + return x.val + + def __nonzero__(self): + """True if the heap is not empty; False otherwise.""" + return self.head != None + + def __iter__(self): + """Returns a _destructive_ iterator over the values in the heap. + This violates the iterator protocol slightly, but is very useful. + """ + return self + + def __len__(self): + """Returns the number of items in this heap.""" + return self.size + + def __setitem__(self, key, value): + """Insert. + H[key] = value is equivalent to H.insert(key, value) + """ + self.insert(key, value) + + def __iadd__(self, other): + """Merge. + a += b is equivalent to a.union(b). + """ + self.union(other) + return self + + def next(self): + """Returns the value with the minimum key (= highest priority) in the heap + AND removes it from the heap; raises StopIteration if the heap is empty. + """ + if self.head: + return self.extract_min() + else: + raise StopIteration + + def __contains__(self, ref): + """Test whether a given reference 'ref' (of ItemRef) is in this heap. + """ + if type(ref) != ItemRef: + raise TypeError, "Expected an ItemRef" + else: + return ref.in_heap(self) + + def __min(self): + if not self.head: + return None + min = self.head + min_prev = None + prev = min + cur = min.next + while cur: + if cur.key < min.key: + min = cur + min_prev = prev + prev = cur + cur = cur.next + return (min, min_prev) + + def __union(self, h2): + if not h2: + # nothing to do + return + h1 = self.head + if not h1: + self.head = h2 + return + h1 = BinomialHeap.Node.roots_merge(h1, h2) + prev = None + x = h1 + next = x.next + while next: + if x.degree != next.degree or \ + (next.next and next.next.degree == x.degree): + prev = x + x = next + elif x.key <= next.key: + # x becomes the root of next + x.next = next.next + x.link(next) + else: + # next becomes the root of x + if not prev: + # update the "master" head + h1 = next + else: + # just update previous link + prev.next = next + next.link(x) + # x is not toplevel anymore, update ref by advancing + x = next + next = x.next + self.head = h1 + +def heap(lst=[]): + """Create a new heap. lst should be a sequence of (key, value) pairs. + Shortcut for BinomialHeap(lst) + """ + return BinomialHeap(lst) + +if __name__ == "__main__": + tokens1 = [(24, 'all'), (16, 'star'), (9, 'true.\nSinging'), (7, 'clear'), + (25, 'praises'), (13, 'to'), (5, 'Heel'), + (6, 'voices\nRinging'), (26, 'thine.'), (21, 'shine\nCarolina'), + (117, 'Rah,'), (102, 'Tar'), (108, 'bred\nAnd'), (125, 'Rah!'), + (107, 'Heel'), (118, 'Rah,'), (111, "die\nI'm"), + (115, 'dead.\nSo'), (120, 'Rah,'), (121, "Car'lina-lina\nRah,"), + (109, 'when'), (105, 'a'), (123, "Car'lina-lina\nRah!"), + (110, 'I'), (114, 'Heel'), (101, 'a'), (106, 'Tar'), + (18, 'all\nClear'), (14, 'the')] + tokens2 = [(113, 'Tar'), (124, 'Rah!'), (112, 'a'), (103, 'Heel'), + (104, "born\nI'm"), (122, 'Rah,'), (119, "Car'lina-lina\nRah,"), + (2, 'sound'), (20, 'radiance'), (12, 'N-C-U.\nHail'), + (10, "Carolina's"), (3, 'of'), (17, 'of'), + (23, 'gem.\nReceive'), (19, 'its'), (0, '\nHark'), + (22, 'priceless'), (4, 'Tar'), (1, 'the'), (8, 'and'), + (15, 'brightest'), (11, 'praises.\nShouting'), + (100, "\nI'm"), (116, "it's")] + h1 = heap(tokens1) + h2 = heap(tokens2) + h3 = heap() + line = "\n===================================" + h3[90] = line + h3[-2] = line + h3[200] = line + h3[201] = '\n\n' + t1ref = h3.insert(1000, "\nUNC Alma Mater:") + t2ref = h3.insert(120, "\nUNC Fight Song:") + bad = [h3.insert(666, "Dook"), + h3.insert(666, "Go Devils!"), + h3.insert(666, "Blue Devils") ] + + ref = bad[0] + print "%s: \n\tin h1: %s\n\tin h2: %s\n\tin h3: %s" % \ + (str(ref), ref in h1, ref in h2, ref in h3) + + print "Merging h3 into h2..." + h2 += h3 + + print "%s: \n\tin h1: %s\n\tin h2: %s\n\tin h3: %s" % \ + (str(ref), ref in h1, ref in h2, ref in h3) + + print "Merging h2 into h1..." + h1 += h2 + + print "%s: \n\tin h1: %s\n\tin h2: %s\n\tin h3: %s" % \ + (str(ref), ref in h1, ref in h2, ref in h3) + + t1ref.decrease(-1) + t2ref.decrease(99) + + for ref in bad: + ref.delete() + for x in h1: + print x, + diff --git a/lib_graphd/inc/binomial-heap/heap.h b/lib_graphd/inc/binomial-heap/heap.h new file mode 100644 index 0000000..8cefc02 --- /dev/null +++ b/lib_graphd/inc/binomial-heap/heap.h @@ -0,0 +1,381 @@ +/* heap.h -- Binomial Heaps + * + * Copyright (c) 2008, Bjoern B. Brandenburg + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the University of North Carolina nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY COPYRIGHT OWNER AND CONTRIBUTERS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTERS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef HEAP_H +#define HEAP_H + +#define NOT_IN_HEAP UINT_MAX + +struct heap_node { + struct heap_node* parent; + struct heap_node* next; + struct heap_node* child; + + unsigned int degree; + void* value; + struct heap_node** ref; +}; + +struct heap { + struct heap_node* head; + /* We cache the minimum of the heap. + * This speeds up repeated peek operations. + */ + struct heap_node* min; +}; + +/* item comparison function: + * return 1 if a has higher prio than b, 0 otherwise + */ +typedef int (*heap_prio_t)(struct heap_node* a, struct heap_node* b); + +static inline void heap_init(struct heap* heap) +{ + heap->head = NULL; + heap->min = NULL; +} + +static inline void heap_node_init_ref(struct heap_node** _h, void* value) +{ + struct heap_node* h = *_h; + h->parent = NULL; + h->next = NULL; + h->child = NULL; + h->degree = NOT_IN_HEAP; + h->value = value; + h->ref = _h; +} + +static inline void heap_node_init(struct heap_node* h, void* value) +{ + h->parent = NULL; + h->next = NULL; + h->child = NULL; + h->degree = NOT_IN_HEAP; + h->value = value; + h->ref = NULL; +} + +static inline void* heap_node_value(struct heap_node* h) +{ + return h->value; +} + +static inline int heap_node_in_heap(struct heap_node* h) +{ + return h->degree != NOT_IN_HEAP; +} + +static inline int heap_empty(struct heap* heap) +{ + return heap->head == NULL && heap->min == NULL; +} + +/* make child a subtree of root */ +static inline void __heap_link(struct heap_node* root, + struct heap_node* child) +{ + child->parent = root; + child->next = root->child; + root->child = child; + root->degree++; +} + +/* merge root lists */ +static inline struct heap_node* __heap_merge(struct heap_node* a, + struct heap_node* b) +{ + struct heap_node* head = NULL; + struct heap_node** pos = &head; + + while (a && b) { + if (a->degree < b->degree) { + *pos = a; + a = a->next; + } else { + *pos = b; + b = b->next; + } + pos = &(*pos)->next; + } + if (a) + *pos = a; + else + *pos = b; + return head; +} + +/* reverse a linked list of nodes. also clears parent pointer */ +static inline struct heap_node* __heap_reverse(struct heap_node* h) +{ + struct heap_node* tail = NULL; + struct heap_node* next; + + if (!h) + return h; + + h->parent = NULL; + while (h->next) { + next = h->next; + h->next = tail; + tail = h; + h = next; + h->parent = NULL; + } + h->next = tail; + return h; +} + +static inline void __heap_min(heap_prio_t higher_prio, struct heap* heap, + struct heap_node** prev, struct heap_node** node) +{ + struct heap_node *_prev, *cur; + *prev = NULL; + + if (!heap->head) { + *node = NULL; + return; + } + + *node = heap->head; + _prev = heap->head; + cur = heap->head->next; + while (cur) { + if (higher_prio(cur, *node)) { + *node = cur; + *prev = _prev; + } + _prev = cur; + cur = cur->next; + } +} + +static inline void __heap_union(heap_prio_t higher_prio, struct heap* heap, + struct heap_node* h2) +{ + struct heap_node* h1; + struct heap_node *prev, *x, *next; + if (!h2) + return; + h1 = heap->head; + if (!h1) { + heap->head = h2; + return; + } + h1 = __heap_merge(h1, h2); + prev = NULL; + x = h1; + next = x->next; + while (next) { + if (x->degree != next->degree || + (next->next && next->next->degree == x->degree)) { + /* nothing to do, advance */ + prev = x; + x = next; + } else if (higher_prio(x, next)) { + /* x becomes the root of next */ + x->next = next->next; + __heap_link(x, next); + } else { + /* next becomes the root of x */ + if (prev) + prev->next = next; + else + h1 = next; + __heap_link(next, x); + x = next; + } + next = x->next; + } + heap->head = h1; +} + +static inline struct heap_node* __heap_extract_min(heap_prio_t higher_prio, + struct heap* heap) +{ + struct heap_node *prev, *node; + __heap_min(higher_prio, heap, &prev, &node); + if (!node) + return NULL; + if (prev) + prev->next = node->next; + else + heap->head = node->next; + __heap_union(higher_prio, heap, __heap_reverse(node->child)); + return node; +} + +/* insert (and reinitialize) a node into the heap */ +static inline void heap_insert(heap_prio_t higher_prio, struct heap* heap, + struct heap_node* node) +{ + struct heap_node *min; + node->child = NULL; + node->parent = NULL; + node->next = NULL; + node->degree = 0; + if (heap->min && higher_prio(node, heap->min)) { + /* swap min cache */ + min = heap->min; + min->child = NULL; + min->parent = NULL; + min->next = NULL; + min->degree = 0; + __heap_union(higher_prio, heap, min); + heap->min = node; + } else + __heap_union(higher_prio, heap, node); +} + +static inline void __uncache_min(heap_prio_t higher_prio, struct heap* heap) +{ + struct heap_node* min; + if (heap->min) { + min = heap->min; + heap->min = NULL; + heap_insert(higher_prio, heap, min); + } +} + +/* merge addition into target */ +static inline void heap_union(heap_prio_t higher_prio, + struct heap* target, struct heap* addition) +{ + /* first insert any cached minima, if necessary */ + __uncache_min(higher_prio, target); + __uncache_min(higher_prio, addition); + __heap_union(higher_prio, target, addition->head); + /* this is a destructive merge */ + addition->head = NULL; +} + +static inline struct heap_node* heap_peek(heap_prio_t higher_prio, + struct heap* heap) +{ + if (!heap->min) + heap->min = __heap_extract_min(higher_prio, heap); + return heap->min; +} + +static inline struct heap_node* heap_take(heap_prio_t higher_prio, + struct heap* heap) +{ + struct heap_node *node; + if (!heap->min) + heap->min = __heap_extract_min(higher_prio, heap); + node = heap->min; + heap->min = NULL; + if (node) + node->degree = NOT_IN_HEAP; + return node; +} + +static inline void heap_decrease(heap_prio_t higher_prio, struct heap* heap, + struct heap_node* node) +{ + struct heap_node *parent; + struct heap_node** tmp_ref; + void* tmp; + + /* node's priority was decreased, we need to update its position */ + if (!node->ref) + return; + if (heap->min != node) { + if (heap->min && higher_prio(node, heap->min)) + __uncache_min(higher_prio, heap); + /* bubble up */ + parent = node->parent; + while (parent && higher_prio(node, parent)) { + /* swap parent and node */ + tmp = parent->value; + parent->value = node->value; + node->value = tmp; + /* swap references */ + if (parent->ref) + *(parent->ref) = node; + *(node->ref) = parent; + tmp_ref = parent->ref; + parent->ref = node->ref; + node->ref = tmp_ref; + /* step up */ + node = parent; + parent = node->parent; + } + } +} + +static inline void heap_delete(heap_prio_t higher_prio, struct heap* heap, + struct heap_node* node) +{ + struct heap_node *parent, *prev, *pos; + struct heap_node** tmp_ref; + void* tmp; + + if (!node->ref) /* can only delete if we have a reference */ + return; + if (heap->min != node) { + /* bubble up */ + parent = node->parent; + while (parent) { + /* swap parent and node */ + tmp = parent->value; + parent->value = node->value; + node->value = tmp; + /* swap references */ + if (parent->ref) + *(parent->ref) = node; + *(node->ref) = parent; + tmp_ref = parent->ref; + parent->ref = node->ref; + node->ref = tmp_ref; + /* step up */ + node = parent; + parent = node->parent; + } + /* now delete: + * first find prev */ + prev = NULL; + pos = heap->head; + while (pos != node) { + prev = pos; + pos = pos->next; + } + /* we have prev, now remove node */ + if (prev) + prev->next = node->next; + else + heap->head = node->next; + __heap_union(higher_prio, heap, __heap_reverse(node->child)); + } else + heap->min = NULL; + node->degree = NOT_IN_HEAP; +} + +#endif /* HEAP_H */ diff --git a/lib_graphd/inc/binomial-heap/htest b/lib_graphd/inc/binomial-heap/htest new file mode 100755 index 0000000000000000000000000000000000000000..cef7a067863848f6743ee6b7e8ae51f7fdcdfe9b GIT binary patch literal 13284 zcmcIr4RBo5b-r3zwh*=@V=(>^cwGbt2Ft=2V}A2&S!P9KBWx=q;ILk6pRC2wuChNy zCU)aQhVf=G7>0%>rGv|)t(j8l=@8<96lCl~X39|0OoJNSR0W)@5e#wzL=Zsz&bjBj zeY>`jPG|Z+d+zzp&pr3tbMO20x0+j518lntO4aT**mib;$(Oi=J^QKqZrp|im&JEYxwP#!B;LqQD z_vt6eR{zlaUmx?KNqv+aL^k&j2)0>RN)19U#(%qftfG&wew5q=g+}K$pUuju0G&~-3OLG*cg)+!O~Pq@^r-aVT011G@!|gU zHQR^#>nqg%US<9-V3@xg-R4hB#}es3Qh9j%>PKb;&G^NS;GFwYJivUCcnbC8KJZt*-;#a(u2A-^Q2#rlZR=YG2lk%h zn9$&%eM|-)sc}sH$58xm?_P>Al&d&(UeJW@8%PJnk8y~5{YQH!dtx0a?!2*PZV-9@ z@(atb#9>wiHuUY0M&b_rzC6@FQWm;)C{@>4Js*=2>K`ZzWh+k1!C=q*DJ$hF-T()k z;8;!Vt*r#-lUQ5A~Zq=O9Cft@0%Y{k$?h{L10Idr20` z?idT@n#V$eq=I;;>F}z3<*+E^L)pwQB>7OzgtAaLv%c7JWl?+3nN5jhIM+TL%C-fi z4To*@p8GMlAGOA(#b9A)0-vLv&q1f2Y<)f{#+(x@MQDaH=h`@&N@AuQq#_xq;2inX zZBPiT9Rb!@i#DRvE9RU0w^N&CIcN5swlYGqZL>WuHgki`qZC|d51BTPjob#ce6DRa z$S~}#eK|Ep+(DnbA<>8}+ngUcUj)b=2`~#RpxHq8R2`%@7V6)TH|Z%L!zS}rmYXJ~ zC`1gBXNv}MOrzNf1_DaPF)t@nl@tbBNTegptiqZI zdo?=xMJPKs{yJ8{EGyE99kL@LpEMBi1Pe|yWp>PDp7mmO5Hn)Up!4>l5FRzvyRJh4 zS&tORu$=`PVGc^!nv-)_18s_t zO$QE-l(x3Y5ooe+Bpvm@ZMJv;79t|p8w_W%`o4vBOE?BAq@re|Y_H8NZI1O`a`&tr z4((}2XJ3aRiX!_f3g!sqjPk_Gma;ao9(6&piQo*4hZJ0nc7|#G+#&;uSOomZJMSWEh|hFb`i9Sm9Bu2H^iW~5_u8X zfESeng;LetPwVn^WUj~?Y6P2lmZq?%I&wVy1XJ;F!SvaR091n*N3DbhvfGxDZbd~M zU_E2wD1@7tXD1&;VBP*LXMu`rMWv@_&t8R*(CSX}=IA?HdHpzEJHu<#iZ@jPxk1G*!H1?7m~|Aj=`)-kGHyE-A}!(FPGEj462D*aagw{c%Wk z1DMZ_81;{*`o3E+h2BcWLT*Fij$(oaPyq+w27i*c+ijW#I8E0#AFSSWg+-u3Jq_vL zhkS#Fj0a8COalh*4W9J8!CNMWK6$jz&`Jfc8Km9@9az`Corb{&?2W`C$GRmLG$! zQG15WnQLFJete+%xdE^GJufdcV#xXDKV%=Up*_}Hz1NT{d(J>tKYOXO8W+Yde>%~2 zV132e7q(wY9Hxf12sC*$-2V}Iq!iMmjd@Oc{7xHnh}rhzgUz4OoQzzQYyK?s=b=Nx zlW1!%=P=c2JtnWe`Li;pT;F_r`@eak?9J|Y9F@8kS7)4>-%x0K=;C59|E6sZQ2SqO zd-(Ya(AA61yp4v?IMoESpQr8q#oz@N{i;O=o~PT17x!Ig(G`rMHup3Syf`f25H0;Z z?FY!oi=zS_w%~w`Lvs2Ah7ZkS01>Ew-?iX=_G#wZj&@n|eGJwJm?-!xn17kfbM0ha z0GHWacR!8q#DB8_xhg1}Zx!~D!VxG8R(v`YwAUl|%Uo3Y@zd z%zygZ@p0^qPqG%>_~7_0-7Wd=m$Kb;L#^3p9j-eTZkZf3t$Qwx5&@oX&8F){TeI8i zP>dVuaCi6KvewH^EYE)4lKnVz==1WH>>K%Y)cJkyr)#f#lkP`bv!AwRKVF&rVEOpD z$3y*xaZfjrd^eQaP=_6$yRN1+7pu41?% zh%5cE@${S*g1CE=`@)e*+-K%+zc@CYIVE?1_Fgpq5XC}w$#k#ozl%2p4-O1HTQKQl z#%-ut7mIJk|E8nc1=gF4#8Pg`q!T9Oy4_}LBG%!is@959x+@lU8%&BwRZ}FHz@waq zSsUrP!mNk&rlcFKS{{!QvcN=RZdJ>rJtpc#qUa}KU~nlJ&;y`I6EA6JzI&?(ZmB^$iCEQ&s4R3T*-T223 zQ&nZE+SfD%mv{F>f~zBGH+h`}R#7*>b&2@q>&(hTVvAYPopFOJ-L0|il;HrbGZ&|V z=%;L6`StY7jrNo7(eZJ*H`oJOiL>N;p!J{*O)uzLPx;7Q3Y z&_>W#LEAtV{2un8cZ2Q)?ZOq;0nk3sqo8!qb2~c9?pW?s!t&`g_XnD$P2K13w>g@???xFFpBZz`qaq_9FQ`p1c-$_z3c6 zi{$^{$!~x>i#go@>gA{W_A*ka14Q^wF~^Vj?Z4Jv9@xe%2<05_g5DC;z}tSkz^}Z1 zehB&RAYW4?Z}H?uAio&36DgA0iK+$m4&>a%-cn@0(vu&7 z{9hseq$s`*IXz<%IaLT`JZ;{M6u=}!NYhXN0l@0k?%>U64e zJ?QL7$3(p16apRmL=1E)bH*&2u0S&l5f-{9NI`DSWN)ap4yU zpA=r>b4%>+7GB58=Nw>Hiv4tvUoX6{9{Gl})Sk~7z%)O-BG-5~3$O9;-V5wY;{RTe zYd-D~Uh|>rG$i`EPS*&p`^xRY>%Pz-ysrDW@H51}^19ByA@Z3b|5M?GHQy0_mH@kj zr#mM)G#|RYHGjHKJRQ@KA^d>w*k^bzR{m&-{1xF( zh<;uYk{4d<@e|>HAPKKJ&tc2Uudo@d7XId@rt5>p?f!YZ~H-wA-+JMa#l;WV3LaxbbV(}P$({3Mr zJHbGfh(^*8)8KZ6JCl(fH{2D4t#YQJBb`X5(4i%FcR&cAk)BuwI!wR~ej3=f^|J|= z>kS==o*p-@^Cs#4Ka+W|q?*!oU;+*}90JgFiT}|0Q|ux%XpdF<+JFO&-n%m~K})<} zt!D+UM8j`?L%?Ct4PsB%5B{UnekFvsY)@$a8v_myI?prV>pp7fzOL)VN{yjwJz67b zzcb)~GiIj%`0FY7?BAH)skTH8eL!XKTx)n3onePXZs zrN*y%O6hz-*8@#a_p${g;k^SBbq|&kTsY zu79$py|mQ+L0}Y@o@e#?ZJA88_74?41Xk8$(em53O>$V)CW;%GEBvUvUN<}nk>6gw z!#N;|2Xz9(h1#jdAC%bZ^=6lB^d;t;Yqcf14}a9Z=D$zR<6{2|34Mp=Poe#2`0e$( z75$#&RaF$K<5&2(68kaPhsWf?rcUNj^-KF75PMal2Qzf&cR!{1DzzVkF2%3*^k$!q zM!8V?WA?8>*KhBLy(9Le{gv`RhdtGv_OI8k`u&l9XQcJ1_8QmmlK%C(k)gQ|;81d9ZDh?LZR~WEOn8vN!p|t0E|Aik!TkRAkUe}IdM2}r+xr36Z z3&1wvPxGex%2~k9)c2~8x<3}h^3!!pKC&qFitfWcjKg@ab%xD(AXQ;1*J&E106%RZy)u@5-; z=`HayQT)5u&pD>PWWF9|e1@4l$3d%bJb`A}8RqftfK$JXGo6AmT8Hp=ro7Sp4(UHC zaV`)mI*$z7ds|2qV`~$(C z6#O#5AD-ecvR&|Hf={co__KmH34Ta$e%1UbR=-Q|M+ARHaDHYA**?L4GtKJrvr^zs3r??H>CpT;@4(B<>Ff6c;PfSIZAl$s63>Xw1YUNAeS_|of_U3ex({3m z9Mx>-l`0)Oxj$nT0oR&gf&4TvKF!cqnsk8WW1Zl7eJilJ19(swAB|0b?_fVZMQJ|7 z`04xhpG~0u)CBlZ;4@5NpPwZD-(Y;Uq4&jf1o_vP|Cqqf2f%C2kWYFRJtI(Uc9yL7 zvv8iD5twP{V^se!3-~!$kNYH_SrJ}B`tWaL9}5b8Iq(|nx25~`QqgzjZDh@3GLJWj zexvviH>POZ(SR1ZCSS-UtWj9D~q^WntY;YBD}dfu_@9W=7$*JNT$!=0Yz`On|7lOORrjT zjUhoe7VRVMT6~yI&q1P@o}O*mPxG3U+|8=B%U3stm7{L7UFe0Mm~b!rwh+N~xsl#5 zKYHO-JP~!74JX}BEA${AyETFrkCu0PdeamOo8z7A7H#*q$<3}ZNtYf4d2A29F&C3e zoE{JfgNHxKNJlzMa)~VECesjS;vJEWF1H}DcC3_+Y>{B1Zb#CMpdZGgcte|Z@fv!I z8xME%^qNRC8fLE0;&FO-%7kxjy>-R%*6^*XR;_DZA6~zFMQbxnBBdxCNhTxP!Y>;Dq9uy0V| za5R+&cj3i1bfvtt)c79~(2%&KHbp2?c +#include +#include + +#include "heap.h" + +struct token { + int prio; + const char* str; +}; + +#define LENGTH(a) (sizeof(a) / sizeof(a[0])) + +struct token tokens1[] = { + {24, "all"}, {16, "star"}, {9, "true.\nSinging"}, {7, "clear"}, + {25, "praises"}, {13, "to"}, {5, "Heel"}, {6, "voices\nRinging"}, + {26, "thine."}, {21, "shine\nCarolina"}, {117, "Rah,"}, {102, "Tar"}, + {108, "bred\nAnd"}, {125, "Rah!"}, {107, "Heel"}, {118, "Rah,"}, + {111, "die\nI'm"}, {115, "dead.\nSo"}, {120, "Rah,"}, + {121, "Car'lina-lina\nRah,"}, {109, "when"}, {105, "a"}, + {123, "Car'lina-lina\nRah!"}, {110, "I"}, {114, "Heel"}, {101, "a"}, + {106, "Tar"}, {18, "all\nClear"}, {14, "the"} +}; + +struct token tokens2[] = { + {113, "Tar"}, {124, "Rah!"}, {112, "a"}, {103, "Heel"}, + {104, "born\nI'm"}, {122, "Rah,"}, {119, "Car'lina-lina\nRah,"}, + {2, "sound"}, {20, "radiance"}, {12, "N-C-U.\nHail"}, + {10, "Carolina's"}, {3, "of"}, {17, "of"}, {23, "gem.\nReceive"}, + {19, "its"}, {0, "\nHark"}, {22, "priceless"}, {4, "Tar"}, + {1, "the"}, {8, "and"}, {15, "brightest"}, + {11, "praises.\nShouting"}, {100, "\nI'm"}, {116, "it's"} +}; + +#define line "\n===================================" + +struct token layout[] = { + {90, line}, {-2, line}, {200, line}, {201, "\n\n"} +}; + + +struct token title[] = { + {1000, "\nUNC Alma Mater:"}, {120, "\nUNC Fight Song:"} +}; + +struct token bad[] = { + {666, "Dook"}, {666666, "Blue Devils"} +}; + +static int token_cmp(struct heap_node* _a, struct heap_node* _b) +{ + struct token *a, *b; + a = (struct token*) heap_node_value(_a); + b = (struct token*) heap_node_value(_b); + return a->prio < b->prio; +} + +static void add_token(struct heap* heap, struct token* tok) +{ + struct heap_node* hn = malloc(sizeof(struct heap_node)); + heap_node_init(hn, tok); + heap_insert(token_cmp, heap, hn); +} + +static void add_token_ref(struct heap* heap, struct token* tok, + struct heap_node** hn) +{ + *hn = malloc(sizeof(struct heap_node)); + heap_node_init_ref(hn, tok); + heap_insert(token_cmp, heap, *hn); +} + +static void add_tokens(struct heap* heap, struct token* tok, int len) +{ + int i; + for (i = 0; i < len; i++) + add_token(heap, tok + i); +} + +int main(int argc __attribute__((unused)), char** argv __attribute__((unused))) +{ + struct heap h1, h2, h3; + struct heap_node* hn; + struct heap_node *t1, *t2, *b1, *b2; + struct token *tok; + + heap_init(&h1); + heap_init(&h2); + heap_init(&h3); + + add_tokens(&h1, tokens1, LENGTH(tokens1)); + add_tokens(&h2, tokens2, LENGTH(tokens2)); + add_tokens(&h3, layout, LENGTH(layout)); + + add_token_ref(&h3, title, &t1); + add_token_ref(&h2, title + 1, &t2); + + heap_union(token_cmp, &h2, &h3); + heap_union(token_cmp, &h1, &h2); + + add_token_ref(&h3, bad, &b1); + add_token_ref(&h3, bad + 1, &b2); + + heap_union(token_cmp, &h1, &h3); + + heap_delete(token_cmp, &h1, b1); + free(b1); + heap_delete(token_cmp, &h1, b2); + free(b2); + + title[0].prio = -1; + title[1].prio = 99; + + heap_decrease(token_cmp, &h1, t1); + heap_decrease(token_cmp, &h1, t2); + + printf("htest:\n"); + while (!heap_empty(&h1)) { + hn = heap_take(token_cmp, &h1); + tok = heap_node_value(hn); + printf("%s ", tok->str); + free(hn); + } + return 0; +} diff --git a/lib_graphd/inc/binomial-heap/iheap.h b/lib_graphd/inc/binomial-heap/iheap.h new file mode 100644 index 0000000..a697f4e --- /dev/null +++ b/lib_graphd/inc/binomial-heap/iheap.h @@ -0,0 +1,385 @@ +/* iheap.h -- Binomial Heaps with integer priorities + * + * Copyright (c) 2008, Bjoern B. Brandenburg + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the University of North Carolina nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY COPYRIGHT OWNER AND CONTRIBUTERS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTERS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef IHEAP_H +#define IHEAP_H + +#define NOT_IN_HEAP UINT_MAX + +struct iheap_node { + struct iheap_node* parent; + struct iheap_node* next; + struct iheap_node* child; + + unsigned int degree; + int key; + const void* value; + struct iheap_node** ref; +}; + +struct iheap { + struct iheap_node* head; + /* We cache the minimum of the heap. + * This speeds up repeated peek operations. + */ + struct iheap_node* min; +}; + + + void iheap_init(struct iheap* heap) +{ + heap->head = NULL; + heap->min = NULL; +} + + void iheap_node_init_ref(struct iheap_node** _h, + int key, const void* value) +{ + struct iheap_node* h = *_h; + h->parent = NULL; + h->next = NULL; + h->child = NULL; + h->degree = NOT_IN_HEAP; + h->value = value; + h->ref = _h; + h->key = key; +} + + void iheap_node_init(struct iheap_node* h, int key, const void* value) +{ + h->parent = NULL; + h->next = NULL; + h->child = NULL; + h->degree = NOT_IN_HEAP; + h->value = value; + h->ref = NULL; + h->key = key; + //fprintf(stderr, "initializing head node with key %d and value 0x%x\n", key, value); +} + + const void* iheap_node_value(struct iheap_node* h) +{ + return h->value; +} + + int iheap_node_in_heap(struct iheap_node* h) +{ + return h->degree != NOT_IN_HEAP; +} + + int iheap_empty(struct iheap* heap) +{ + return heap->head == NULL && heap->min == NULL; +} + +/* make child a subtree of root */ + void __iheap_link(struct iheap_node* root, + struct iheap_node* child) +{ + child->parent = root; + child->next = root->child; + root->child = child; + root->degree++; +} + +/* merge root lists */ + struct iheap_node* __iheap_merge(struct iheap_node* a, + struct iheap_node* b) +{ + struct iheap_node* head = NULL; + struct iheap_node** pos = &head; + + while (a && b) { + if (a->degree < b->degree) { + *pos = a; + a = a->next; + } else { + *pos = b; + b = b->next; + } + pos = &(*pos)->next; + } + if (a) + *pos = a; + else + *pos = b; + return head; +} + +/* reverse a linked list of nodes. also clears parent pointer */ + struct iheap_node* __iheap_reverse(struct iheap_node* h) +{ + struct iheap_node* tail = NULL; + struct iheap_node* next; + + if (!h) + return h; + + h->parent = NULL; + while (h->next) { + next = h->next; + h->next = tail; + tail = h; + h = next; + h->parent = NULL; + } + h->next = tail; + return h; +} + + void __iheap_min(struct iheap* heap, + struct iheap_node** prev, + struct iheap_node** node) +{ + struct iheap_node *_prev, *cur; + *prev = NULL; + + if (!heap->head) { + *node = NULL; + return; + } + + *node = heap->head; + _prev = heap->head; + cur = heap->head->next; + while (cur) { + if (cur->key < (*node)->key) { + *node = cur; + *prev = _prev; + } + _prev = cur; + cur = cur->next; + } +} + + void __iheap_union(struct iheap* heap, struct iheap_node* h2) +{ + struct iheap_node* h1; + struct iheap_node *prev, *x, *next; + if (!h2) + return; + h1 = heap->head; + if (!h1) { + heap->head = h2; + return; + } + h1 = __iheap_merge(h1, h2); + prev = NULL; + x = h1; + next = x->next; + while (next) { + if (x->degree != next->degree || + (next->next && next->next->degree == x->degree)) { + /* nothing to do, advance */ + prev = x; + x = next; + } else if (x->key < next->key) { + /* x becomes the root of next */ + x->next = next->next; + __iheap_link(x, next); + } else { + /* next becomes the root of x */ + if (prev) + prev->next = next; + else + h1 = next; + __iheap_link(next, x); + x = next; + } + next = x->next; + } + heap->head = h1; +} + + struct iheap_node* __iheap_extract_min(struct iheap* heap) +{ + struct iheap_node *prev, *node; + __iheap_min(heap, &prev, &node); + if (!node) + return NULL; + if (prev) + prev->next = node->next; + else + heap->head = node->next; + __iheap_union(heap, __iheap_reverse(node->child)); + return node; +} + +/* insert (and reinitialize) a node into the heap */ + void iheap_insert(struct iheap* heap, struct iheap_node* node) +{ + struct iheap_node *min; + node->child = NULL; + node->parent = NULL; + node->next = NULL; + node->degree = 0; + if (heap->min && node->key < heap->min->key) { + /* swap min cache */ + min = heap->min; + min->child = NULL; + min->parent = NULL; + min->next = NULL; + min->degree = 0; + __iheap_union(heap, min); + heap->min = node; + } else + __iheap_union(heap, node); +} + + void __iheap_uncache_min(struct iheap* heap) +{ + struct iheap_node* min; + if (heap->min) { + min = heap->min; + heap->min = NULL; + iheap_insert(heap, min); + } +} + +/* merge addition into target */ + void iheap_union(struct iheap* target, struct iheap* addition) +{ + /* first insert any cached minima, if necessary */ + __iheap_uncache_min(target); + __iheap_uncache_min(addition); + __iheap_union(target, addition->head); + /* this is a destructive merge */ + addition->head = NULL; +} + + struct iheap_node* iheap_peek(struct iheap* heap) +{ + if (!heap->min) + heap->min = __iheap_extract_min(heap); + return heap->min; +} + + struct iheap_node* iheap_take(struct iheap* heap) +{ + struct iheap_node *node; + if (!heap->min) + heap->min = __iheap_extract_min(heap); + node = heap->min; + heap->min = NULL; + if (node) + node->degree = NOT_IN_HEAP; + return node; +} + + void iheap_decrease(struct iheap* heap, struct iheap_node* node, + int new_key) +{ + struct iheap_node *parent; + struct iheap_node** tmp_ref; + const void* tmp; + int tmp_key; + + /* node's priority was decreased, we need to update its position */ + if (!node->ref || new_key >= node->key) + return; + node->key = new_key; + if (heap->min != node) { + if (heap->min && node->key < heap->min->key) + __iheap_uncache_min(heap); + /* bubble up */ + parent = node->parent; + while (parent && node->key < parent->key) { + /* swap parent and node */ + tmp = parent->value; + tmp_key = parent->key; + parent->value = node->value; + parent->key = node->key; + node->value = tmp; + node->key = tmp_key; + /* swap references */ + if (parent->ref) + *(parent->ref) = node; + *(node->ref) = parent; + tmp_ref = parent->ref; + parent->ref = node->ref; + node->ref = tmp_ref; + /* step up */ + node = parent; + parent = node->parent; + } + } +} + + void iheap_delete(struct iheap* heap, struct iheap_node* node) +{ + struct iheap_node *parent, *prev, *pos; + struct iheap_node** tmp_ref; + const void* tmp; + int tmp_key; + + if (!node->ref) /* can only delete if we have a reference */ + return; + if (heap->min != node) { + /* bubble up */ + parent = node->parent; + while (parent) { + /* swap parent and node */ + tmp = parent->value; + tmp_key = parent->key; + parent->value = node->value; + parent->key = node->key; + node->value = tmp; + node->key = tmp_key; + /* swap references */ + if (parent->ref) + *(parent->ref) = node; + *(node->ref) = parent; + tmp_ref = parent->ref; + parent->ref = node->ref; + node->ref = tmp_ref; + /* step up */ + node = parent; + parent = node->parent; + } + /* now delete: + * first find prev */ + prev = NULL; + pos = heap->head; + while (pos != node) { + prev = pos; + pos = pos->next; + } + /* we have prev, now remove node */ + if (prev) + prev->next = node->next; + else + heap->head = node->next; + __iheap_union(heap, __iheap_reverse(node->child)); + } else + heap->min = NULL; + node->degree = NOT_IN_HEAP; +} + +#endif /* HEAP_H */ diff --git a/lib_graphd/inc/binomial-heap/iheap.h.noinline b/lib_graphd/inc/binomial-heap/iheap.h.noinline new file mode 100644 index 0000000..a697f4e --- /dev/null +++ b/lib_graphd/inc/binomial-heap/iheap.h.noinline @@ -0,0 +1,385 @@ +/* iheap.h -- Binomial Heaps with integer priorities + * + * Copyright (c) 2008, Bjoern B. Brandenburg + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the University of North Carolina nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY COPYRIGHT OWNER AND CONTRIBUTERS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTERS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef IHEAP_H +#define IHEAP_H + +#define NOT_IN_HEAP UINT_MAX + +struct iheap_node { + struct iheap_node* parent; + struct iheap_node* next; + struct iheap_node* child; + + unsigned int degree; + int key; + const void* value; + struct iheap_node** ref; +}; + +struct iheap { + struct iheap_node* head; + /* We cache the minimum of the heap. + * This speeds up repeated peek operations. + */ + struct iheap_node* min; +}; + + + void iheap_init(struct iheap* heap) +{ + heap->head = NULL; + heap->min = NULL; +} + + void iheap_node_init_ref(struct iheap_node** _h, + int key, const void* value) +{ + struct iheap_node* h = *_h; + h->parent = NULL; + h->next = NULL; + h->child = NULL; + h->degree = NOT_IN_HEAP; + h->value = value; + h->ref = _h; + h->key = key; +} + + void iheap_node_init(struct iheap_node* h, int key, const void* value) +{ + h->parent = NULL; + h->next = NULL; + h->child = NULL; + h->degree = NOT_IN_HEAP; + h->value = value; + h->ref = NULL; + h->key = key; + //fprintf(stderr, "initializing head node with key %d and value 0x%x\n", key, value); +} + + const void* iheap_node_value(struct iheap_node* h) +{ + return h->value; +} + + int iheap_node_in_heap(struct iheap_node* h) +{ + return h->degree != NOT_IN_HEAP; +} + + int iheap_empty(struct iheap* heap) +{ + return heap->head == NULL && heap->min == NULL; +} + +/* make child a subtree of root */ + void __iheap_link(struct iheap_node* root, + struct iheap_node* child) +{ + child->parent = root; + child->next = root->child; + root->child = child; + root->degree++; +} + +/* merge root lists */ + struct iheap_node* __iheap_merge(struct iheap_node* a, + struct iheap_node* b) +{ + struct iheap_node* head = NULL; + struct iheap_node** pos = &head; + + while (a && b) { + if (a->degree < b->degree) { + *pos = a; + a = a->next; + } else { + *pos = b; + b = b->next; + } + pos = &(*pos)->next; + } + if (a) + *pos = a; + else + *pos = b; + return head; +} + +/* reverse a linked list of nodes. also clears parent pointer */ + struct iheap_node* __iheap_reverse(struct iheap_node* h) +{ + struct iheap_node* tail = NULL; + struct iheap_node* next; + + if (!h) + return h; + + h->parent = NULL; + while (h->next) { + next = h->next; + h->next = tail; + tail = h; + h = next; + h->parent = NULL; + } + h->next = tail; + return h; +} + + void __iheap_min(struct iheap* heap, + struct iheap_node** prev, + struct iheap_node** node) +{ + struct iheap_node *_prev, *cur; + *prev = NULL; + + if (!heap->head) { + *node = NULL; + return; + } + + *node = heap->head; + _prev = heap->head; + cur = heap->head->next; + while (cur) { + if (cur->key < (*node)->key) { + *node = cur; + *prev = _prev; + } + _prev = cur; + cur = cur->next; + } +} + + void __iheap_union(struct iheap* heap, struct iheap_node* h2) +{ + struct iheap_node* h1; + struct iheap_node *prev, *x, *next; + if (!h2) + return; + h1 = heap->head; + if (!h1) { + heap->head = h2; + return; + } + h1 = __iheap_merge(h1, h2); + prev = NULL; + x = h1; + next = x->next; + while (next) { + if (x->degree != next->degree || + (next->next && next->next->degree == x->degree)) { + /* nothing to do, advance */ + prev = x; + x = next; + } else if (x->key < next->key) { + /* x becomes the root of next */ + x->next = next->next; + __iheap_link(x, next); + } else { + /* next becomes the root of x */ + if (prev) + prev->next = next; + else + h1 = next; + __iheap_link(next, x); + x = next; + } + next = x->next; + } + heap->head = h1; +} + + struct iheap_node* __iheap_extract_min(struct iheap* heap) +{ + struct iheap_node *prev, *node; + __iheap_min(heap, &prev, &node); + if (!node) + return NULL; + if (prev) + prev->next = node->next; + else + heap->head = node->next; + __iheap_union(heap, __iheap_reverse(node->child)); + return node; +} + +/* insert (and reinitialize) a node into the heap */ + void iheap_insert(struct iheap* heap, struct iheap_node* node) +{ + struct iheap_node *min; + node->child = NULL; + node->parent = NULL; + node->next = NULL; + node->degree = 0; + if (heap->min && node->key < heap->min->key) { + /* swap min cache */ + min = heap->min; + min->child = NULL; + min->parent = NULL; + min->next = NULL; + min->degree = 0; + __iheap_union(heap, min); + heap->min = node; + } else + __iheap_union(heap, node); +} + + void __iheap_uncache_min(struct iheap* heap) +{ + struct iheap_node* min; + if (heap->min) { + min = heap->min; + heap->min = NULL; + iheap_insert(heap, min); + } +} + +/* merge addition into target */ + void iheap_union(struct iheap* target, struct iheap* addition) +{ + /* first insert any cached minima, if necessary */ + __iheap_uncache_min(target); + __iheap_uncache_min(addition); + __iheap_union(target, addition->head); + /* this is a destructive merge */ + addition->head = NULL; +} + + struct iheap_node* iheap_peek(struct iheap* heap) +{ + if (!heap->min) + heap->min = __iheap_extract_min(heap); + return heap->min; +} + + struct iheap_node* iheap_take(struct iheap* heap) +{ + struct iheap_node *node; + if (!heap->min) + heap->min = __iheap_extract_min(heap); + node = heap->min; + heap->min = NULL; + if (node) + node->degree = NOT_IN_HEAP; + return node; +} + + void iheap_decrease(struct iheap* heap, struct iheap_node* node, + int new_key) +{ + struct iheap_node *parent; + struct iheap_node** tmp_ref; + const void* tmp; + int tmp_key; + + /* node's priority was decreased, we need to update its position */ + if (!node->ref || new_key >= node->key) + return; + node->key = new_key; + if (heap->min != node) { + if (heap->min && node->key < heap->min->key) + __iheap_uncache_min(heap); + /* bubble up */ + parent = node->parent; + while (parent && node->key < parent->key) { + /* swap parent and node */ + tmp = parent->value; + tmp_key = parent->key; + parent->value = node->value; + parent->key = node->key; + node->value = tmp; + node->key = tmp_key; + /* swap references */ + if (parent->ref) + *(parent->ref) = node; + *(node->ref) = parent; + tmp_ref = parent->ref; + parent->ref = node->ref; + node->ref = tmp_ref; + /* step up */ + node = parent; + parent = node->parent; + } + } +} + + void iheap_delete(struct iheap* heap, struct iheap_node* node) +{ + struct iheap_node *parent, *prev, *pos; + struct iheap_node** tmp_ref; + const void* tmp; + int tmp_key; + + if (!node->ref) /* can only delete if we have a reference */ + return; + if (heap->min != node) { + /* bubble up */ + parent = node->parent; + while (parent) { + /* swap parent and node */ + tmp = parent->value; + tmp_key = parent->key; + parent->value = node->value; + parent->key = node->key; + node->value = tmp; + node->key = tmp_key; + /* swap references */ + if (parent->ref) + *(parent->ref) = node; + *(node->ref) = parent; + tmp_ref = parent->ref; + parent->ref = node->ref; + node->ref = tmp_ref; + /* step up */ + node = parent; + parent = node->parent; + } + /* now delete: + * first find prev */ + prev = NULL; + pos = heap->head; + while (pos != node) { + prev = pos; + pos = pos->next; + } + /* we have prev, now remove node */ + if (prev) + prev->next = node->next; + else + heap->head = node->next; + __iheap_union(heap, __iheap_reverse(node->child)); + } else + heap->min = NULL; + node->degree = NOT_IN_HEAP; +} + +#endif /* HEAP_H */ diff --git a/lib_graphd/inc/binomial-heap/iheap.h.orig b/lib_graphd/inc/binomial-heap/iheap.h.orig new file mode 100644 index 0000000..ffc19ab --- /dev/null +++ b/lib_graphd/inc/binomial-heap/iheap.h.orig @@ -0,0 +1,385 @@ +/* iheap.h -- Binomial Heaps with integer priorities + * + * Copyright (c) 2008, Bjoern B. Brandenburg + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the University of North Carolina nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY COPYRIGHT OWNER AND CONTRIBUTERS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTERS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef IHEAP_H +#define IHEAP_H + +#define NOT_IN_HEAP UINT_MAX + +struct iheap_node { + struct iheap_node* parent; + struct iheap_node* next; + struct iheap_node* child; + + unsigned int degree; + int key; + const void* value; + struct iheap_node** ref; +}; + +struct iheap { + struct iheap_node* head; + /* We cache the minimum of the heap. + * This speeds up repeated peek operations. + */ + struct iheap_node* min; +}; + + +static inline void iheap_init(struct iheap* heap) +{ + heap->head = NULL; + heap->min = NULL; +} + +static inline void iheap_node_init_ref(struct iheap_node** _h, + int key, const void* value) +{ + struct iheap_node* h = *_h; + h->parent = NULL; + h->next = NULL; + h->child = NULL; + h->degree = NOT_IN_HEAP; + h->value = value; + h->ref = _h; + h->key = key; +} + +static inline void iheap_node_init(struct iheap_node* h, int key, const void* value) +{ + h->parent = NULL; + h->next = NULL; + h->child = NULL; + h->degree = NOT_IN_HEAP; + h->value = value; + h->ref = NULL; + h->key = key; + //fprintf(stderr, "initializing head node with key %d and value 0x%x\n", key, value); +} + +static inline const void* iheap_node_value(struct iheap_node* h) +{ + return h->value; +} + +static inline int iheap_node_in_heap(struct iheap_node* h) +{ + return h->degree != NOT_IN_HEAP; +} + +static inline int iheap_empty(struct iheap* heap) +{ + return heap->head == NULL && heap->min == NULL; +} + +/* make child a subtree of root */ +static inline void __iheap_link(struct iheap_node* root, + struct iheap_node* child) +{ + child->parent = root; + child->next = root->child; + root->child = child; + root->degree++; +} + +/* merge root lists */ +static inline struct iheap_node* __iheap_merge(struct iheap_node* a, + struct iheap_node* b) +{ + struct iheap_node* head = NULL; + struct iheap_node** pos = &head; + + while (a && b) { + if (a->degree < b->degree) { + *pos = a; + a = a->next; + } else { + *pos = b; + b = b->next; + } + pos = &(*pos)->next; + } + if (a) + *pos = a; + else + *pos = b; + return head; +} + +/* reverse a linked list of nodes. also clears parent pointer */ +static inline struct iheap_node* __iheap_reverse(struct iheap_node* h) +{ + struct iheap_node* tail = NULL; + struct iheap_node* next; + + if (!h) + return h; + + h->parent = NULL; + while (h->next) { + next = h->next; + h->next = tail; + tail = h; + h = next; + h->parent = NULL; + } + h->next = tail; + return h; +} + +static inline void __iheap_min(struct iheap* heap, + struct iheap_node** prev, + struct iheap_node** node) +{ + struct iheap_node *_prev, *cur; + *prev = NULL; + + if (!heap->head) { + *node = NULL; + return; + } + + *node = heap->head; + _prev = heap->head; + cur = heap->head->next; + while (cur) { + if (cur->key < (*node)->key) { + *node = cur; + *prev = _prev; + } + _prev = cur; + cur = cur->next; + } +} + +static inline void __iheap_union(struct iheap* heap, struct iheap_node* h2) +{ + struct iheap_node* h1; + struct iheap_node *prev, *x, *next; + if (!h2) + return; + h1 = heap->head; + if (!h1) { + heap->head = h2; + return; + } + h1 = __iheap_merge(h1, h2); + prev = NULL; + x = h1; + next = x->next; + while (next) { + if (x->degree != next->degree || + (next->next && next->next->degree == x->degree)) { + /* nothing to do, advance */ + prev = x; + x = next; + } else if (x->key < next->key) { + /* x becomes the root of next */ + x->next = next->next; + __iheap_link(x, next); + } else { + /* next becomes the root of x */ + if (prev) + prev->next = next; + else + h1 = next; + __iheap_link(next, x); + x = next; + } + next = x->next; + } + heap->head = h1; +} + +static inline struct iheap_node* __iheap_extract_min(struct iheap* heap) +{ + struct iheap_node *prev, *node; + __iheap_min(heap, &prev, &node); + if (!node) + return NULL; + if (prev) + prev->next = node->next; + else + heap->head = node->next; + __iheap_union(heap, __iheap_reverse(node->child)); + return node; +} + +/* insert (and reinitialize) a node into the heap */ +static inline void iheap_insert(struct iheap* heap, struct iheap_node* node) +{ + struct iheap_node *min; + node->child = NULL; + node->parent = NULL; + node->next = NULL; + node->degree = 0; + if (heap->min && node->key < heap->min->key) { + /* swap min cache */ + min = heap->min; + min->child = NULL; + min->parent = NULL; + min->next = NULL; + min->degree = 0; + __iheap_union(heap, min); + heap->min = node; + } else + __iheap_union(heap, node); +} + +static inline void __iheap_uncache_min(struct iheap* heap) +{ + struct iheap_node* min; + if (heap->min) { + min = heap->min; + heap->min = NULL; + iheap_insert(heap, min); + } +} + +/* merge addition into target */ +static inline void iheap_union(struct iheap* target, struct iheap* addition) +{ + /* first insert any cached minima, if necessary */ + __iheap_uncache_min(target); + __iheap_uncache_min(addition); + __iheap_union(target, addition->head); + /* this is a destructive merge */ + addition->head = NULL; +} + +static inline struct iheap_node* iheap_peek(struct iheap* heap) +{ + if (!heap->min) + heap->min = __iheap_extract_min(heap); + return heap->min; +} + +static inline struct iheap_node* iheap_take(struct iheap* heap) +{ + struct iheap_node *node; + if (!heap->min) + heap->min = __iheap_extract_min(heap); + node = heap->min; + heap->min = NULL; + if (node) + node->degree = NOT_IN_HEAP; + return node; +} + +static inline void iheap_decrease(struct iheap* heap, struct iheap_node* node, + int new_key) +{ + struct iheap_node *parent; + struct iheap_node** tmp_ref; + const void* tmp; + int tmp_key; + + /* node's priority was decreased, we need to update its position */ + if (!node->ref || new_key >= node->key) + return; + node->key = new_key; + if (heap->min != node) { + if (heap->min && node->key < heap->min->key) + __iheap_uncache_min(heap); + /* bubble up */ + parent = node->parent; + while (parent && node->key < parent->key) { + /* swap parent and node */ + tmp = parent->value; + tmp_key = parent->key; + parent->value = node->value; + parent->key = node->key; + node->value = tmp; + node->key = tmp_key; + /* swap references */ + if (parent->ref) + *(parent->ref) = node; + *(node->ref) = parent; + tmp_ref = parent->ref; + parent->ref = node->ref; + node->ref = tmp_ref; + /* step up */ + node = parent; + parent = node->parent; + } + } +} + +static inline void iheap_delete(struct iheap* heap, struct iheap_node* node) +{ + struct iheap_node *parent, *prev, *pos; + struct iheap_node** tmp_ref; + const void* tmp; + int tmp_key; + + if (!node->ref) /* can only delete if we have a reference */ + return; + if (heap->min != node) { + /* bubble up */ + parent = node->parent; + while (parent) { + /* swap parent and node */ + tmp = parent->value; + tmp_key = parent->key; + parent->value = node->value; + parent->key = node->key; + node->value = tmp; + node->key = tmp_key; + /* swap references */ + if (parent->ref) + *(parent->ref) = node; + *(node->ref) = parent; + tmp_ref = parent->ref; + parent->ref = node->ref; + node->ref = tmp_ref; + /* step up */ + node = parent; + parent = node->parent; + } + /* now delete: + * first find prev */ + prev = NULL; + pos = heap->head; + while (pos != node) { + prev = pos; + pos = pos->next; + } + /* we have prev, now remove node */ + if (prev) + prev->next = node->next; + else + heap->head = node->next; + __iheap_union(heap, __iheap_reverse(node->child)); + } else + heap->min = NULL; + node->degree = NOT_IN_HEAP; +} + +#endif /* HEAP_H */ diff --git a/lib_graphd/inc/binomial-heap/ihtest b/lib_graphd/inc/binomial-heap/ihtest new file mode 100755 index 0000000000000000000000000000000000000000..01f8fca068fd44745c15105e8c614289f1f77936 GIT binary patch literal 13145 zcmcIq4RBOdmcHo_2oXs55rbx=9m9f-G(RE(>WnXh#*PMvNCsy_J5Bl}Y3X!lx?f{Z zs9_dx?P+i`yY7^Z>`sQ-a;bHGNzwO1$>R}DQ-YgnO5 z`87ax6l)*L`)b=XF0_V(D1N45N8u54jO~uGozOlGOsMpa`bK|s+`l@X1&(-&h+3-pfhg?}-1 z&f4d8lCAuq`Ue-9Zq!C;Az%Jd5d7u%n@InUE`l$<2!6{&a1{=Bb|(|zv=d1=;jlv5 z+9^vbRZqrAtDaOW;dH3(NIafwhc1a(w>uI`sE(9vt6Q6!)-;Bf2bKqJKr56jWx^!+p^Y0Q*A)h;{`L~FtP|x*)U-o`e_O*LM*|$P_-yUt*+%!0_be5$; zgD+c}3~sKmRQ@?Ae%#kbF@|y#5jY6#A8>r*LpsDhZ)pu>-?@_%_k5>so*#L?{rMwU z;xPLO*wBwh`iXn_i}KLkk+RV0GwJ${>iHOy(B6TvP`1K`()gTz&`P23CAgLf8s#<#0zIu`s^4ZMWp=|3J2=k$w3T2@)u?d^&$wl=+tCn)B;T#-fTl`$l zqrQmhxz@L{Ep={NW7*8dXbbI37?Xjmi!?w^O#_40BI!=9_2Z%jOaPX@(4;|V>@ss$ zT1m{5V>Eq6Ds=Wd>eCKUJz<# zI5Zd>)nOha)8N?19Z<{XT53UtVYm83dLFxjK6yi4tV*cnM=oQ*un`Qi0F;`ic|&?* zp}o8F%9#Q(tTMke+;or6kxPpGjCvxJ=*UH8GW7Bz_s}oTm67W;V*;WXf#7tvDFuj^ zGK2sStmfSbX8M5q4wTw>+NSK7DTgdkj+9Z>qeLAzBT@7i0c8ghjFUu@l$u9dFw`j< z8@UC*Sgxf`YvxqWs#|?x_gurtP$GZS2XaH9lMi&wI6(HsROUEGx%a)LSUhMlgXO+^ zNLBA!f$74&VLEJbPM*%d=@6Wro2@la$M}Y_{}Rd$=HL4g>w~lhgL&>IM7m)#ZW=y! z!t{UCOpP%;H8NMbv0-5^62_>E8kJcp zfdEHVnVB;KIDApES}I4NslA$<>AJRf{X8%El5XhyRqwyv>&3SH`y+gkJ|i6Ocw}(A{i26OmxON0JIQIUYEq1_Oqeen_~ zvukK}nS`3_O(95HhK}C1Jl7Z3`6^kJ+1Ar=F@!N$gfXe!ccWRJLl}&kf~Tt=SuA|( zXuGoFlh_Q7H7MgVx)XLwVqiQpBrIR3D)AIx?xxyG||S_!Q>C0JQPP3C@_LodQ5< zM9Ob72vn$vA;}Axbn`;PVe$eklMl|zfXVle$pEBoUIucK7xLuh#W1$blBB~UbjL7^8YYh(m`Xx*9T~{r z_Hp+arS~ZK(>u}`v}yJzL6FHB)1cX-9vnkcS=yr@(F-Z}dkg{1wo`?b8XVx+?;RMw z>|HM{MWFe~pO7co9w{c>{BW)k+?d%{|KwBJ`-;~5XPRKZ6Bnu9n8-&^#Q6+H}&D;-#}9@ z4&Z@<&;*Suw2#w1`(l5cLGLo?z;SvYc+r2QLDy)s^%(RAUTkCVHCp=zTaS{H7ke0d z!GHrM4&C`@(0S+$0YaD>I&7dL+TR{F{jo9a*I*xm@q#}ww#hixO2z`+YxdhC)UR)S zq{ZY$#J3o6KZ&Pl@p|gY@Nskt(?nlspVMB~Q*VZkx1;ln{{r|+&*P9FfB1Kpi$UXd zFn=xS%XJ=pf2OBLaO~Jg=<2DZyLt?sRDKIg^^AdHj_NwL!F(D<*xR1cTJ&Vn*Y^=U z&3K<@vhn&e&Dm)EaOmLTn`i)JY|eh(oc(ld_JfA;IcGzAPvV(tB=v46x3wP2 zBVJ$AoQu}iHlyZm&N=mqnsdAAm*O#Nl@1Q^xzBT$PCw3`KgR2d@|#{kdzazw^yv8bFzEZB zbSUzD467gXIH(1B8ng}c3(!5F4Vd!%p#K3n02;;`90skx^rvaC1sjwf^em_a`uEtK z+dw}8-2?jF&tMPw1n2oK>_ z6t(}lZlC7u3y=@vjtImp^{D+8z!~6KLhm?G@zCV(3~TR{KlMFQesGfSt{M7?jV(|!!px+FUuMJe<$)@q_m+99+w?VA7c75rcW|0wfj0=^0A1=S?0ra%uC*u zF)w+(h532hK#+NvH|v>~v+x$?C$oMl^Yq?SCW|Ugn?Z?_~SKEbnIi8RlcmA7}nS=3ihw!Tdin zpJHC(vrFvnV_y2JuPwk{V|%>JBjzuKs)mCVaNW-%XS`6lKa=C?5a1LoV9$G)TYX5mkj$X{iC zKkMf?ArCVz^YL-!f6fX2TjsC5&Sdmy=5K9mywSf1Zx^reuL!INtn@Emx@`H<>zCf( zU$n`N`a==N;EPvWqf{Whv)hSm19eh{c1aDd=j>FE3M7(_9cWn7wAhJsGS`{N1h!>j zcm*1ZssM3ak#v^|M0Y0O&rm02Bs=U>I+jcnF=5D3c057`T3I#50f90~(;ALT7F{{*`l720FPzRqWXE4&ByYp(Dk^I4E( zsCeyf_E}nVGdraF32!O2Ukf2_k&@DWo6iD5*L_Xg?+IjIm-S+#N^L-e)`-~e@mb*L zzCaUo#1Q>W0QFt$(~VdjsL+{@`J@_d`yFu4CT#HHaVDA1S9|FZUxy*k1Z6?U(j{Ux~fk-wd$5tbekn zy|mQ+5nvRTTxaEeZWRx-v=0?s7#3D#QS;ijOtQ4Bg%#U0SNIWoxo>zBBCoxC2XmAa z?~(yv7h)$Ke_moQ_n(!#(U+L(T#GHye*97UlK)!1&eXE~($i?`_(^6~4PE%~z@YAauR<^k$t( zKM(xZ+5ZN*UVD12PUR@um$p~RzYblRdlJ9g&&u~d@|};&PqCM{&cfE)zI?Y4x*P%& z(KlRy7yREL@Y>7sL<`$nV#rkNguYv1-_Oq@{cK-4;ru23M!}OW>3=^CI;r$usfqi% zWw=88!heDa#lKVlrec3x2~N6Hgwp+zw5>B(@-eg~y3T&eGN0%7;Sc$N-eWNw;Z#hNlvn~*pBVxHudWGePM6Q3u_$2o^wivH) zpI?jd$x5z6#rPB@*Oy|vQpt6r7@w--dQgm4xzDl1_$BW1criXr$-Z2SPj|mNEXHRj z*++}*Z>ulKsppEXS8)vQHJ`v$5~Ac_Cdd$0?ocD_&taP6cGY zD8}cy-)|M;m$~N!#dxifbz6+j!#Zs9Lb_hAzkVx*%{rK_&hqt7q_n;!sSn-r6~XIJ zDVrb<*J}L2Jgn0Ag?R`9_bEI@S6HYO%H61zsY3j+Zti3J2=`0YV=r*>(^KN-V)5_O zerBo1O2+G_8lR~iuC-7rlwY7)Ho-VP1)SO)nq?J~QF|GG6XornfRp~C9OqSR^#Yv(SMTh^^E_Taebx=+1-rKuQK}kSwG46Uo-w1u)=MqpHa&G^%dZ#A%blkrPx zER8fV{-40h@K!;t!wf4rtEDea50uQe>H6YxA?^oWHo^XI4RF7@aJ{bpK9lgeHr?bN z-JZhrVB+swTQojh(btev!0OV*xZKAwtU7`Fh4IiG7r}p`{dg3)dPw6J?$3uWqW|ng z@Hc?ZRE7O~68nE!QeFRU!~r?h#$H?t(hR7Q*qs%>8n=$*%o^+WUj_%EBffu zTdoE^3-i^^w~UUyT&KD{9gg=%^Np`o15<3 zj4zzS;k8BFZH*pLG#T!UC$~l7VSQK;j%0cj4kCKuwqr*FE3aSiZAF4`EZR%lYJ31q z=N-{ZclSxXD#U3R1=tPfdCHIawZm){Y=TSNxz?jDCCGA{6nb-T-S+o?|5O4$lWQmM$!u#MNaMS%XYU4_?ve?!Cirbb04 zOy&!Ayw*lz>E-;9yJdO5W9LuZ+tZn_KI3AOlCR~%x9tdTvO8mG9KtomBWZeBPT$R! z_|hKCH}oZv(hurO#7!H~ZZwt%XVP|5IWZ@0>rd`W)WV)lg~QQwGTeo?+0f;=F7r-* my-!`zvuj&~GKI6YqI4`%CWW>>ii<~f;`KMa|EF1@t^NnlCtaWb literal 0 HcmV?d00001 diff --git a/lib_graphd/inc/binomial-heap/ihtest.c b/lib_graphd/inc/binomial-heap/ihtest.c new file mode 100644 index 0000000..eda1bf9 --- /dev/null +++ b/lib_graphd/inc/binomial-heap/ihtest.c @@ -0,0 +1,116 @@ +#include +#include +#include + +#include "iheap.h" + +struct token { + int prio; + const char* str; +}; + +#define LENGTH(a) (sizeof(a) / sizeof(a[0])) + +struct token tokens1[] = { + {24, "all"}, {16, "star"}, {9, "true.\nSinging"}, {7, "clear"}, + {25, "praises"}, {13, "to"}, {5, "Heel"}, {6, "voices\nRinging"}, + {26, "thine."}, {21, "shine\nCarolina"}, {117, "Rah,"}, {102, "Tar"}, + {108, "bred\nAnd"}, {125, "Rah!"}, {107, "Heel"}, {118, "Rah,"}, + {111, "die\nI'm"}, {115, "dead.\nSo"}, {120, "Rah,"}, + {121, "Car'lina-lina\nRah,"}, {109, "when"}, {105, "a"}, + {123, "Car'lina-lina\nRah!"}, {110, "I"}, {114, "Heel"}, {101, "a"}, + {106, "Tar"}, {18, "all\nClear"}, {14, "the"} +}; + +struct token tokens2[] = { + {113, "Tar"}, {124, "Rah!"}, {112, "a"}, {103, "Heel"}, + {104, "born\nI'm"}, {122, "Rah,"}, {119, "Car'lina-lina\nRah,"}, + {2, "sound"}, {20, "radiance"}, {12, "N-C-U.\nHail"}, + {10, "Carolina's"}, {3, "of"}, {17, "of"}, {23, "gem.\nReceive"}, + {19, "its"}, {0, "\nHark"}, {22, "priceless"}, {4, "Tar"}, + {1, "the"}, {8, "and"}, {15, "brightest"}, + {11, "praises.\nShouting"}, {100, "\nI'm"}, {116, "it's"} +}; + +#define line "\n===================================" + +struct token layout[] = { + {90, line}, {-2, line}, {200, line}, {201, "\n\n"} +}; + + +struct token title[] = { + {1000, "\nUNC Alma Mater:"}, {120, "\nUNC Fight Song:"} +}; + +struct token bad[] = { + {666, "Dook"}, {666666, "Blue Devils"} +}; + + +static void add_token(struct iheap* heap, struct token* tok) +{ + struct iheap_node* hn = malloc(sizeof(struct iheap_node)); + iheap_node_init(hn, tok->prio, tok->str); + iheap_insert(heap, hn); +} + +static void add_token_ref(struct iheap* heap, struct token* tok, + struct iheap_node** hn) +{ + *hn = malloc(sizeof(struct iheap_node)); + iheap_node_init_ref(hn, tok->prio, tok->str); + iheap_insert(heap, *hn); +} + +static void add_tokens(struct iheap* heap, struct token* tok, int len) +{ + int i; + for (i = 0; i < len; i++) + add_token(heap, tok + i); +} + +int main(int argc __attribute__((unused)), char** argv __attribute__((unused))) +{ + struct iheap h1, h2, h3; + struct iheap_node* hn; + struct iheap_node *t1, *t2, *b1, *b2; + const char *str; + + iheap_init(&h1); + iheap_init(&h2); + iheap_init(&h3); + + add_tokens(&h1, tokens1, LENGTH(tokens1)); + add_tokens(&h2, tokens2, LENGTH(tokens2)); + add_tokens(&h3, layout, LENGTH(layout)); + + add_token_ref(&h3, title, &t1); + add_token_ref(&h2, title + 1, &t2); + + iheap_union(&h2, &h3); + iheap_union(&h1, &h2); + + add_token_ref(&h3, bad, &b1); + add_token_ref(&h3, bad + 1, &b2); + + iheap_union(&h1, &h3); + + iheap_delete(&h1, b1); + free(b1); + iheap_delete(&h1, b2); + free(b2); + + iheap_decrease(&h1, t1, -1); + iheap_decrease(&h1, t2, 99); + + printf("ihtest:\n"); + while (!iheap_empty(&h1)) { + hn = iheap_take(&h1); + str = iheap_node_value(hn); + printf("%s ", str); + free(hn); + } + return 0; +} + From 469ec5c93141ba8118c94215060bf1173979d584 Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Wed, 17 Jul 2013 13:06:41 -0400 Subject: [PATCH 23/73] remove binomial heap code --- lib_graphd/inc/GraphProperties.h | 10 --- lib_graphd/src/GraphProperties.cpp | 104 ----------------------------- 2 files changed, 114 deletions(-) diff --git a/lib_graphd/inc/GraphProperties.h b/lib_graphd/inc/GraphProperties.h index d227ce4..05ad6f5 100644 --- a/lib_graphd/inc/GraphProperties.h +++ b/lib_graphd/inc/GraphProperties.h @@ -89,21 +89,11 @@ namespace Graph { void paths_dijkstra_boost_all(Graph *g, vector< vector > &p); #endif - /** - * \brief returns shortest paths from source to all other nodes - */ - void paths_dijkstra_heap_single(Graph *g, vector &dists, int source); - /** * \brief returns shortest paths from all nodes to all nodes */ void paths_dijkstra_all(Graph *g, vector< vector > &p); - /** - * \brief returns shortest paths from all nodes to all nodes - */ - void paths_dijkstra_heap_all(Graph *g, vector< vector > &p); - /** * \brief returns eccentricity for all nodes */ diff --git a/lib_graphd/src/GraphProperties.cpp b/lib_graphd/src/GraphProperties.cpp index d7e954c..b1709d8 100644 --- a/lib_graphd/src/GraphProperties.cpp +++ b/lib_graphd/src/GraphProperties.cpp @@ -664,74 +664,6 @@ namespace Graph { #endif // ifdef HAS_BOOST - /** - * We assume that edge weights are all 1 - * - * \param[in] g input graph - * \param[in] source node id - * \param[out] p path distances from source to all other vertices - */ - void GraphProperties::paths_dijkstra_heap_single(Graph *g, vector &dists, int source){ - struct iheap heap; - struct iheap_node *hn; - const int n = g->get_num_nodes(); - struct iheap_node **heapnodes; - int j, k; - long i; - - dists.resize(n,INDDGO_INFINITY); - dists[source] = 0; - - fprintf(stderr, "Running paths_dijkstra_heap_single on with source node %d\n", source); - fprintf(stderr, "INDDGO_INFINITY is %d\n",INDDGO_INFINITY); - iheap_init(&heap); - - heapnodes = (struct iheap_node **)malloc(n * sizeof(iheap_node *)); - - for(i = 0; i < n; i++){ // insert all of our nodes into the heap - heapnodes[i] = (struct iheap_node *)malloc(sizeof(struct iheap_node)); - hn = heapnodes[i]; - iheap_node_init_ref(&hn, dists[i], (void *)(i)); - iheap_insert(&heap, hn); - //iheap_node_init(hn, dist[n], g->get_node(i)); - } - - // now, keep finding the vertex with the smallest dist[] - // and recompute paths to update all shortest paths - list::const_iterator lcit; - Node *u; - int d; - fprintf(stderr, "Entering for loop, k=0->%d\n",n); - for(k = 0; k < n; k++){ - //if(k == source){ - // continue; - //} - hn = iheap_take(&heap); - i = (long)(hn->value); - fprintf(stderr, " Iteration %d ", k); - fprintf(stderr, " Got i: %lu\n",i); - d = hn->key; - // trying this for speed - u = &(g->nodes[i]); - dists[i] = d; - fprintf(stderr, " d is: %d\n",d); - - const list &nbrs = u->get_nbrs_ref(); - for(lcit = nbrs.begin(); lcit != nbrs.end(); ++lcit){ - fprintf(stderr," Looking at edge (%d,%d)\n", i, *lcit); - hn = heapnodes[*lcit]; - if(d + 1 < hn->key){ - fprintf(stderr," running decrease on node %d, new key should be %d\n",hn->value, d + 1); - iheap_decrease(&heap, hn, d + 1); - } - } - } - fprintf(stderr,"Distances: \n"); - for(k = 0; k < n; k++){ - fprintf(stderr, "%d: %d\n",k, dists[k]); - } - } // paths_dijkstra_heap_single - /** * \param[in] g input graph * \param[in] source node id @@ -831,42 +763,6 @@ namespace Graph { //printf("\n"); } //paths_dijkstra_all - /** - * All pairs shortest paths using heaps - * \param[in] g input graph - * \param[out] p multidimentional list of all pairs shortest paths - */ - - void GraphProperties::paths_dijkstra_heap_all(Graph *g, vector< vector > &pAll){ - int inf = INDDGO_INFINITY; - - int minD = inf; - const int n = g->get_num_nodes(); - - pAll.resize(n); - - //#pragma omp parallel for default(none) shared(g, inf, pAll) private(nvisiting, nVisited, nv) firstprivate(dist, minD, visited) - #pragma omp parallel for schedule(dynamic, 8) default(none) shared(g, inf, pAll) - //loop over all vertices - for(int v = 0; v < n; v++){ //0; v < n; v++){ - //reset all distances to INF and mark all vertices as unvisited - fill(pAll[v].begin(),pAll[v].end(),inf); - paths_dijkstra_heap_single(g, pAll[v], v); //stores shortest paths from this vertex to all in pAll[v] - } //end loop over vertices - - //store the results - g->set_shortest_path_dist(pAll); - - //print out results - //for(int i = 0; i < n; i++){ - // for (int j = 0; j < n; j++) { - // printf("%d, ",pAll[i][j]); - // } - // printf("\n"); - //} - //printf("\n"); - } //paths_dijkstra_heap_all - /** * Calcuates the eccentricity for each vertex (max dist to any other vertex) * \param[in] g input graph From e29bb870454bc57a49f3a747b7e85b7314d15ab6 Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Wed, 17 Jul 2013 13:08:19 -0400 Subject: [PATCH 24/73] Remove heap code from graph_stats --- util/src/graph_stats.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/util/src/graph_stats.cpp b/util/src/graph_stats.cpp index 9f8dfb9..6f9c857 100644 --- a/util/src/graph_stats.cpp +++ b/util/src/graph_stats.cpp @@ -41,7 +41,7 @@ void print_time(string prefix, ORB_t start, ORB_t end){ cout << prefix + ": " << ORB_seconds(end, start) << endl; } -const string allowed_methods ("edge_density,avg_degree,degree_dist,global_cc,avg_cc,local_ccs,shortest_paths,assortativity,eccentricity,eccentricity_dist,expansion,avg_shortest_path,shortest_paths_heap,shortest_paths_boost"); +const string allowed_methods ("edge_density,avg_degree,degree_dist,global_cc,avg_cc,local_ccs,shortest_paths,assortativity,eccentricity,eccentricity_dist,expansion,avg_shortest_path,shortest_paths_boost"); /** * Creates a map from a comma-separated string @@ -223,13 +223,6 @@ int main(int argc, char **argv){ if(req_methods["local_ccs"] == true){ } } - if(req_methods["shortest_paths_heap"] == true){ - cout << "Calculating shortest paths (heap)" << endl; - ORB_read(t1); - gp.paths_dijkstra_heap_all(&g, shortest_path_distances); - ORB_read(t2); - print_time("Time(shortest_paths_dijkstra_heap)", t1, t2); - } if(req_methods["shortest_paths"] == true){ cout << "Calculating shortest paths" << endl; ORB_read(t1); From b69bebc59b8f8c8a926418e81d2844d9e7a1c6f0 Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Wed, 17 Jul 2013 13:24:04 -0400 Subject: [PATCH 25/73] update make.inc.X to include boost definitions --- make.inc.parallel | 7 +++++++ make.inc.serial | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/make.inc.parallel b/make.inc.parallel index a4d72de..d60b22b 100644 --- a/make.inc.parallel +++ b/make.inc.parallel @@ -26,6 +26,9 @@ HAS_METIS = 1 HAS_IGRAPH = 0 HAS_GMP = 0 HAS_GTEST = 0 +# Set to 1 if you have boost installed on your system +# Many linux systems have it installed by default +HAS_BOOST = 0 # Set whether serial or parallel version is desired for WIS. IS_PARALLEL = 1 HAS_MADNESS = 1 @@ -69,6 +72,10 @@ CFLAGS = -O3 CPPFLAGS = LDFLAGS = +ifeq ($(HAS_BOOST),1) +CFLAGS := $(CFLAGS) -DHAS_BOOST +endif + ifeq ($(LOG_ENABLED), 1) CFLAGS := $(CFLAGS) -D__LOG_ENABLE__ endif diff --git a/make.inc.serial b/make.inc.serial index 7df9bcf..6aa1c90 100644 --- a/make.inc.serial +++ b/make.inc.serial @@ -32,6 +32,9 @@ HAS_METIS = 0 HAS_IGRAPH = 0 HAS_GMP = 0 HAS_GTEST = 0 +# Set to 1 if you have boost installed on your system +# Many linux systems have it installed by default +HAS_BOOST = 0 # Set whether serial or parallel version is desired for WIS. IS_PARALLEL = 0 HAS_MADNESS = 0 @@ -89,6 +92,10 @@ ifeq ($(LOG_ENABLED), 1) CFLAGS := $(CFLAGS) -D__LOG_ENABLE__ endif +ifeq ($(HAS_BOOST),1) +CFLAGS := $(CFLAGS) -DHAS_BOOST +endif + ifeq ($(HAS_MADNESS),1) CXX = mpicxx ifeq ($(OLDGCC), 1) From ae45509f53d2169ccbe28063567085ed94b765dd Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Wed, 17 Jul 2013 13:48:16 -0400 Subject: [PATCH 26/73] removing binomial heap code --- lib_graphd/inc/binomial-heap/Makefile | 15 - lib_graphd/inc/binomial-heap/bh.py | 434 ------------------ lib_graphd/inc/binomial-heap/heap.h | 381 --------------- lib_graphd/inc/binomial-heap/htest | Bin 13284 -> 0 bytes lib_graphd/inc/binomial-heap/htest.c | 125 ----- lib_graphd/inc/binomial-heap/iheap.h | 385 ---------------- lib_graphd/inc/binomial-heap/iheap.h.noinline | 385 ---------------- lib_graphd/inc/binomial-heap/iheap.h.orig | 385 ---------------- lib_graphd/inc/binomial-heap/ihtest | Bin 13145 -> 0 bytes lib_graphd/inc/binomial-heap/ihtest.c | 116 ----- 10 files changed, 2226 deletions(-) delete mode 100644 lib_graphd/inc/binomial-heap/Makefile delete mode 100644 lib_graphd/inc/binomial-heap/bh.py delete mode 100644 lib_graphd/inc/binomial-heap/heap.h delete mode 100755 lib_graphd/inc/binomial-heap/htest delete mode 100644 lib_graphd/inc/binomial-heap/htest.c delete mode 100644 lib_graphd/inc/binomial-heap/iheap.h delete mode 100644 lib_graphd/inc/binomial-heap/iheap.h.noinline delete mode 100644 lib_graphd/inc/binomial-heap/iheap.h.orig delete mode 100755 lib_graphd/inc/binomial-heap/ihtest delete mode 100644 lib_graphd/inc/binomial-heap/ihtest.c diff --git a/lib_graphd/inc/binomial-heap/Makefile b/lib_graphd/inc/binomial-heap/Makefile deleted file mode 100644 index a0fe929..0000000 --- a/lib_graphd/inc/binomial-heap/Makefile +++ /dev/null @@ -1,15 +0,0 @@ - -CFLAGS = -Wall -Wextra -Werror -ansi -std=c99 -pedantic - -ALL = htest ihtest - -.PHONY: clean all - -all: ${ALL} - -clean: - rm -f ${ALL} *.pyc - -htest: htest.c - -ihtest: ihtest.c diff --git a/lib_graphd/inc/binomial-heap/bh.py b/lib_graphd/inc/binomial-heap/bh.py deleted file mode 100644 index 6559897..0000000 --- a/lib_graphd/inc/binomial-heap/bh.py +++ /dev/null @@ -1,434 +0,0 @@ -#!/usr/bin/env python -# -# Copyright (c) 2008, Bjoern B. Brandenburg -# -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# * Neither the name of the copyright holder nor the -# names of its contributors may be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. - -"""An implementation of Binomial Heaps. - -From Wikipedia: - A binomial heap is a heap similar to a binary heap but also supporting the - operation of merging two heaps quickly. This is achieved by using a special - tree structure. - - All of the following operations work in O(log n) time on a binomial heap with - n elements: - - Insert a new element to the heap - - Find the element with minimum key - - Delete the element with minimum key from the heap - - Decrease key of a given element - - Delete given element from the heap - - Merge two given heaps to one heap - - More details: http://en.wikipedia.org/wiki/Binomial_heap - -This implementation is based on the description in CLRS. -""" - -class ItemRef(object): - """Reference to an item in the heap. Used for decreasing keys and deletion. - Do not use this class directly; only use instances returned by - BinomialHeap.insert()! - - You should only use ItemRef.delete() and ItemRef.decrease(new_priority). - """ - def __init__(self, node, get_heap): - self.ref = node - self.get_heap = get_heap - self.in_tree = True - - def __str__(self): - if self.in_tree: - return "" % str(self.ref.val) - else: - return "" - - def decrease(self, new_key): - "Update the priority of the referenced item to a lower value." - assert self.in_tree - assert self.ref.ref == self - self.ref.decrease(new_key) - - def delete(self): - """Remove the referenced item from the heap. - """ - self.decrease(self) - v = self.get_heap().extract_min() - assert not self.in_tree - assert v is self.ref.val - - def in_heap(self, heap): - """Returns True if the referenced item is part of the BinomialHeap 'heap'; - False otherwise. - """ - return self.in_tree and self.get_heap() == heap - - def __lt__(self, other): - "Behaves like negative infinity: always True." - return True - - def __gt__(self, other): - "Behaves like negative infinity: always False." - return False - - -class BinomialHeap(object): - """Usage: - > H1 = BinomialHeap() - > H1.insert(40, "fast.") - > H1.insert(10, "Merging") - > H2 = BinomialHeap([(30, "quite"), (20, "is")]) - > H1 += H2 - > for x in H1: - > print x, - => "Merging is quite fast." - - """ - - class Node(object): - "Internal node of the heap. Don't use directly." - def __init__(self, get_heap, key, val=None): - self.degree = 0 - self.parent = None - self.next = None - self.child = None - self.key = key - self.ref = ItemRef(self, get_heap) - if val == None: - val = key - self.val = val - - def __str__(self): - k = lambda x: str(x.key) if x else 'NIL' - return '(%s, c:%s, n:%s)' % (k(self), k(self.child), k(self.next)) - - def link(self, other): - "Makes other a subtree of self." - other.parent = self - other.next = self.child - self.child = other - self.degree += 1 - - def decrease(self, new_key): - node = self - assert new_key < node.key - node.key = new_key - cur = node - parent = cur.parent - while parent and cur.key < parent.key: - # need to bubble up - # swap refs - parent.ref.ref, cur.ref.ref = cur, parent - parent.ref, cur.ref = cur.ref, parent.ref - # now swap keys and payload - parent.key, cur.key = cur.key, parent.key - parent.val, cur.val = cur.val, parent.val - # step up - cur = parent - parent = cur.parent - - @staticmethod - def roots_merge(h1, h2): - """Merge two lists of heap roots, sorted by degree. - Returns the new head. - """ - if not h1: - return h2 - if not h2: - return h1 - if h1.degree < h2.degree: - h = h1 - h1 = h.next - else: - h = h2 - h2 = h2.next - p = h - while h2 and h1: - if h1.degree < h2.degree: - p.next = h1 - h1 = h1.next - else: - p.next = h2 - h2 = h2.next - p = p.next - if h2: - p.next = h2 - else: - p.next = h1 - return h - - @staticmethod - def roots_reverse(h): - """Reverse the heap root list. - Returns the new head. Also clears parent references. - """ - if not h: - return None - tail = None - next = h - h.parent = None - while h.next: - next = h.next - h.next = tail - tail = h - h = next - h.parent = None - h.next = tail - return h - - class __Ref(object): - def __init__(self, h): - self.heap = h - self.ref = None - def get_heap_ref(self): - if not self.ref: - return self - else: - # compact - self.ref = self.ref.get_heap_ref() - return self.ref - def get_heap(self): - return self.get_heap_ref().heap - - def __init__(self, lst=[]): - """Populate a new heap with the (key, value) pairs in 'lst'. - If the elements of lst are not subscriptable, then they are treated as - opaque elements and inserted into the heap themselves. - """ - self.head = None - self.size = 0 - self.ref = BinomialHeap.__Ref(self) - for x in lst: - try: - self.insert(x[0], x[1]) - except TypeError: - self.insert(x) - - def insert(self, key, value=None): - """Insert 'value' in to the heap with priority 'key'. If 'value' is omitted, - then 'key' is used as the value. - Returns a reference (of type ItemRef) to the internal node in the tree. - Use this reference to delete the key or to change its priority. - """ - n = BinomialHeap.Node(self.ref.get_heap, key, value) - self.__union(n) - self.size += 1 - return n.ref - - def union(self, other): - """Merge 'other' into 'self'. Returns None. - Note: This is a destructive operation; 'other' is an empty heap afterwards. - """ - self.size = self.size + other.size - h2 = other.head - self.__union(h2) - other.ref.ref = self.ref - other.__init__() - - def min(self): - """Returns the value with the minimum key (= highest priority) in the heap - without removing it, or None if the heap is empty. - """ - pos = self.__min() - return pos[0].val if pos else None - - def extract_min(self): - """Returns the value with the minimum key (= highest priority) in the heap - AND removes it from the heap, or None if the heap is empty. - """ - # find mininum - pos = self.__min() - if not pos: - return None - else: - (x, prev) = pos - # remove from list - if prev: - prev.next = x.next - else: - self.head = x.next - kids = BinomialHeap.Node.roots_reverse(x.child) - self.__union(kids) - x.ref.in_tree = False - self.size -= 1 - return x.val - - def __nonzero__(self): - """True if the heap is not empty; False otherwise.""" - return self.head != None - - def __iter__(self): - """Returns a _destructive_ iterator over the values in the heap. - This violates the iterator protocol slightly, but is very useful. - """ - return self - - def __len__(self): - """Returns the number of items in this heap.""" - return self.size - - def __setitem__(self, key, value): - """Insert. - H[key] = value is equivalent to H.insert(key, value) - """ - self.insert(key, value) - - def __iadd__(self, other): - """Merge. - a += b is equivalent to a.union(b). - """ - self.union(other) - return self - - def next(self): - """Returns the value with the minimum key (= highest priority) in the heap - AND removes it from the heap; raises StopIteration if the heap is empty. - """ - if self.head: - return self.extract_min() - else: - raise StopIteration - - def __contains__(self, ref): - """Test whether a given reference 'ref' (of ItemRef) is in this heap. - """ - if type(ref) != ItemRef: - raise TypeError, "Expected an ItemRef" - else: - return ref.in_heap(self) - - def __min(self): - if not self.head: - return None - min = self.head - min_prev = None - prev = min - cur = min.next - while cur: - if cur.key < min.key: - min = cur - min_prev = prev - prev = cur - cur = cur.next - return (min, min_prev) - - def __union(self, h2): - if not h2: - # nothing to do - return - h1 = self.head - if not h1: - self.head = h2 - return - h1 = BinomialHeap.Node.roots_merge(h1, h2) - prev = None - x = h1 - next = x.next - while next: - if x.degree != next.degree or \ - (next.next and next.next.degree == x.degree): - prev = x - x = next - elif x.key <= next.key: - # x becomes the root of next - x.next = next.next - x.link(next) - else: - # next becomes the root of x - if not prev: - # update the "master" head - h1 = next - else: - # just update previous link - prev.next = next - next.link(x) - # x is not toplevel anymore, update ref by advancing - x = next - next = x.next - self.head = h1 - -def heap(lst=[]): - """Create a new heap. lst should be a sequence of (key, value) pairs. - Shortcut for BinomialHeap(lst) - """ - return BinomialHeap(lst) - -if __name__ == "__main__": - tokens1 = [(24, 'all'), (16, 'star'), (9, 'true.\nSinging'), (7, 'clear'), - (25, 'praises'), (13, 'to'), (5, 'Heel'), - (6, 'voices\nRinging'), (26, 'thine.'), (21, 'shine\nCarolina'), - (117, 'Rah,'), (102, 'Tar'), (108, 'bred\nAnd'), (125, 'Rah!'), - (107, 'Heel'), (118, 'Rah,'), (111, "die\nI'm"), - (115, 'dead.\nSo'), (120, 'Rah,'), (121, "Car'lina-lina\nRah,"), - (109, 'when'), (105, 'a'), (123, "Car'lina-lina\nRah!"), - (110, 'I'), (114, 'Heel'), (101, 'a'), (106, 'Tar'), - (18, 'all\nClear'), (14, 'the')] - tokens2 = [(113, 'Tar'), (124, 'Rah!'), (112, 'a'), (103, 'Heel'), - (104, "born\nI'm"), (122, 'Rah,'), (119, "Car'lina-lina\nRah,"), - (2, 'sound'), (20, 'radiance'), (12, 'N-C-U.\nHail'), - (10, "Carolina's"), (3, 'of'), (17, 'of'), - (23, 'gem.\nReceive'), (19, 'its'), (0, '\nHark'), - (22, 'priceless'), (4, 'Tar'), (1, 'the'), (8, 'and'), - (15, 'brightest'), (11, 'praises.\nShouting'), - (100, "\nI'm"), (116, "it's")] - h1 = heap(tokens1) - h2 = heap(tokens2) - h3 = heap() - line = "\n===================================" - h3[90] = line - h3[-2] = line - h3[200] = line - h3[201] = '\n\n' - t1ref = h3.insert(1000, "\nUNC Alma Mater:") - t2ref = h3.insert(120, "\nUNC Fight Song:") - bad = [h3.insert(666, "Dook"), - h3.insert(666, "Go Devils!"), - h3.insert(666, "Blue Devils") ] - - ref = bad[0] - print "%s: \n\tin h1: %s\n\tin h2: %s\n\tin h3: %s" % \ - (str(ref), ref in h1, ref in h2, ref in h3) - - print "Merging h3 into h2..." - h2 += h3 - - print "%s: \n\tin h1: %s\n\tin h2: %s\n\tin h3: %s" % \ - (str(ref), ref in h1, ref in h2, ref in h3) - - print "Merging h2 into h1..." - h1 += h2 - - print "%s: \n\tin h1: %s\n\tin h2: %s\n\tin h3: %s" % \ - (str(ref), ref in h1, ref in h2, ref in h3) - - t1ref.decrease(-1) - t2ref.decrease(99) - - for ref in bad: - ref.delete() - for x in h1: - print x, - diff --git a/lib_graphd/inc/binomial-heap/heap.h b/lib_graphd/inc/binomial-heap/heap.h deleted file mode 100644 index 8cefc02..0000000 --- a/lib_graphd/inc/binomial-heap/heap.h +++ /dev/null @@ -1,381 +0,0 @@ -/* heap.h -- Binomial Heaps - * - * Copyright (c) 2008, Bjoern B. Brandenburg - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the University of North Carolina nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY COPYRIGHT OWNER AND CONTRIBUTERS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTERS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef HEAP_H -#define HEAP_H - -#define NOT_IN_HEAP UINT_MAX - -struct heap_node { - struct heap_node* parent; - struct heap_node* next; - struct heap_node* child; - - unsigned int degree; - void* value; - struct heap_node** ref; -}; - -struct heap { - struct heap_node* head; - /* We cache the minimum of the heap. - * This speeds up repeated peek operations. - */ - struct heap_node* min; -}; - -/* item comparison function: - * return 1 if a has higher prio than b, 0 otherwise - */ -typedef int (*heap_prio_t)(struct heap_node* a, struct heap_node* b); - -static inline void heap_init(struct heap* heap) -{ - heap->head = NULL; - heap->min = NULL; -} - -static inline void heap_node_init_ref(struct heap_node** _h, void* value) -{ - struct heap_node* h = *_h; - h->parent = NULL; - h->next = NULL; - h->child = NULL; - h->degree = NOT_IN_HEAP; - h->value = value; - h->ref = _h; -} - -static inline void heap_node_init(struct heap_node* h, void* value) -{ - h->parent = NULL; - h->next = NULL; - h->child = NULL; - h->degree = NOT_IN_HEAP; - h->value = value; - h->ref = NULL; -} - -static inline void* heap_node_value(struct heap_node* h) -{ - return h->value; -} - -static inline int heap_node_in_heap(struct heap_node* h) -{ - return h->degree != NOT_IN_HEAP; -} - -static inline int heap_empty(struct heap* heap) -{ - return heap->head == NULL && heap->min == NULL; -} - -/* make child a subtree of root */ -static inline void __heap_link(struct heap_node* root, - struct heap_node* child) -{ - child->parent = root; - child->next = root->child; - root->child = child; - root->degree++; -} - -/* merge root lists */ -static inline struct heap_node* __heap_merge(struct heap_node* a, - struct heap_node* b) -{ - struct heap_node* head = NULL; - struct heap_node** pos = &head; - - while (a && b) { - if (a->degree < b->degree) { - *pos = a; - a = a->next; - } else { - *pos = b; - b = b->next; - } - pos = &(*pos)->next; - } - if (a) - *pos = a; - else - *pos = b; - return head; -} - -/* reverse a linked list of nodes. also clears parent pointer */ -static inline struct heap_node* __heap_reverse(struct heap_node* h) -{ - struct heap_node* tail = NULL; - struct heap_node* next; - - if (!h) - return h; - - h->parent = NULL; - while (h->next) { - next = h->next; - h->next = tail; - tail = h; - h = next; - h->parent = NULL; - } - h->next = tail; - return h; -} - -static inline void __heap_min(heap_prio_t higher_prio, struct heap* heap, - struct heap_node** prev, struct heap_node** node) -{ - struct heap_node *_prev, *cur; - *prev = NULL; - - if (!heap->head) { - *node = NULL; - return; - } - - *node = heap->head; - _prev = heap->head; - cur = heap->head->next; - while (cur) { - if (higher_prio(cur, *node)) { - *node = cur; - *prev = _prev; - } - _prev = cur; - cur = cur->next; - } -} - -static inline void __heap_union(heap_prio_t higher_prio, struct heap* heap, - struct heap_node* h2) -{ - struct heap_node* h1; - struct heap_node *prev, *x, *next; - if (!h2) - return; - h1 = heap->head; - if (!h1) { - heap->head = h2; - return; - } - h1 = __heap_merge(h1, h2); - prev = NULL; - x = h1; - next = x->next; - while (next) { - if (x->degree != next->degree || - (next->next && next->next->degree == x->degree)) { - /* nothing to do, advance */ - prev = x; - x = next; - } else if (higher_prio(x, next)) { - /* x becomes the root of next */ - x->next = next->next; - __heap_link(x, next); - } else { - /* next becomes the root of x */ - if (prev) - prev->next = next; - else - h1 = next; - __heap_link(next, x); - x = next; - } - next = x->next; - } - heap->head = h1; -} - -static inline struct heap_node* __heap_extract_min(heap_prio_t higher_prio, - struct heap* heap) -{ - struct heap_node *prev, *node; - __heap_min(higher_prio, heap, &prev, &node); - if (!node) - return NULL; - if (prev) - prev->next = node->next; - else - heap->head = node->next; - __heap_union(higher_prio, heap, __heap_reverse(node->child)); - return node; -} - -/* insert (and reinitialize) a node into the heap */ -static inline void heap_insert(heap_prio_t higher_prio, struct heap* heap, - struct heap_node* node) -{ - struct heap_node *min; - node->child = NULL; - node->parent = NULL; - node->next = NULL; - node->degree = 0; - if (heap->min && higher_prio(node, heap->min)) { - /* swap min cache */ - min = heap->min; - min->child = NULL; - min->parent = NULL; - min->next = NULL; - min->degree = 0; - __heap_union(higher_prio, heap, min); - heap->min = node; - } else - __heap_union(higher_prio, heap, node); -} - -static inline void __uncache_min(heap_prio_t higher_prio, struct heap* heap) -{ - struct heap_node* min; - if (heap->min) { - min = heap->min; - heap->min = NULL; - heap_insert(higher_prio, heap, min); - } -} - -/* merge addition into target */ -static inline void heap_union(heap_prio_t higher_prio, - struct heap* target, struct heap* addition) -{ - /* first insert any cached minima, if necessary */ - __uncache_min(higher_prio, target); - __uncache_min(higher_prio, addition); - __heap_union(higher_prio, target, addition->head); - /* this is a destructive merge */ - addition->head = NULL; -} - -static inline struct heap_node* heap_peek(heap_prio_t higher_prio, - struct heap* heap) -{ - if (!heap->min) - heap->min = __heap_extract_min(higher_prio, heap); - return heap->min; -} - -static inline struct heap_node* heap_take(heap_prio_t higher_prio, - struct heap* heap) -{ - struct heap_node *node; - if (!heap->min) - heap->min = __heap_extract_min(higher_prio, heap); - node = heap->min; - heap->min = NULL; - if (node) - node->degree = NOT_IN_HEAP; - return node; -} - -static inline void heap_decrease(heap_prio_t higher_prio, struct heap* heap, - struct heap_node* node) -{ - struct heap_node *parent; - struct heap_node** tmp_ref; - void* tmp; - - /* node's priority was decreased, we need to update its position */ - if (!node->ref) - return; - if (heap->min != node) { - if (heap->min && higher_prio(node, heap->min)) - __uncache_min(higher_prio, heap); - /* bubble up */ - parent = node->parent; - while (parent && higher_prio(node, parent)) { - /* swap parent and node */ - tmp = parent->value; - parent->value = node->value; - node->value = tmp; - /* swap references */ - if (parent->ref) - *(parent->ref) = node; - *(node->ref) = parent; - tmp_ref = parent->ref; - parent->ref = node->ref; - node->ref = tmp_ref; - /* step up */ - node = parent; - parent = node->parent; - } - } -} - -static inline void heap_delete(heap_prio_t higher_prio, struct heap* heap, - struct heap_node* node) -{ - struct heap_node *parent, *prev, *pos; - struct heap_node** tmp_ref; - void* tmp; - - if (!node->ref) /* can only delete if we have a reference */ - return; - if (heap->min != node) { - /* bubble up */ - parent = node->parent; - while (parent) { - /* swap parent and node */ - tmp = parent->value; - parent->value = node->value; - node->value = tmp; - /* swap references */ - if (parent->ref) - *(parent->ref) = node; - *(node->ref) = parent; - tmp_ref = parent->ref; - parent->ref = node->ref; - node->ref = tmp_ref; - /* step up */ - node = parent; - parent = node->parent; - } - /* now delete: - * first find prev */ - prev = NULL; - pos = heap->head; - while (pos != node) { - prev = pos; - pos = pos->next; - } - /* we have prev, now remove node */ - if (prev) - prev->next = node->next; - else - heap->head = node->next; - __heap_union(higher_prio, heap, __heap_reverse(node->child)); - } else - heap->min = NULL; - node->degree = NOT_IN_HEAP; -} - -#endif /* HEAP_H */ diff --git a/lib_graphd/inc/binomial-heap/htest b/lib_graphd/inc/binomial-heap/htest deleted file mode 100755 index cef7a067863848f6743ee6b7e8ae51f7fdcdfe9b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13284 zcmcIr4RBo5b-r3zwh*=@V=(>^cwGbt2Ft=2V}A2&S!P9KBWx=q;ILk6pRC2wuChNy zCU)aQhVf=G7>0%>rGv|)t(j8l=@8<96lCl~X39|0OoJNSR0W)@5e#wzL=Zsz&bjBj zeY>`jPG|Z+d+zzp&pr3tbMO20x0+j518lntO4aT**mib;$(Oi=J^QKqZrp|im&JEYxwP#!B;LqQD z_vt6eR{zlaUmx?KNqv+aL^k&j2)0>RN)19U#(%qftfG&wew5q=g+}K$pUuju0G&~-3OLG*cg)+!O~Pq@^r-aVT011G@!|gU zHQR^#>nqg%US<9-V3@xg-R4hB#}es3Qh9j%>PKb;&G^NS;GFwYJivUCcnbC8KJZt*-;#a(u2A-^Q2#rlZR=YG2lk%h zn9$&%eM|-)sc}sH$58xm?_P>Al&d&(UeJW@8%PJnk8y~5{YQH!dtx0a?!2*PZV-9@ z@(atb#9>wiHuUY0M&b_rzC6@FQWm;)C{@>4Js*=2>K`ZzWh+k1!C=q*DJ$hF-T()k z;8;!Vt*r#-lUQ5A~Zq=O9Cft@0%Y{k$?h{L10Idr20` z?idT@n#V$eq=I;;>F}z3<*+E^L)pwQB>7OzgtAaLv%c7JWl?+3nN5jhIM+TL%C-fi z4To*@p8GMlAGOA(#b9A)0-vLv&q1f2Y<)f{#+(x@MQDaH=h`@&N@AuQq#_xq;2inX zZBPiT9Rb!@i#DRvE9RU0w^N&CIcN5swlYGqZL>WuHgki`qZC|d51BTPjob#ce6DRa z$S~}#eK|Ep+(DnbA<>8}+ngUcUj)b=2`~#RpxHq8R2`%@7V6)TH|Z%L!zS}rmYXJ~ zC`1gBXNv}MOrzNf1_DaPF)t@nl@tbBNTegptiqZI zdo?=xMJPKs{yJ8{EGyE99kL@LpEMBi1Pe|yWp>PDp7mmO5Hn)Up!4>l5FRzvyRJh4 zS&tORu$=`PVGc^!nv-)_18s_t zO$QE-l(x3Y5ooe+Bpvm@ZMJv;79t|p8w_W%`o4vBOE?BAq@re|Y_H8NZI1O`a`&tr z4((}2XJ3aRiX!_f3g!sqjPk_Gma;ao9(6&piQo*4hZJ0nc7|#G+#&;uSOomZJMSWEh|hFb`i9Sm9Bu2H^iW~5_u8X zfESeng;LetPwVn^WUj~?Y6P2lmZq?%I&wVy1XJ;F!SvaR091n*N3DbhvfGxDZbd~M zU_E2wD1@7tXD1&;VBP*LXMu`rMWv@_&t8R*(CSX}=IA?HdHpzEJHu<#iZ@jPxk1G*!H1?7m~|Aj=`)-kGHyE-A}!(FPGEj462D*aagw{c%Wk z1DMZ_81;{*`o3E+h2BcWLT*Fij$(oaPyq+w27i*c+ijW#I8E0#AFSSWg+-u3Jq_vL zhkS#Fj0a8COalh*4W9J8!CNMWK6$jz&`Jfc8Km9@9az`Corb{&?2W`C$GRmLG$! zQG15WnQLFJete+%xdE^GJufdcV#xXDKV%=Up*_}Hz1NT{d(J>tKYOXO8W+Yde>%~2 zV132e7q(wY9Hxf12sC*$-2V}Iq!iMmjd@Oc{7xHnh}rhzgUz4OoQzzQYyK?s=b=Nx zlW1!%=P=c2JtnWe`Li;pT;F_r`@eak?9J|Y9F@8kS7)4>-%x0K=;C59|E6sZQ2SqO zd-(Ya(AA61yp4v?IMoESpQr8q#oz@N{i;O=o~PT17x!Ig(G`rMHup3Syf`f25H0;Z z?FY!oi=zS_w%~w`Lvs2Ah7ZkS01>Ew-?iX=_G#wZj&@n|eGJwJm?-!xn17kfbM0ha z0GHWacR!8q#DB8_xhg1}Zx!~D!VxG8R(v`YwAUl|%Uo3Y@zd z%zygZ@p0^qPqG%>_~7_0-7Wd=m$Kb;L#^3p9j-eTZkZf3t$Qwx5&@oX&8F){TeI8i zP>dVuaCi6KvewH^EYE)4lKnVz==1WH>>K%Y)cJkyr)#f#lkP`bv!AwRKVF&rVEOpD z$3y*xaZfjrd^eQaP=_6$yRN1+7pu41?% zh%5cE@${S*g1CE=`@)e*+-K%+zc@CYIVE?1_Fgpq5XC}w$#k#ozl%2p4-O1HTQKQl z#%-ut7mIJk|E8nc1=gF4#8Pg`q!T9Oy4_}LBG%!is@959x+@lU8%&BwRZ}FHz@waq zSsUrP!mNk&rlcFKS{{!QvcN=RZdJ>rJtpc#qUa}KU~nlJ&;y`I6EA6JzI&?(ZmB^$iCEQ&s4R3T*-T223 zQ&nZE+SfD%mv{F>f~zBGH+h`}R#7*>b&2@q>&(hTVvAYPopFOJ-L0|il;HrbGZ&|V z=%;L6`StY7jrNo7(eZJ*H`oJOiL>N;p!J{*O)uzLPx;7Q3Y z&_>W#LEAtV{2un8cZ2Q)?ZOq;0nk3sqo8!qb2~c9?pW?s!t&`g_XnD$P2K13w>g@???xFFpBZz`qaq_9FQ`p1c-$_z3c6 zi{$^{$!~x>i#go@>gA{W_A*ka14Q^wF~^Vj?Z4Jv9@xe%2<05_g5DC;z}tSkz^}Z1 zehB&RAYW4?Z}H?uAio&36DgA0iK+$m4&>a%-cn@0(vu&7 z{9hseq$s`*IXz<%IaLT`JZ;{M6u=}!NYhXN0l@0k?%>U64e zJ?QL7$3(p16apRmL=1E)bH*&2u0S&l5f-{9NI`DSWN)ap4yU zpA=r>b4%>+7GB58=Nw>Hiv4tvUoX6{9{Gl})Sk~7z%)O-BG-5~3$O9;-V5wY;{RTe zYd-D~Uh|>rG$i`EPS*&p`^xRY>%Pz-ysrDW@H51}^19ByA@Z3b|5M?GHQy0_mH@kj zr#mM)G#|RYHGjHKJRQ@KA^d>w*k^bzR{m&-{1xF( zh<;uYk{4d<@e|>HAPKKJ&tc2Uudo@d7XId@rt5>p?f!YZ~H-wA-+JMa#l;WV3LaxbbV(}P$({3Mr zJHbGfh(^*8)8KZ6JCl(fH{2D4t#YQJBb`X5(4i%FcR&cAk)BuwI!wR~ej3=f^|J|= z>kS==o*p-@^Cs#4Ka+W|q?*!oU;+*}90JgFiT}|0Q|ux%XpdF<+JFO&-n%m~K})<} zt!D+UM8j`?L%?Ct4PsB%5B{UnekFvsY)@$a8v_myI?prV>pp7fzOL)VN{yjwJz67b zzcb)~GiIj%`0FY7?BAH)skTH8eL!XKTx)n3onePXZs zrN*y%O6hz-*8@#a_p${g;k^SBbq|&kTsY zu79$py|mQ+L0}Y@o@e#?ZJA88_74?41Xk8$(em53O>$V)CW;%GEBvUvUN<}nk>6gw z!#N;|2Xz9(h1#jdAC%bZ^=6lB^d;t;Yqcf14}a9Z=D$zR<6{2|34Mp=Poe#2`0e$( z75$#&RaF$K<5&2(68kaPhsWf?rcUNj^-KF75PMal2Qzf&cR!{1DzzVkF2%3*^k$!q zM!8V?WA?8>*KhBLy(9Le{gv`RhdtGv_OI8k`u&l9XQcJ1_8QmmlK%C(k)gQ|;81d9ZDh?LZR~WEOn8vN!p|t0E|Aik!TkRAkUe}IdM2}r+xr36Z z3&1wvPxGex%2~k9)c2~8x<3}h^3!!pKC&qFitfWcjKg@ab%xD(AXQ;1*J&E106%RZy)u@5-; z=`HayQT)5u&pD>PWWF9|e1@4l$3d%bJb`A}8RqftfK$JXGo6AmT8Hp=ro7Sp4(UHC zaV`)mI*$z7ds|2qV`~$(C z6#O#5AD-ecvR&|Hf={co__KmH34Ta$e%1UbR=-Q|M+ARHaDHYA**?L4GtKJrvr^zs3r??H>CpT;@4(B<>Ff6c;PfSIZAl$s63>Xw1YUNAeS_|of_U3ex({3m z9Mx>-l`0)Oxj$nT0oR&gf&4TvKF!cqnsk8WW1Zl7eJilJ19(swAB|0b?_fVZMQJ|7 z`04xhpG~0u)CBlZ;4@5NpPwZD-(Y;Uq4&jf1o_vP|Cqqf2f%C2kWYFRJtI(Uc9yL7 zvv8iD5twP{V^se!3-~!$kNYH_SrJ}B`tWaL9}5b8Iq(|nx25~`QqgzjZDh@3GLJWj zexvviH>POZ(SR1ZCSS-UtWj9D~q^WntY;YBD}dfu_@9W=7$*JNT$!=0Yz`On|7lOORrjT zjUhoe7VRVMT6~yI&q1P@o}O*mPxG3U+|8=B%U3stm7{L7UFe0Mm~b!rwh+N~xsl#5 zKYHO-JP~!74JX}BEA${AyETFrkCu0PdeamOo8z7A7H#*q$<3}ZNtYf4d2A29F&C3e zoE{JfgNHxKNJlzMa)~VECesjS;vJEWF1H}DcC3_+Y>{B1Zb#CMpdZGgcte|Z@fv!I z8xME%^qNRC8fLE0;&FO-%7kxjy>-R%*6^*XR;_DZA6~zFMQbxnBBdxCNhTxP!Y>;Dq9uy0V| za5R+&cj3i1bfvtt)c79~(2%&KHbp2?c -#include -#include - -#include "heap.h" - -struct token { - int prio; - const char* str; -}; - -#define LENGTH(a) (sizeof(a) / sizeof(a[0])) - -struct token tokens1[] = { - {24, "all"}, {16, "star"}, {9, "true.\nSinging"}, {7, "clear"}, - {25, "praises"}, {13, "to"}, {5, "Heel"}, {6, "voices\nRinging"}, - {26, "thine."}, {21, "shine\nCarolina"}, {117, "Rah,"}, {102, "Tar"}, - {108, "bred\nAnd"}, {125, "Rah!"}, {107, "Heel"}, {118, "Rah,"}, - {111, "die\nI'm"}, {115, "dead.\nSo"}, {120, "Rah,"}, - {121, "Car'lina-lina\nRah,"}, {109, "when"}, {105, "a"}, - {123, "Car'lina-lina\nRah!"}, {110, "I"}, {114, "Heel"}, {101, "a"}, - {106, "Tar"}, {18, "all\nClear"}, {14, "the"} -}; - -struct token tokens2[] = { - {113, "Tar"}, {124, "Rah!"}, {112, "a"}, {103, "Heel"}, - {104, "born\nI'm"}, {122, "Rah,"}, {119, "Car'lina-lina\nRah,"}, - {2, "sound"}, {20, "radiance"}, {12, "N-C-U.\nHail"}, - {10, "Carolina's"}, {3, "of"}, {17, "of"}, {23, "gem.\nReceive"}, - {19, "its"}, {0, "\nHark"}, {22, "priceless"}, {4, "Tar"}, - {1, "the"}, {8, "and"}, {15, "brightest"}, - {11, "praises.\nShouting"}, {100, "\nI'm"}, {116, "it's"} -}; - -#define line "\n===================================" - -struct token layout[] = { - {90, line}, {-2, line}, {200, line}, {201, "\n\n"} -}; - - -struct token title[] = { - {1000, "\nUNC Alma Mater:"}, {120, "\nUNC Fight Song:"} -}; - -struct token bad[] = { - {666, "Dook"}, {666666, "Blue Devils"} -}; - -static int token_cmp(struct heap_node* _a, struct heap_node* _b) -{ - struct token *a, *b; - a = (struct token*) heap_node_value(_a); - b = (struct token*) heap_node_value(_b); - return a->prio < b->prio; -} - -static void add_token(struct heap* heap, struct token* tok) -{ - struct heap_node* hn = malloc(sizeof(struct heap_node)); - heap_node_init(hn, tok); - heap_insert(token_cmp, heap, hn); -} - -static void add_token_ref(struct heap* heap, struct token* tok, - struct heap_node** hn) -{ - *hn = malloc(sizeof(struct heap_node)); - heap_node_init_ref(hn, tok); - heap_insert(token_cmp, heap, *hn); -} - -static void add_tokens(struct heap* heap, struct token* tok, int len) -{ - int i; - for (i = 0; i < len; i++) - add_token(heap, tok + i); -} - -int main(int argc __attribute__((unused)), char** argv __attribute__((unused))) -{ - struct heap h1, h2, h3; - struct heap_node* hn; - struct heap_node *t1, *t2, *b1, *b2; - struct token *tok; - - heap_init(&h1); - heap_init(&h2); - heap_init(&h3); - - add_tokens(&h1, tokens1, LENGTH(tokens1)); - add_tokens(&h2, tokens2, LENGTH(tokens2)); - add_tokens(&h3, layout, LENGTH(layout)); - - add_token_ref(&h3, title, &t1); - add_token_ref(&h2, title + 1, &t2); - - heap_union(token_cmp, &h2, &h3); - heap_union(token_cmp, &h1, &h2); - - add_token_ref(&h3, bad, &b1); - add_token_ref(&h3, bad + 1, &b2); - - heap_union(token_cmp, &h1, &h3); - - heap_delete(token_cmp, &h1, b1); - free(b1); - heap_delete(token_cmp, &h1, b2); - free(b2); - - title[0].prio = -1; - title[1].prio = 99; - - heap_decrease(token_cmp, &h1, t1); - heap_decrease(token_cmp, &h1, t2); - - printf("htest:\n"); - while (!heap_empty(&h1)) { - hn = heap_take(token_cmp, &h1); - tok = heap_node_value(hn); - printf("%s ", tok->str); - free(hn); - } - return 0; -} diff --git a/lib_graphd/inc/binomial-heap/iheap.h b/lib_graphd/inc/binomial-heap/iheap.h deleted file mode 100644 index a697f4e..0000000 --- a/lib_graphd/inc/binomial-heap/iheap.h +++ /dev/null @@ -1,385 +0,0 @@ -/* iheap.h -- Binomial Heaps with integer priorities - * - * Copyright (c) 2008, Bjoern B. Brandenburg - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the University of North Carolina nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY COPYRIGHT OWNER AND CONTRIBUTERS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTERS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef IHEAP_H -#define IHEAP_H - -#define NOT_IN_HEAP UINT_MAX - -struct iheap_node { - struct iheap_node* parent; - struct iheap_node* next; - struct iheap_node* child; - - unsigned int degree; - int key; - const void* value; - struct iheap_node** ref; -}; - -struct iheap { - struct iheap_node* head; - /* We cache the minimum of the heap. - * This speeds up repeated peek operations. - */ - struct iheap_node* min; -}; - - - void iheap_init(struct iheap* heap) -{ - heap->head = NULL; - heap->min = NULL; -} - - void iheap_node_init_ref(struct iheap_node** _h, - int key, const void* value) -{ - struct iheap_node* h = *_h; - h->parent = NULL; - h->next = NULL; - h->child = NULL; - h->degree = NOT_IN_HEAP; - h->value = value; - h->ref = _h; - h->key = key; -} - - void iheap_node_init(struct iheap_node* h, int key, const void* value) -{ - h->parent = NULL; - h->next = NULL; - h->child = NULL; - h->degree = NOT_IN_HEAP; - h->value = value; - h->ref = NULL; - h->key = key; - //fprintf(stderr, "initializing head node with key %d and value 0x%x\n", key, value); -} - - const void* iheap_node_value(struct iheap_node* h) -{ - return h->value; -} - - int iheap_node_in_heap(struct iheap_node* h) -{ - return h->degree != NOT_IN_HEAP; -} - - int iheap_empty(struct iheap* heap) -{ - return heap->head == NULL && heap->min == NULL; -} - -/* make child a subtree of root */ - void __iheap_link(struct iheap_node* root, - struct iheap_node* child) -{ - child->parent = root; - child->next = root->child; - root->child = child; - root->degree++; -} - -/* merge root lists */ - struct iheap_node* __iheap_merge(struct iheap_node* a, - struct iheap_node* b) -{ - struct iheap_node* head = NULL; - struct iheap_node** pos = &head; - - while (a && b) { - if (a->degree < b->degree) { - *pos = a; - a = a->next; - } else { - *pos = b; - b = b->next; - } - pos = &(*pos)->next; - } - if (a) - *pos = a; - else - *pos = b; - return head; -} - -/* reverse a linked list of nodes. also clears parent pointer */ - struct iheap_node* __iheap_reverse(struct iheap_node* h) -{ - struct iheap_node* tail = NULL; - struct iheap_node* next; - - if (!h) - return h; - - h->parent = NULL; - while (h->next) { - next = h->next; - h->next = tail; - tail = h; - h = next; - h->parent = NULL; - } - h->next = tail; - return h; -} - - void __iheap_min(struct iheap* heap, - struct iheap_node** prev, - struct iheap_node** node) -{ - struct iheap_node *_prev, *cur; - *prev = NULL; - - if (!heap->head) { - *node = NULL; - return; - } - - *node = heap->head; - _prev = heap->head; - cur = heap->head->next; - while (cur) { - if (cur->key < (*node)->key) { - *node = cur; - *prev = _prev; - } - _prev = cur; - cur = cur->next; - } -} - - void __iheap_union(struct iheap* heap, struct iheap_node* h2) -{ - struct iheap_node* h1; - struct iheap_node *prev, *x, *next; - if (!h2) - return; - h1 = heap->head; - if (!h1) { - heap->head = h2; - return; - } - h1 = __iheap_merge(h1, h2); - prev = NULL; - x = h1; - next = x->next; - while (next) { - if (x->degree != next->degree || - (next->next && next->next->degree == x->degree)) { - /* nothing to do, advance */ - prev = x; - x = next; - } else if (x->key < next->key) { - /* x becomes the root of next */ - x->next = next->next; - __iheap_link(x, next); - } else { - /* next becomes the root of x */ - if (prev) - prev->next = next; - else - h1 = next; - __iheap_link(next, x); - x = next; - } - next = x->next; - } - heap->head = h1; -} - - struct iheap_node* __iheap_extract_min(struct iheap* heap) -{ - struct iheap_node *prev, *node; - __iheap_min(heap, &prev, &node); - if (!node) - return NULL; - if (prev) - prev->next = node->next; - else - heap->head = node->next; - __iheap_union(heap, __iheap_reverse(node->child)); - return node; -} - -/* insert (and reinitialize) a node into the heap */ - void iheap_insert(struct iheap* heap, struct iheap_node* node) -{ - struct iheap_node *min; - node->child = NULL; - node->parent = NULL; - node->next = NULL; - node->degree = 0; - if (heap->min && node->key < heap->min->key) { - /* swap min cache */ - min = heap->min; - min->child = NULL; - min->parent = NULL; - min->next = NULL; - min->degree = 0; - __iheap_union(heap, min); - heap->min = node; - } else - __iheap_union(heap, node); -} - - void __iheap_uncache_min(struct iheap* heap) -{ - struct iheap_node* min; - if (heap->min) { - min = heap->min; - heap->min = NULL; - iheap_insert(heap, min); - } -} - -/* merge addition into target */ - void iheap_union(struct iheap* target, struct iheap* addition) -{ - /* first insert any cached minima, if necessary */ - __iheap_uncache_min(target); - __iheap_uncache_min(addition); - __iheap_union(target, addition->head); - /* this is a destructive merge */ - addition->head = NULL; -} - - struct iheap_node* iheap_peek(struct iheap* heap) -{ - if (!heap->min) - heap->min = __iheap_extract_min(heap); - return heap->min; -} - - struct iheap_node* iheap_take(struct iheap* heap) -{ - struct iheap_node *node; - if (!heap->min) - heap->min = __iheap_extract_min(heap); - node = heap->min; - heap->min = NULL; - if (node) - node->degree = NOT_IN_HEAP; - return node; -} - - void iheap_decrease(struct iheap* heap, struct iheap_node* node, - int new_key) -{ - struct iheap_node *parent; - struct iheap_node** tmp_ref; - const void* tmp; - int tmp_key; - - /* node's priority was decreased, we need to update its position */ - if (!node->ref || new_key >= node->key) - return; - node->key = new_key; - if (heap->min != node) { - if (heap->min && node->key < heap->min->key) - __iheap_uncache_min(heap); - /* bubble up */ - parent = node->parent; - while (parent && node->key < parent->key) { - /* swap parent and node */ - tmp = parent->value; - tmp_key = parent->key; - parent->value = node->value; - parent->key = node->key; - node->value = tmp; - node->key = tmp_key; - /* swap references */ - if (parent->ref) - *(parent->ref) = node; - *(node->ref) = parent; - tmp_ref = parent->ref; - parent->ref = node->ref; - node->ref = tmp_ref; - /* step up */ - node = parent; - parent = node->parent; - } - } -} - - void iheap_delete(struct iheap* heap, struct iheap_node* node) -{ - struct iheap_node *parent, *prev, *pos; - struct iheap_node** tmp_ref; - const void* tmp; - int tmp_key; - - if (!node->ref) /* can only delete if we have a reference */ - return; - if (heap->min != node) { - /* bubble up */ - parent = node->parent; - while (parent) { - /* swap parent and node */ - tmp = parent->value; - tmp_key = parent->key; - parent->value = node->value; - parent->key = node->key; - node->value = tmp; - node->key = tmp_key; - /* swap references */ - if (parent->ref) - *(parent->ref) = node; - *(node->ref) = parent; - tmp_ref = parent->ref; - parent->ref = node->ref; - node->ref = tmp_ref; - /* step up */ - node = parent; - parent = node->parent; - } - /* now delete: - * first find prev */ - prev = NULL; - pos = heap->head; - while (pos != node) { - prev = pos; - pos = pos->next; - } - /* we have prev, now remove node */ - if (prev) - prev->next = node->next; - else - heap->head = node->next; - __iheap_union(heap, __iheap_reverse(node->child)); - } else - heap->min = NULL; - node->degree = NOT_IN_HEAP; -} - -#endif /* HEAP_H */ diff --git a/lib_graphd/inc/binomial-heap/iheap.h.noinline b/lib_graphd/inc/binomial-heap/iheap.h.noinline deleted file mode 100644 index a697f4e..0000000 --- a/lib_graphd/inc/binomial-heap/iheap.h.noinline +++ /dev/null @@ -1,385 +0,0 @@ -/* iheap.h -- Binomial Heaps with integer priorities - * - * Copyright (c) 2008, Bjoern B. Brandenburg - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the University of North Carolina nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY COPYRIGHT OWNER AND CONTRIBUTERS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTERS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef IHEAP_H -#define IHEAP_H - -#define NOT_IN_HEAP UINT_MAX - -struct iheap_node { - struct iheap_node* parent; - struct iheap_node* next; - struct iheap_node* child; - - unsigned int degree; - int key; - const void* value; - struct iheap_node** ref; -}; - -struct iheap { - struct iheap_node* head; - /* We cache the minimum of the heap. - * This speeds up repeated peek operations. - */ - struct iheap_node* min; -}; - - - void iheap_init(struct iheap* heap) -{ - heap->head = NULL; - heap->min = NULL; -} - - void iheap_node_init_ref(struct iheap_node** _h, - int key, const void* value) -{ - struct iheap_node* h = *_h; - h->parent = NULL; - h->next = NULL; - h->child = NULL; - h->degree = NOT_IN_HEAP; - h->value = value; - h->ref = _h; - h->key = key; -} - - void iheap_node_init(struct iheap_node* h, int key, const void* value) -{ - h->parent = NULL; - h->next = NULL; - h->child = NULL; - h->degree = NOT_IN_HEAP; - h->value = value; - h->ref = NULL; - h->key = key; - //fprintf(stderr, "initializing head node with key %d and value 0x%x\n", key, value); -} - - const void* iheap_node_value(struct iheap_node* h) -{ - return h->value; -} - - int iheap_node_in_heap(struct iheap_node* h) -{ - return h->degree != NOT_IN_HEAP; -} - - int iheap_empty(struct iheap* heap) -{ - return heap->head == NULL && heap->min == NULL; -} - -/* make child a subtree of root */ - void __iheap_link(struct iheap_node* root, - struct iheap_node* child) -{ - child->parent = root; - child->next = root->child; - root->child = child; - root->degree++; -} - -/* merge root lists */ - struct iheap_node* __iheap_merge(struct iheap_node* a, - struct iheap_node* b) -{ - struct iheap_node* head = NULL; - struct iheap_node** pos = &head; - - while (a && b) { - if (a->degree < b->degree) { - *pos = a; - a = a->next; - } else { - *pos = b; - b = b->next; - } - pos = &(*pos)->next; - } - if (a) - *pos = a; - else - *pos = b; - return head; -} - -/* reverse a linked list of nodes. also clears parent pointer */ - struct iheap_node* __iheap_reverse(struct iheap_node* h) -{ - struct iheap_node* tail = NULL; - struct iheap_node* next; - - if (!h) - return h; - - h->parent = NULL; - while (h->next) { - next = h->next; - h->next = tail; - tail = h; - h = next; - h->parent = NULL; - } - h->next = tail; - return h; -} - - void __iheap_min(struct iheap* heap, - struct iheap_node** prev, - struct iheap_node** node) -{ - struct iheap_node *_prev, *cur; - *prev = NULL; - - if (!heap->head) { - *node = NULL; - return; - } - - *node = heap->head; - _prev = heap->head; - cur = heap->head->next; - while (cur) { - if (cur->key < (*node)->key) { - *node = cur; - *prev = _prev; - } - _prev = cur; - cur = cur->next; - } -} - - void __iheap_union(struct iheap* heap, struct iheap_node* h2) -{ - struct iheap_node* h1; - struct iheap_node *prev, *x, *next; - if (!h2) - return; - h1 = heap->head; - if (!h1) { - heap->head = h2; - return; - } - h1 = __iheap_merge(h1, h2); - prev = NULL; - x = h1; - next = x->next; - while (next) { - if (x->degree != next->degree || - (next->next && next->next->degree == x->degree)) { - /* nothing to do, advance */ - prev = x; - x = next; - } else if (x->key < next->key) { - /* x becomes the root of next */ - x->next = next->next; - __iheap_link(x, next); - } else { - /* next becomes the root of x */ - if (prev) - prev->next = next; - else - h1 = next; - __iheap_link(next, x); - x = next; - } - next = x->next; - } - heap->head = h1; -} - - struct iheap_node* __iheap_extract_min(struct iheap* heap) -{ - struct iheap_node *prev, *node; - __iheap_min(heap, &prev, &node); - if (!node) - return NULL; - if (prev) - prev->next = node->next; - else - heap->head = node->next; - __iheap_union(heap, __iheap_reverse(node->child)); - return node; -} - -/* insert (and reinitialize) a node into the heap */ - void iheap_insert(struct iheap* heap, struct iheap_node* node) -{ - struct iheap_node *min; - node->child = NULL; - node->parent = NULL; - node->next = NULL; - node->degree = 0; - if (heap->min && node->key < heap->min->key) { - /* swap min cache */ - min = heap->min; - min->child = NULL; - min->parent = NULL; - min->next = NULL; - min->degree = 0; - __iheap_union(heap, min); - heap->min = node; - } else - __iheap_union(heap, node); -} - - void __iheap_uncache_min(struct iheap* heap) -{ - struct iheap_node* min; - if (heap->min) { - min = heap->min; - heap->min = NULL; - iheap_insert(heap, min); - } -} - -/* merge addition into target */ - void iheap_union(struct iheap* target, struct iheap* addition) -{ - /* first insert any cached minima, if necessary */ - __iheap_uncache_min(target); - __iheap_uncache_min(addition); - __iheap_union(target, addition->head); - /* this is a destructive merge */ - addition->head = NULL; -} - - struct iheap_node* iheap_peek(struct iheap* heap) -{ - if (!heap->min) - heap->min = __iheap_extract_min(heap); - return heap->min; -} - - struct iheap_node* iheap_take(struct iheap* heap) -{ - struct iheap_node *node; - if (!heap->min) - heap->min = __iheap_extract_min(heap); - node = heap->min; - heap->min = NULL; - if (node) - node->degree = NOT_IN_HEAP; - return node; -} - - void iheap_decrease(struct iheap* heap, struct iheap_node* node, - int new_key) -{ - struct iheap_node *parent; - struct iheap_node** tmp_ref; - const void* tmp; - int tmp_key; - - /* node's priority was decreased, we need to update its position */ - if (!node->ref || new_key >= node->key) - return; - node->key = new_key; - if (heap->min != node) { - if (heap->min && node->key < heap->min->key) - __iheap_uncache_min(heap); - /* bubble up */ - parent = node->parent; - while (parent && node->key < parent->key) { - /* swap parent and node */ - tmp = parent->value; - tmp_key = parent->key; - parent->value = node->value; - parent->key = node->key; - node->value = tmp; - node->key = tmp_key; - /* swap references */ - if (parent->ref) - *(parent->ref) = node; - *(node->ref) = parent; - tmp_ref = parent->ref; - parent->ref = node->ref; - node->ref = tmp_ref; - /* step up */ - node = parent; - parent = node->parent; - } - } -} - - void iheap_delete(struct iheap* heap, struct iheap_node* node) -{ - struct iheap_node *parent, *prev, *pos; - struct iheap_node** tmp_ref; - const void* tmp; - int tmp_key; - - if (!node->ref) /* can only delete if we have a reference */ - return; - if (heap->min != node) { - /* bubble up */ - parent = node->parent; - while (parent) { - /* swap parent and node */ - tmp = parent->value; - tmp_key = parent->key; - parent->value = node->value; - parent->key = node->key; - node->value = tmp; - node->key = tmp_key; - /* swap references */ - if (parent->ref) - *(parent->ref) = node; - *(node->ref) = parent; - tmp_ref = parent->ref; - parent->ref = node->ref; - node->ref = tmp_ref; - /* step up */ - node = parent; - parent = node->parent; - } - /* now delete: - * first find prev */ - prev = NULL; - pos = heap->head; - while (pos != node) { - prev = pos; - pos = pos->next; - } - /* we have prev, now remove node */ - if (prev) - prev->next = node->next; - else - heap->head = node->next; - __iheap_union(heap, __iheap_reverse(node->child)); - } else - heap->min = NULL; - node->degree = NOT_IN_HEAP; -} - -#endif /* HEAP_H */ diff --git a/lib_graphd/inc/binomial-heap/iheap.h.orig b/lib_graphd/inc/binomial-heap/iheap.h.orig deleted file mode 100644 index ffc19ab..0000000 --- a/lib_graphd/inc/binomial-heap/iheap.h.orig +++ /dev/null @@ -1,385 +0,0 @@ -/* iheap.h -- Binomial Heaps with integer priorities - * - * Copyright (c) 2008, Bjoern B. Brandenburg - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the University of North Carolina nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY COPYRIGHT OWNER AND CONTRIBUTERS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTERS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef IHEAP_H -#define IHEAP_H - -#define NOT_IN_HEAP UINT_MAX - -struct iheap_node { - struct iheap_node* parent; - struct iheap_node* next; - struct iheap_node* child; - - unsigned int degree; - int key; - const void* value; - struct iheap_node** ref; -}; - -struct iheap { - struct iheap_node* head; - /* We cache the minimum of the heap. - * This speeds up repeated peek operations. - */ - struct iheap_node* min; -}; - - -static inline void iheap_init(struct iheap* heap) -{ - heap->head = NULL; - heap->min = NULL; -} - -static inline void iheap_node_init_ref(struct iheap_node** _h, - int key, const void* value) -{ - struct iheap_node* h = *_h; - h->parent = NULL; - h->next = NULL; - h->child = NULL; - h->degree = NOT_IN_HEAP; - h->value = value; - h->ref = _h; - h->key = key; -} - -static inline void iheap_node_init(struct iheap_node* h, int key, const void* value) -{ - h->parent = NULL; - h->next = NULL; - h->child = NULL; - h->degree = NOT_IN_HEAP; - h->value = value; - h->ref = NULL; - h->key = key; - //fprintf(stderr, "initializing head node with key %d and value 0x%x\n", key, value); -} - -static inline const void* iheap_node_value(struct iheap_node* h) -{ - return h->value; -} - -static inline int iheap_node_in_heap(struct iheap_node* h) -{ - return h->degree != NOT_IN_HEAP; -} - -static inline int iheap_empty(struct iheap* heap) -{ - return heap->head == NULL && heap->min == NULL; -} - -/* make child a subtree of root */ -static inline void __iheap_link(struct iheap_node* root, - struct iheap_node* child) -{ - child->parent = root; - child->next = root->child; - root->child = child; - root->degree++; -} - -/* merge root lists */ -static inline struct iheap_node* __iheap_merge(struct iheap_node* a, - struct iheap_node* b) -{ - struct iheap_node* head = NULL; - struct iheap_node** pos = &head; - - while (a && b) { - if (a->degree < b->degree) { - *pos = a; - a = a->next; - } else { - *pos = b; - b = b->next; - } - pos = &(*pos)->next; - } - if (a) - *pos = a; - else - *pos = b; - return head; -} - -/* reverse a linked list of nodes. also clears parent pointer */ -static inline struct iheap_node* __iheap_reverse(struct iheap_node* h) -{ - struct iheap_node* tail = NULL; - struct iheap_node* next; - - if (!h) - return h; - - h->parent = NULL; - while (h->next) { - next = h->next; - h->next = tail; - tail = h; - h = next; - h->parent = NULL; - } - h->next = tail; - return h; -} - -static inline void __iheap_min(struct iheap* heap, - struct iheap_node** prev, - struct iheap_node** node) -{ - struct iheap_node *_prev, *cur; - *prev = NULL; - - if (!heap->head) { - *node = NULL; - return; - } - - *node = heap->head; - _prev = heap->head; - cur = heap->head->next; - while (cur) { - if (cur->key < (*node)->key) { - *node = cur; - *prev = _prev; - } - _prev = cur; - cur = cur->next; - } -} - -static inline void __iheap_union(struct iheap* heap, struct iheap_node* h2) -{ - struct iheap_node* h1; - struct iheap_node *prev, *x, *next; - if (!h2) - return; - h1 = heap->head; - if (!h1) { - heap->head = h2; - return; - } - h1 = __iheap_merge(h1, h2); - prev = NULL; - x = h1; - next = x->next; - while (next) { - if (x->degree != next->degree || - (next->next && next->next->degree == x->degree)) { - /* nothing to do, advance */ - prev = x; - x = next; - } else if (x->key < next->key) { - /* x becomes the root of next */ - x->next = next->next; - __iheap_link(x, next); - } else { - /* next becomes the root of x */ - if (prev) - prev->next = next; - else - h1 = next; - __iheap_link(next, x); - x = next; - } - next = x->next; - } - heap->head = h1; -} - -static inline struct iheap_node* __iheap_extract_min(struct iheap* heap) -{ - struct iheap_node *prev, *node; - __iheap_min(heap, &prev, &node); - if (!node) - return NULL; - if (prev) - prev->next = node->next; - else - heap->head = node->next; - __iheap_union(heap, __iheap_reverse(node->child)); - return node; -} - -/* insert (and reinitialize) a node into the heap */ -static inline void iheap_insert(struct iheap* heap, struct iheap_node* node) -{ - struct iheap_node *min; - node->child = NULL; - node->parent = NULL; - node->next = NULL; - node->degree = 0; - if (heap->min && node->key < heap->min->key) { - /* swap min cache */ - min = heap->min; - min->child = NULL; - min->parent = NULL; - min->next = NULL; - min->degree = 0; - __iheap_union(heap, min); - heap->min = node; - } else - __iheap_union(heap, node); -} - -static inline void __iheap_uncache_min(struct iheap* heap) -{ - struct iheap_node* min; - if (heap->min) { - min = heap->min; - heap->min = NULL; - iheap_insert(heap, min); - } -} - -/* merge addition into target */ -static inline void iheap_union(struct iheap* target, struct iheap* addition) -{ - /* first insert any cached minima, if necessary */ - __iheap_uncache_min(target); - __iheap_uncache_min(addition); - __iheap_union(target, addition->head); - /* this is a destructive merge */ - addition->head = NULL; -} - -static inline struct iheap_node* iheap_peek(struct iheap* heap) -{ - if (!heap->min) - heap->min = __iheap_extract_min(heap); - return heap->min; -} - -static inline struct iheap_node* iheap_take(struct iheap* heap) -{ - struct iheap_node *node; - if (!heap->min) - heap->min = __iheap_extract_min(heap); - node = heap->min; - heap->min = NULL; - if (node) - node->degree = NOT_IN_HEAP; - return node; -} - -static inline void iheap_decrease(struct iheap* heap, struct iheap_node* node, - int new_key) -{ - struct iheap_node *parent; - struct iheap_node** tmp_ref; - const void* tmp; - int tmp_key; - - /* node's priority was decreased, we need to update its position */ - if (!node->ref || new_key >= node->key) - return; - node->key = new_key; - if (heap->min != node) { - if (heap->min && node->key < heap->min->key) - __iheap_uncache_min(heap); - /* bubble up */ - parent = node->parent; - while (parent && node->key < parent->key) { - /* swap parent and node */ - tmp = parent->value; - tmp_key = parent->key; - parent->value = node->value; - parent->key = node->key; - node->value = tmp; - node->key = tmp_key; - /* swap references */ - if (parent->ref) - *(parent->ref) = node; - *(node->ref) = parent; - tmp_ref = parent->ref; - parent->ref = node->ref; - node->ref = tmp_ref; - /* step up */ - node = parent; - parent = node->parent; - } - } -} - -static inline void iheap_delete(struct iheap* heap, struct iheap_node* node) -{ - struct iheap_node *parent, *prev, *pos; - struct iheap_node** tmp_ref; - const void* tmp; - int tmp_key; - - if (!node->ref) /* can only delete if we have a reference */ - return; - if (heap->min != node) { - /* bubble up */ - parent = node->parent; - while (parent) { - /* swap parent and node */ - tmp = parent->value; - tmp_key = parent->key; - parent->value = node->value; - parent->key = node->key; - node->value = tmp; - node->key = tmp_key; - /* swap references */ - if (parent->ref) - *(parent->ref) = node; - *(node->ref) = parent; - tmp_ref = parent->ref; - parent->ref = node->ref; - node->ref = tmp_ref; - /* step up */ - node = parent; - parent = node->parent; - } - /* now delete: - * first find prev */ - prev = NULL; - pos = heap->head; - while (pos != node) { - prev = pos; - pos = pos->next; - } - /* we have prev, now remove node */ - if (prev) - prev->next = node->next; - else - heap->head = node->next; - __iheap_union(heap, __iheap_reverse(node->child)); - } else - heap->min = NULL; - node->degree = NOT_IN_HEAP; -} - -#endif /* HEAP_H */ diff --git a/lib_graphd/inc/binomial-heap/ihtest b/lib_graphd/inc/binomial-heap/ihtest deleted file mode 100755 index 01f8fca068fd44745c15105e8c614289f1f77936..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13145 zcmcIq4RBOdmcHo_2oXs55rbx=9m9f-G(RE(>WnXh#*PMvNCsy_J5Bl}Y3X!lx?f{Z zs9_dx?P+i`yY7^Z>`sQ-a;bHGNzwO1$>R}DQ-YgnO5 z`87ax6l)*L`)b=XF0_V(D1N45N8u54jO~uGozOlGOsMpa`bK|s+`l@X1&(-&h+3-pfhg?}-1 z&f4d8lCAuq`Ue-9Zq!C;Az%Jd5d7u%n@InUE`l$<2!6{&a1{=Bb|(|zv=d1=;jlv5 z+9^vbRZqrAtDaOW;dH3(NIafwhc1a(w>uI`sE(9vt6Q6!)-;Bf2bKqJKr56jWx^!+p^Y0Q*A)h;{`L~FtP|x*)U-o`e_O*LM*|$P_-yUt*+%!0_be5$; zgD+c}3~sKmRQ@?Ae%#kbF@|y#5jY6#A8>r*LpsDhZ)pu>-?@_%_k5>so*#L?{rMwU z;xPLO*wBwh`iXn_i}KLkk+RV0GwJ${>iHOy(B6TvP`1K`()gTz&`P23CAgLf8s#<#0zIu`s^4ZMWp=|3J2=k$w3T2@)u?d^&$wl=+tCn)B;T#-fTl`$l zqrQmhxz@L{Ep={NW7*8dXbbI37?Xjmi!?w^O#_40BI!=9_2Z%jOaPX@(4;|V>@ss$ zT1m{5V>Eq6Ds=Wd>eCKUJz<# zI5Zd>)nOha)8N?19Z<{XT53UtVYm83dLFxjK6yi4tV*cnM=oQ*un`Qi0F;`ic|&?* zp}o8F%9#Q(tTMke+;or6kxPpGjCvxJ=*UH8GW7Bz_s}oTm67W;V*;WXf#7tvDFuj^ zGK2sStmfSbX8M5q4wTw>+NSK7DTgdkj+9Z>qeLAzBT@7i0c8ghjFUu@l$u9dFw`j< z8@UC*Sgxf`YvxqWs#|?x_gurtP$GZS2XaH9lMi&wI6(HsROUEGx%a)LSUhMlgXO+^ zNLBA!f$74&VLEJbPM*%d=@6Wro2@la$M}Y_{}Rd$=HL4g>w~lhgL&>IM7m)#ZW=y! z!t{UCOpP%;H8NMbv0-5^62_>E8kJcp zfdEHVnVB;KIDApES}I4NslA$<>AJRf{X8%El5XhyRqwyv>&3SH`y+gkJ|i6Ocw}(A{i26OmxON0JIQIUYEq1_Oqeen_~ zvukK}nS`3_O(95HhK}C1Jl7Z3`6^kJ+1Ar=F@!N$gfXe!ccWRJLl}&kf~Tt=SuA|( zXuGoFlh_Q7H7MgVx)XLwVqiQpBrIR3D)AIx?xxyG||S_!Q>C0JQPP3C@_LodQ5< zM9Ob72vn$vA;}Axbn`;PVe$eklMl|zfXVle$pEBoUIucK7xLuh#W1$blBB~UbjL7^8YYh(m`Xx*9T~{r z_Hp+arS~ZK(>u}`v}yJzL6FHB)1cX-9vnkcS=yr@(F-Z}dkg{1wo`?b8XVx+?;RMw z>|HM{MWFe~pO7co9w{c>{BW)k+?d%{|KwBJ`-;~5XPRKZ6Bnu9n8-&^#Q6+H}&D;-#}9@ z4&Z@<&;*Suw2#w1`(l5cLGLo?z;SvYc+r2QLDy)s^%(RAUTkCVHCp=zTaS{H7ke0d z!GHrM4&C`@(0S+$0YaD>I&7dL+TR{F{jo9a*I*xm@q#}ww#hixO2z`+YxdhC)UR)S zq{ZY$#J3o6KZ&Pl@p|gY@Nskt(?nlspVMB~Q*VZkx1;ln{{r|+&*P9FfB1Kpi$UXd zFn=xS%XJ=pf2OBLaO~Jg=<2DZyLt?sRDKIg^^AdHj_NwL!F(D<*xR1cTJ&Vn*Y^=U z&3K<@vhn&e&Dm)EaOmLTn`i)JY|eh(oc(ld_JfA;IcGzAPvV(tB=v46x3wP2 zBVJ$AoQu}iHlyZm&N=mqnsdAAm*O#Nl@1Q^xzBT$PCw3`KgR2d@|#{kdzazw^yv8bFzEZB zbSUzD467gXIH(1B8ng}c3(!5F4Vd!%p#K3n02;;`90skx^rvaC1sjwf^em_a`uEtK z+dw}8-2?jF&tMPw1n2oK>_ z6t(}lZlC7u3y=@vjtImp^{D+8z!~6KLhm?G@zCV(3~TR{KlMFQesGfSt{M7?jV(|!!px+FUuMJe<$)@q_m+99+w?VA7c75rcW|0wfj0=^0A1=S?0ra%uC*u zF)w+(h532hK#+NvH|v>~v+x$?C$oMl^Yq?SCW|Ugn?Z?_~SKEbnIi8RlcmA7}nS=3ihw!Tdin zpJHC(vrFvnV_y2JuPwk{V|%>JBjzuKs)mCVaNW-%XS`6lKa=C?5a1LoV9$G)TYX5mkj$X{iC zKkMf?ArCVz^YL-!f6fX2TjsC5&Sdmy=5K9mywSf1Zx^reuL!INtn@Emx@`H<>zCf( zU$n`N`a==N;EPvWqf{Whv)hSm19eh{c1aDd=j>FE3M7(_9cWn7wAhJsGS`{N1h!>j zcm*1ZssM3ak#v^|M0Y0O&rm02Bs=U>I+jcnF=5D3c057`T3I#50f90~(;ALT7F{{*`l720FPzRqWXE4&ByYp(Dk^I4E( zsCeyf_E}nVGdraF32!O2Ukf2_k&@DWo6iD5*L_Xg?+IjIm-S+#N^L-e)`-~e@mb*L zzCaUo#1Q>W0QFt$(~VdjsL+{@`J@_d`yFu4CT#HHaVDA1S9|FZUxy*k1Z6?U(j{Ux~fk-wd$5tbekn zy|mQ+5nvRTTxaEeZWRx-v=0?s7#3D#QS;ijOtQ4Bg%#U0SNIWoxo>zBBCoxC2XmAa z?~(yv7h)$Ke_moQ_n(!#(U+L(T#GHye*97UlK)!1&eXE~($i?`_(^6~4PE%~z@YAauR<^k$t( zKM(xZ+5ZN*UVD12PUR@um$p~RzYblRdlJ9g&&u~d@|};&PqCM{&cfE)zI?Y4x*P%& z(KlRy7yREL@Y>7sL<`$nV#rkNguYv1-_Oq@{cK-4;ru23M!}OW>3=^CI;r$usfqi% zWw=88!heDa#lKVlrec3x2~N6Hgwp+zw5>B(@-eg~y3T&eGN0%7;Sc$N-eWNw;Z#hNlvn~*pBVxHudWGePM6Q3u_$2o^wivH) zpI?jd$x5z6#rPB@*Oy|vQpt6r7@w--dQgm4xzDl1_$BW1criXr$-Z2SPj|mNEXHRj z*++}*Z>ulKsppEXS8)vQHJ`v$5~Ac_Cdd$0?ocD_&taP6cGY zD8}cy-)|M;m$~N!#dxifbz6+j!#Zs9Lb_hAzkVx*%{rK_&hqt7q_n;!sSn-r6~XIJ zDVrb<*J}L2Jgn0Ag?R`9_bEI@S6HYO%H61zsY3j+Zti3J2=`0YV=r*>(^KN-V)5_O zerBo1O2+G_8lR~iuC-7rlwY7)Ho-VP1)SO)nq?J~QF|GG6XornfRp~C9OqSR^#Yv(SMTh^^E_Taebx=+1-rKuQK}kSwG46Uo-w1u)=MqpHa&G^%dZ#A%blkrPx zER8fV{-40h@K!;t!wf4rtEDea50uQe>H6YxA?^oWHo^XI4RF7@aJ{bpK9lgeHr?bN z-JZhrVB+swTQojh(btev!0OV*xZKAwtU7`Fh4IiG7r}p`{dg3)dPw6J?$3uWqW|ng z@Hc?ZRE7O~68nE!QeFRU!~r?h#$H?t(hR7Q*qs%>8n=$*%o^+WUj_%EBffu zTdoE^3-i^^w~UUyT&KD{9gg=%^Np`o15<3 zj4zzS;k8BFZH*pLG#T!UC$~l7VSQK;j%0cj4kCKuwqr*FE3aSiZAF4`EZR%lYJ31q z=N-{ZclSxXD#U3R1=tPfdCHIawZm){Y=TSNxz?jDCCGA{6nb-T-S+o?|5O4$lWQmM$!u#MNaMS%XYU4_?ve?!Cirbb04 zOy&!Ayw*lz>E-;9yJdO5W9LuZ+tZn_KI3AOlCR~%x9tdTvO8mG9KtomBWZeBPT$R! z_|hKCH}oZv(hurO#7!H~ZZwt%XVP|5IWZ@0>rd`W)WV)lg~QQwGTeo?+0f;=F7r-* my-!`zvuj&~GKI6YqI4`%CWW>>ii<~f;`KMa|EF1@t^NnlCtaWb diff --git a/lib_graphd/inc/binomial-heap/ihtest.c b/lib_graphd/inc/binomial-heap/ihtest.c deleted file mode 100644 index eda1bf9..0000000 --- a/lib_graphd/inc/binomial-heap/ihtest.c +++ /dev/null @@ -1,116 +0,0 @@ -#include -#include -#include - -#include "iheap.h" - -struct token { - int prio; - const char* str; -}; - -#define LENGTH(a) (sizeof(a) / sizeof(a[0])) - -struct token tokens1[] = { - {24, "all"}, {16, "star"}, {9, "true.\nSinging"}, {7, "clear"}, - {25, "praises"}, {13, "to"}, {5, "Heel"}, {6, "voices\nRinging"}, - {26, "thine."}, {21, "shine\nCarolina"}, {117, "Rah,"}, {102, "Tar"}, - {108, "bred\nAnd"}, {125, "Rah!"}, {107, "Heel"}, {118, "Rah,"}, - {111, "die\nI'm"}, {115, "dead.\nSo"}, {120, "Rah,"}, - {121, "Car'lina-lina\nRah,"}, {109, "when"}, {105, "a"}, - {123, "Car'lina-lina\nRah!"}, {110, "I"}, {114, "Heel"}, {101, "a"}, - {106, "Tar"}, {18, "all\nClear"}, {14, "the"} -}; - -struct token tokens2[] = { - {113, "Tar"}, {124, "Rah!"}, {112, "a"}, {103, "Heel"}, - {104, "born\nI'm"}, {122, "Rah,"}, {119, "Car'lina-lina\nRah,"}, - {2, "sound"}, {20, "radiance"}, {12, "N-C-U.\nHail"}, - {10, "Carolina's"}, {3, "of"}, {17, "of"}, {23, "gem.\nReceive"}, - {19, "its"}, {0, "\nHark"}, {22, "priceless"}, {4, "Tar"}, - {1, "the"}, {8, "and"}, {15, "brightest"}, - {11, "praises.\nShouting"}, {100, "\nI'm"}, {116, "it's"} -}; - -#define line "\n===================================" - -struct token layout[] = { - {90, line}, {-2, line}, {200, line}, {201, "\n\n"} -}; - - -struct token title[] = { - {1000, "\nUNC Alma Mater:"}, {120, "\nUNC Fight Song:"} -}; - -struct token bad[] = { - {666, "Dook"}, {666666, "Blue Devils"} -}; - - -static void add_token(struct iheap* heap, struct token* tok) -{ - struct iheap_node* hn = malloc(sizeof(struct iheap_node)); - iheap_node_init(hn, tok->prio, tok->str); - iheap_insert(heap, hn); -} - -static void add_token_ref(struct iheap* heap, struct token* tok, - struct iheap_node** hn) -{ - *hn = malloc(sizeof(struct iheap_node)); - iheap_node_init_ref(hn, tok->prio, tok->str); - iheap_insert(heap, *hn); -} - -static void add_tokens(struct iheap* heap, struct token* tok, int len) -{ - int i; - for (i = 0; i < len; i++) - add_token(heap, tok + i); -} - -int main(int argc __attribute__((unused)), char** argv __attribute__((unused))) -{ - struct iheap h1, h2, h3; - struct iheap_node* hn; - struct iheap_node *t1, *t2, *b1, *b2; - const char *str; - - iheap_init(&h1); - iheap_init(&h2); - iheap_init(&h3); - - add_tokens(&h1, tokens1, LENGTH(tokens1)); - add_tokens(&h2, tokens2, LENGTH(tokens2)); - add_tokens(&h3, layout, LENGTH(layout)); - - add_token_ref(&h3, title, &t1); - add_token_ref(&h2, title + 1, &t2); - - iheap_union(&h2, &h3); - iheap_union(&h1, &h2); - - add_token_ref(&h3, bad, &b1); - add_token_ref(&h3, bad + 1, &b2); - - iheap_union(&h1, &h3); - - iheap_delete(&h1, b1); - free(b1); - iheap_delete(&h1, b2); - free(b2); - - iheap_decrease(&h1, t1, -1); - iheap_decrease(&h1, t2, 99); - - printf("ihtest:\n"); - while (!iheap_empty(&h1)) { - hn = iheap_take(&h1); - str = iheap_node_value(hn); - printf("%s ", str); - free(hn); - } - return 0; -} - From db10b8876569ff794563f9f8b7b3af607ff6b85b Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Wed, 17 Jul 2013 15:28:35 -0400 Subject: [PATCH 27/73] Clean up build errors related to BOOST and PETSC merge --- lib_graphd/src/GraphProperties.cpp | 4 +++- util/src/graph_stats.cpp | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/lib_graphd/src/GraphProperties.cpp b/lib_graphd/src/GraphProperties.cpp index d365f79..a588508 100644 --- a/lib_graphd/src/GraphProperties.cpp +++ b/lib_graphd/src/GraphProperties.cpp @@ -24,7 +24,6 @@ #include #include #include -#include "binomial-heap/iheap.h" #include #ifdef HAS_SLEPC @@ -1017,6 +1016,7 @@ namespace Graph { coeff = (n1 - n2) / (de - n2); } // deg_assortativity + #ifdef HAS_PETSC /** * Built in self tester for the eigen solver. Looks at Ax - yx and looks for the * largest magnitude of error. @@ -1095,4 +1095,6 @@ namespace Graph { #endif // ifndef HAS_SLEPC } // eigen_spectrum + + #endif // ifdef HAS_PETSC } diff --git a/util/src/graph_stats.cpp b/util/src/graph_stats.cpp index 38cd40c..94d0ba5 100644 --- a/util/src/graph_stats.cpp +++ b/util/src/graph_stats.cpp @@ -240,6 +240,8 @@ int main(int argc, char **argv){ ORB_read(t2); print_time("Time(shortest_paths_dijkstra)", t1, t2); } + + #ifdef HAS_BOOST if(req_methods["shortest_paths_boost"] == true){ cout << "Creating BOOST representation of g" << endl; ORB_read(t1); @@ -252,6 +254,7 @@ int main(int argc, char **argv){ ORB_read(t2); print_time("Time(shortest_paths_dijkstra_boost)", t1, t2); } + #endif if(req_methods["eccentricity"] == true){ cout << "Calculating eccentricities" << endl; ORB_read(t1); @@ -281,6 +284,7 @@ int main(int argc, char **argv){ print_time("Time(avg_path_length)", t1, t2); outfile << "avg_path_length " << avg_path_length << endl; } + #ifdef HAS_PETSC if(req_methods["eigen_spectrum"] == true){ //If petsc/slepc are present, initalize those. //If MPI support is added in the future, init MPI before Petsc. Petsc will do it's own MPI @@ -305,6 +309,7 @@ int main(int argc, char **argv){ } outfile << "\n"; } + #endif // ifdef HAS_PETSC outfile.close(); From c4ac183973dc94bf38dad1c3b7e6eed259b2baa2 Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Thu, 18 Jul 2013 12:18:03 -0400 Subject: [PATCH 28/73] - Add doxygen comments to k-cores code - Add function to Util for writing out k-core array - Update graph-stats for degeneracy and k-core output --- lib_graphd/inc/GraphUtil.h | 5 +++-- lib_graphd/inc/Util.h | 9 +++++++++ lib_graphd/src/GraphUtil.cpp | 5 ++++- lib_graphd/src/Util.cpp | 28 ++++++++++++++++++++++++++++ util/src/graph_stats.cpp | 17 ++++++++++++++++- 5 files changed, 60 insertions(+), 4 deletions(-) diff --git a/lib_graphd/inc/GraphUtil.h b/lib_graphd/inc/GraphUtil.h index 6420994..8853117 100644 --- a/lib_graphd/inc/GraphUtil.h +++ b/lib_graphd/inc/GraphUtil.h @@ -88,8 +88,9 @@ namespace Graph { //Find the eccentricity of each vertex and store it in ecc. void find_ecc(Graph *g, vector *ecc); - //Find the k-core number of each vertex and store it in kcore. - //Return degeneracy. + /** + * \brief Find the k-core number of each vertex and store it in kcore. + */ int find_kcore(Graph *g, vector *kcore); //Calculate the maximum distance between nodes within a subset of vertices diff --git a/lib_graphd/inc/Util.h b/lib_graphd/inc/Util.h index da654ba..67dbbdc 100644 --- a/lib_graphd/inc/Util.h +++ b/lib_graphd/inc/Util.h @@ -92,7 +92,16 @@ const char *eo_name(int eo_id); std::string str_to_up(std::string s); void split(const std::string& s, char sep, vector& v); // used in metisgraph reader +/** + * \brief write a degree distribution out to a file + */ void write_degree_distribution(string filename, const vector &dist); + +/** + * \brief write a k_core list out to a file + */ +void write_kcores(string filename, const vector &kcores); + int_int mylog2(int x); #endif /* UTIL_H_ */ diff --git a/lib_graphd/src/GraphUtil.cpp b/lib_graphd/src/GraphUtil.cpp index a165280..08f0f9f 100644 --- a/lib_graphd/src/GraphUtil.cpp +++ b/lib_graphd/src/GraphUtil.cpp @@ -852,6 +852,9 @@ namespace Graph { * Return value is degeneracy (maximum non-empty k-core). * Uses algorithm of Batagelj and Zaversnik (2003) * Implemented by Timothy Goodrich and Matthew Farrell (2013) + * \param[in] g input graph + * \param[in] kcore pointer to vector to store kcores in + * \reutrn the degneracy of the graph */ int GraphUtil::find_kcore(Graph *g, vector *kcore){ int n = g->num_nodes; @@ -906,7 +909,7 @@ namespace Graph { } } return k; - } // find_degen + } // find_kcore } using namespace std; /** diff --git a/lib_graphd/src/Util.cpp b/lib_graphd/src/Util.cpp index 2db0a22..3ee902e 100644 --- a/lib_graphd/src/Util.cpp +++ b/lib_graphd/src/Util.cpp @@ -841,6 +841,11 @@ void split(const std::string& s, char sep, vector& v){ } } // split +/** + * Write a degree distribution out to file. + * \param[in] filename filename to write output to + * \param[in] dist a vector, indexed on degree + */ void write_degree_distribution(string filename, const vector &dist){ ofstream outfile; @@ -859,3 +864,26 @@ void write_degree_distribution(string filename, const vector &dist){ outfile.close(); } // write_degree_distribution +/** + * Write a kcore list out to file. + * \param[in] filename filename to write output to + * \param[in] kcores a vector, indexed on vertex number + */ +void write_kcores(string filename, const vector &kcores){ + ofstream outfile; + + outfile.open(filename.c_str()); + + if(!outfile.is_open()){ + cerr << "Error opening " << filename << "for writing\n"; + } + else { + int i; + for(i = 0; i < kcores.size(); i++){ + outfile << i << " " << kcores[i] << "\n"; + } + } + + outfile.close(); +} // write_k_cores + diff --git a/util/src/graph_stats.cpp b/util/src/graph_stats.cpp index 94d0ba5..09c0d2d 100644 --- a/util/src/graph_stats.cpp +++ b/util/src/graph_stats.cpp @@ -45,7 +45,7 @@ void print_time(string prefix, ORB_t start, ORB_t end){ cout << prefix + ": " << ORB_seconds(end, start) << endl; } -const string allowed_methods ("edge_density,avg_degree,degree_dist,global_cc,avg_cc,local_ccs,shortest_paths,assortativity,eccentricity,eccentricity_dist,expansion,avg_shortest_path,shortest_paths_boost,eigen_spectrum"); +const string allowed_methods ("edge_density,avg_degree,degree_dist,global_cc,avg_cc,local_ccs,shortest_paths,assortativity,eccentricity,eccentricity_dist,expansion,avg_shortest_path,shortest_paths_boost,eigen_spectrum,k_cores,degeneracy"); /** * Creates a map from a comma-separated string @@ -162,6 +162,8 @@ int main(int argc, char **argv){ vector local_cc, freq_ecc, norm_hops, eigen_spectrum; float edge_density, avg_degree; vector deg_dist, ecc; + int degeneracy; + vector k_cores; double avg_path_length; vector< vector > shortest_path_distances; @@ -218,6 +220,19 @@ int main(int argc, char **argv){ print_time("Time(assortativity)", t1, t2); outfile << "assortativity " << assortativity << endl; } + if((req_methods["degeneracy"] == true) || (req_methods["k_cores"] == true)){ + cout << "Calculating k_cores and degeneracy" << endl; + ORB_read(t1); + degeneracy = gu.find_kcore(&g, &k_cores); + ORB_read(t2); + print_time("Time(find_kcore)", t1, t2); + outfile << "degeneracy " << degeneracy << endl; + if(req_methods["k_cores"] == true){ + string of = outprefix + ".kcores"; + write_kcores(of, k_cores); + } + } + if((req_methods["global_cc"] == true) || (req_methods["local_ccs"] == true) || (req_methods["avg_cc"] == true)){ cout << "Calculating clustering coefficients" << endl; ORB_read(t1); From 92b7bcc703cc9f6556d14c9e0042d792e2b0ad6e Mon Sep 17 00:00:00 2001 From: Matthew Baker Date: Thu, 18 Jul 2013 13:21:52 -0400 Subject: [PATCH 29/73] doxygen comments for eigen spectrum --- lib_graphd/inc/GraphUtil.h | 6 ++++++ lib_graphd/src/GraphUtil.cpp | 10 ++++++++++ 2 files changed, 16 insertions(+) diff --git a/lib_graphd/inc/GraphUtil.h b/lib_graphd/inc/GraphUtil.h index 6420994..f50c2fb 100644 --- a/lib_graphd/inc/GraphUtil.h +++ b/lib_graphd/inc/GraphUtil.h @@ -95,7 +95,13 @@ namespace Graph { //Calculate the maximum distance between nodes within a subset of vertices //given as a list int subset_max_dist(Graph *g, vector subset); + /** + * \brief Populate adjency matrix as a Petsc Matrix + */ void populate_PetscMat(Graph *g); + /** + * \brief Releases PetscMat. + */ void free_PetscMat(Graph *g); }; diff --git a/lib_graphd/src/GraphUtil.cpp b/lib_graphd/src/GraphUtil.cpp index a165280..82ac4ef 100644 --- a/lib_graphd/src/GraphUtil.cpp +++ b/lib_graphd/src/GraphUtil.cpp @@ -535,6 +535,11 @@ namespace Graph { #endif //HAS_BOOST #ifdef HAS_PETSC + /** + * Populates the PetscMat member of graph g. This function will also call populate_CRS() if it hasn't been already. + * Durring cleanup a free_CRS() also needs to be done. + * \param[in] g the input graph + */ void GraphUtil::populate_PetscMat(Graph *g){ if(g->adjncy.size() == 0){ populate_CRS(g); @@ -574,6 +579,11 @@ namespace Graph { CHKERRABORT(PETSC_COMM_WORLD,ierror); } // populate_PetscMat + /** + * Frees the PetscMat member of g. This function will not cleanup CRS, even if populate_PetscMat() filled it. + * You will have to also call free_CRS(); + * \param[in] g the input graph + */ void GraphUtil::free_PetscMat(Graph *g){ PetscErrorCode ierror = MatDestroy(&(g->PetscMat)); CHKERRABORT(PETSC_COMM_WORLD,ierror); From f617e5bb25f4fe016a3c38e26e0f802e447396e1 Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Thu, 18 Jul 2013 13:28:51 -0400 Subject: [PATCH 30/73] Fix graph_stats to emit a warning if calling shortest_paths_boost and it's not compiled in. Previously was silently failing --- util/src/graph_stats.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/util/src/graph_stats.cpp b/util/src/graph_stats.cpp index 09c0d2d..1501097 100644 --- a/util/src/graph_stats.cpp +++ b/util/src/graph_stats.cpp @@ -269,7 +269,10 @@ int main(int argc, char **argv){ ORB_read(t2); print_time("Time(shortest_paths_dijkstra_boost)", t1, t2); } + #else + cerr << "Error: BOOST support was not compiled, cannot run shortest_paths_boost" << endl; #endif + if(req_methods["eccentricity"] == true){ cout << "Calculating eccentricities" << endl; ORB_read(t1); From 336bd6c0eea08d3bb1b0e808081fbf8126c176b9 Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Fri, 19 Jul 2013 09:42:12 -0400 Subject: [PATCH 31/73] Starting BC calculations; gives wrong answer --- lib_graphd/inc/Graph.h | 6 ++++ lib_graphd/inc/GraphProperties.h | 2 +- lib_graphd/inc/Util.h | 6 ++++ lib_graphd/src/Graph.cpp | 15 ++++++++ lib_graphd/src/GraphProperties.cpp | 55 ++++++++++++++++++++++++------ lib_graphd/src/Util.cpp | 24 +++++++++++++ util/src/graph_stats.cpp | 12 +++++-- 7 files changed, 105 insertions(+), 15 deletions(-) diff --git a/lib_graphd/inc/Graph.h b/lib_graphd/inc/Graph.h index 215089e..d6f6175 100644 --- a/lib_graphd/inc/Graph.h +++ b/lib_graphd/inc/Graph.h @@ -85,6 +85,7 @@ namespace Graph { #ifdef HAS_BOOST BoostUndirected *boost_graph; + vector betweenness; #endif //HAS_BOOST #ifdef HAS_PETSC @@ -116,6 +117,8 @@ namespace Graph { void resize(int n); /** \brief set shortest path distances **/ void set_shortest_path_dist(vector< vector > apsp_dist); + /** \brief set betweenness centrality vector **/ + void set_betweenness(vector bc); vector get_adj_vec() const; vector *get_adj_vec_ptr(); @@ -135,6 +138,9 @@ namespace Graph { int get_num_nodes() const; vector get_xadj() const; + /** \brief get a const ref to the betweenness vector **/ + const vector &get_betweenness_ref(); + virtual bool is_edge(int i, int j) const; bool is_canonical() const; bool is_simple() const; diff --git a/lib_graphd/inc/GraphProperties.h b/lib_graphd/inc/GraphProperties.h index 6d177ff..aa5d982 100644 --- a/lib_graphd/inc/GraphProperties.h +++ b/lib_graphd/inc/GraphProperties.h @@ -81,7 +81,7 @@ namespace Graph { /** * \brief returns shortest paths from source to all other nodes */ - void paths_dijkstra_boost_single(Graph *g, vector &dists, int source); + void paths_dijkstra_boost_single(Graph *g, vector &dists, vector &preds, int source); /** * \brief returns shortest paths from all nodes to all nodes diff --git a/lib_graphd/inc/Util.h b/lib_graphd/inc/Util.h index 67dbbdc..a52b568 100644 --- a/lib_graphd/inc/Util.h +++ b/lib_graphd/inc/Util.h @@ -102,6 +102,12 @@ void write_degree_distribution(string filename, const vector &dist); */ void write_kcores(string filename, const vector &kcores); + +/** + * \brief write a betweenness centrality list out to a file + */ +void write_betweenness(string filename, const vector &bc); + int_int mylog2(int x); #endif /* UTIL_H_ */ diff --git a/lib_graphd/src/Graph.cpp b/lib_graphd/src/Graph.cpp index 3520454..73f2e9e 100644 --- a/lib_graphd/src/Graph.cpp +++ b/lib_graphd/src/Graph.cpp @@ -696,6 +696,21 @@ namespace Graph { this->apsp_dist = apsp_dist; } + /** + * \param[in] bc betweenness centrality measures for all vertices + */ + void Graph::set_betweenness(vector bc){ + this->betweenness = bc; + } + + /** + * return a const ref to the betweenness centrality vector + */ + const vector &Graph::get_betweenness_ref(){ + //FIXME: should this check to see if it's not-empty? + return this->betweenness; + } + /** * Checks if distance matrix has been computed (or needs to be recomputed) * if yes, returns the all pairs shortest paths distances diff --git a/lib_graphd/src/GraphProperties.cpp b/lib_graphd/src/GraphProperties.cpp index a588508..24f7193 100644 --- a/lib_graphd/src/GraphProperties.cpp +++ b/lib_graphd/src/GraphProperties.cpp @@ -628,13 +628,17 @@ namespace Graph { * \param[in] source node id * \param[out] p path distances from source to all other vertices */ - void GraphProperties::paths_dijkstra_boost_single(Graph *g, vector &dists, int source){ + void GraphProperties::paths_dijkstra_boost_single(Graph *g, vector &dists, vector &preds, int source){ BoostUndirected *bg = g->boost_graph; - std::vector p(boost::num_vertices(*bg)); + //std::vector p(boost::num_vertices(*bg)); dists.resize(g->get_num_nodes()); //std::vector d(boost::num_vertices(*bg)); vertex_descriptor s = vertex(source, *bg); - boost::dijkstra_shortest_paths(*bg, s, boost::predecessor_map(&p[0]).distance_map(&dists[0])); + boost::dijkstra_shortest_paths(*bg, s, boost::predecessor_map(&preds[0]).distance_map(&dists[0])); + int i; + //for(i=0;i > &pAll){ int inf = INDDGO_INFINITY; - int minD = inf; + const int n = g->get_num_nodes(); + std::vector betweenness_counts(n, 0); + std::vector betweenness(n, 0.0); + + pAll.resize(n); //#pragma omp parallel for default(none) shared(g, inf, pAll) private(nvisiting, nVisited, nv) firstprivate(dist, minD, visited) - #pragma omp parallel for schedule(dynamic, 8) default(none) shared(g, inf, pAll) - //loop over all vertices - for(int v = 0; v < n; v++){ //0; v < n; v++){ - //reset all distances to INF and mark all vertices as unvisited - fill(pAll[v].begin(),pAll[v].end(),inf); - paths_dijkstra_boost_single(g, pAll[v], v); //stores shortest paths from this vertex to all in pAll[v] - } //end loop over vertices + #pragma omp parallel default(none) shared(g, inf, betweenness_counts, pAll) + { + std::vector p(boost::num_vertices(*(g->boost_graph))); + int i; + #pragma omp for schedule(dynamic, 8) + //loop over all vertices + for(int v = 0; v < n; v++){ //0; v < n; v++){ + //reset all distances to INF and mark all vertices as unvisited + fill(pAll[v].begin(),pAll[v].end(),inf); + paths_dijkstra_boost_single(g, pAll[v], p, v); //stores shortest paths from this vertex to all in pAll[v] + #pragma omp critical //since we can't reduce over an array *grumble* + { + printf("for source node %d pred is ", v); + for(i=0;iset_shortest_path_dist(pAll); + double num_paths = n*(n-1)/2; + cout << "Number of paths: " << num_paths << endl; + for(int i=0; iset_betweenness(betweenness); } // paths_dijkstra_boost_all #endif // ifdef HAS_BOOST diff --git a/lib_graphd/src/Util.cpp b/lib_graphd/src/Util.cpp index 3ee902e..073f324 100644 --- a/lib_graphd/src/Util.cpp +++ b/lib_graphd/src/Util.cpp @@ -887,3 +887,27 @@ void write_kcores(string filename, const vector &kcores){ outfile.close(); } // write_k_cores +/** + * Write a betweenness centrality vecotr out to file. + * + * \param[in] filename filename to write output to + * \param[in] bc a vector, indexed on vertex number + */ +void write_betweenness(string filename, const vector &bc){ + ofstream outfile; + + outfile.open(filename.c_str()); + + if(!outfile.is_open()){ + cerr << "Error opening " << filename << "for writing\n"; + } + else { + outfile.precision(10); + int i; + for(i = 0; i < bc.size(); i++){ + outfile << fixed << i << " " << bc[i] << "\n"; + } + } + + outfile.close(); +} diff --git a/util/src/graph_stats.cpp b/util/src/graph_stats.cpp index 1501097..373484f 100644 --- a/util/src/graph_stats.cpp +++ b/util/src/graph_stats.cpp @@ -45,7 +45,7 @@ void print_time(string prefix, ORB_t start, ORB_t end){ cout << prefix + ": " << ORB_seconds(end, start) << endl; } -const string allowed_methods ("edge_density,avg_degree,degree_dist,global_cc,avg_cc,local_ccs,shortest_paths,assortativity,eccentricity,eccentricity_dist,expansion,avg_shortest_path,shortest_paths_boost,eigen_spectrum,k_cores,degeneracy"); +const string allowed_methods ("edge_density,avg_degree,degree_dist,global_cc,avg_cc,local_ccs,shortest_paths,assortativity,eccentricity,eccentricity_dist,expansion,avg_shortest_path,shortest_paths_boost,eigen_spectrum,k_cores,degeneracy,betweenness"); /** * Creates a map from a comma-separated string @@ -229,6 +229,7 @@ int main(int argc, char **argv){ outfile << "degeneracy " << degeneracy << endl; if(req_methods["k_cores"] == true){ string of = outprefix + ".kcores"; + outfile << "kcore file " << of << endl; write_kcores(of, k_cores); } } @@ -257,7 +258,7 @@ int main(int argc, char **argv){ } #ifdef HAS_BOOST - if(req_methods["shortest_paths_boost"] == true){ + if((req_methods["shortest_paths_boost"] == true) or (req_methods["betweenness"] == true)){ cout << "Creating BOOST representation of g" << endl; ORB_read(t1); gu.populate_boost(&g); @@ -268,9 +269,14 @@ int main(int argc, char **argv){ gp.paths_dijkstra_boost_all(&g, shortest_path_distances); ORB_read(t2); print_time("Time(shortest_paths_dijkstra_boost)", t1, t2); + if(req_methods["betweenness"]) { + string of = outprefix + ".betweenness"; + outfile << "betweenness_file " << of << endl; + write_betweenness(of, g.get_betweenness_ref()); + } } #else - cerr << "Error: BOOST support was not compiled, cannot run shortest_paths_boost" << endl; + cerr << "Error: BOOST support was not compiled, cannot run shortest_paths_boost or betweenness" << endl; #endif if(req_methods["eccentricity"] == true){ From 45081054e860d787ab1112e77abdbdcf1b1c53d6 Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Fri, 19 Jul 2013 11:35:06 -0400 Subject: [PATCH 32/73] - reimplement betweenness centrality using boost methods - code clean --- lib_graphd/inc/Graph.h | 3 +- lib_graphd/inc/GraphProperties.h | 7 +++++ lib_graphd/inc/Util.h | 1 - lib_graphd/src/Graph.cpp | 2 +- lib_graphd/src/GraphProperties.cpp | 48 ++++++++++++++---------------- lib_graphd/src/Util.cpp | 3 +- util/src/graph_stats.cpp | 29 ++++++++++++------ 7 files changed, 55 insertions(+), 38 deletions(-) diff --git a/lib_graphd/inc/Graph.h b/lib_graphd/inc/Graph.h index d6f6175..99b9008 100644 --- a/lib_graphd/inc/Graph.h +++ b/lib_graphd/inc/Graph.h @@ -55,7 +55,8 @@ using namespace std; #ifdef HAS_BOOST typedef boost::property EdgeWeightProperty; -typedef boost::adjacency_list BoostUndirected; +typedef boost::property CentralityMap; +typedef boost::adjacency_list BoostUndirected; typedef boost::graph_traits < BoostUndirected >::vertex_descriptor vertex_descriptor; typedef boost::graph_traits < BoostUndirected >::edge_descriptor edge_descriptor; #endif //HAS_BOOST diff --git a/lib_graphd/inc/GraphProperties.h b/lib_graphd/inc/GraphProperties.h index aa5d982..9a37588 100644 --- a/lib_graphd/inc/GraphProperties.h +++ b/lib_graphd/inc/GraphProperties.h @@ -26,6 +26,7 @@ #ifdef HAS_BOOST #include "boost/graph/adjacency_list.hpp" #include "boost/graph/topological_sort.hpp" + #include "boost/graph/betweenness_centrality.hpp" #endif using namespace std; @@ -87,6 +88,12 @@ namespace Graph { * \brief returns shortest paths from all nodes to all nodes */ void paths_dijkstra_boost_all(Graph *g, vector< vector > &p); + + /** + * \brief calculations betweenness centrality for all vertices + */ + void betweenness_centrality(Graph *g, vector &bc); + #endif /** diff --git a/lib_graphd/inc/Util.h b/lib_graphd/inc/Util.h index a52b568..2fa188c 100644 --- a/lib_graphd/inc/Util.h +++ b/lib_graphd/inc/Util.h @@ -102,7 +102,6 @@ void write_degree_distribution(string filename, const vector &dist); */ void write_kcores(string filename, const vector &kcores); - /** * \brief write a betweenness centrality list out to a file */ diff --git a/lib_graphd/src/Graph.cpp b/lib_graphd/src/Graph.cpp index 73f2e9e..9e68983 100644 --- a/lib_graphd/src/Graph.cpp +++ b/lib_graphd/src/Graph.cpp @@ -707,7 +707,7 @@ namespace Graph { * return a const ref to the betweenness centrality vector */ const vector &Graph::get_betweenness_ref(){ - //FIXME: should this check to see if it's not-empty? + //FIXME: should this check to see if it's not-empty? return this->betweenness; } diff --git a/lib_graphd/src/GraphProperties.cpp b/lib_graphd/src/GraphProperties.cpp index 24f7193..f605251 100644 --- a/lib_graphd/src/GraphProperties.cpp +++ b/lib_graphd/src/GraphProperties.cpp @@ -656,7 +656,6 @@ namespace Graph { std::vector betweenness_counts(n, 0); std::vector betweenness(n, 0.0); - pAll.resize(n); //#pragma omp parallel for default(none) shared(g, inf, pAll) private(nvisiting, nVisited, nv) firstprivate(dist, minD, visited) @@ -665,38 +664,37 @@ namespace Graph { std::vector p(boost::num_vertices(*(g->boost_graph))); int i; #pragma omp for schedule(dynamic, 8) - //loop over all vertices - for(int v = 0; v < n; v++){ //0; v < n; v++){ + for(int v = 0; v < n; v++){ //reset all distances to INF and mark all vertices as unvisited fill(pAll[v].begin(),pAll[v].end(),inf); paths_dijkstra_boost_single(g, pAll[v], p, v); //stores shortest paths from this vertex to all in pAll[v] - #pragma omp critical //since we can't reduce over an array *grumble* - { - printf("for source node %d pred is ", v); - for(i=0;iset_shortest_path_dist(pAll); - double num_paths = n*(n-1)/2; - cout << "Number of paths: " << num_paths << endl; - for(int i=0; iset_betweenness(betweenness); } // paths_dijkstra_boost_all + /** + * Calculate the relative betweenness centrality for all nodes + * \param[in] g input graph + * \param[out] bc vector with one BC value for each vertex + */ + + void GraphProperties::betweenness_centrality(Graph *g, vector &bc){ + BoostUndirected *bg = g->boost_graph; + bc.resize(g->get_num_nodes()); + //boost::brandes_betweenness_centrality(*bg, get(boost::vertex_centrality, *bg)); + boost::brandes_betweenness_centrality(*bg, + boost::centrality_map( + boost::make_iterator_property_map(bc.begin(), get(boost::vertex_index, *bg), double())).vertex_index_map(get(boost::vertex_index, *bg) + ) + ); + + boost::relative_betweenness_centrality(*bg, + boost::make_iterator_property_map(bc.begin(), get(boost::vertex_index, *bg), double())); + g->set_betweenness(bc); + } + #endif // ifdef HAS_BOOST /** diff --git a/lib_graphd/src/Util.cpp b/lib_graphd/src/Util.cpp index 073f324..2be89b3 100644 --- a/lib_graphd/src/Util.cpp +++ b/lib_graphd/src/Util.cpp @@ -910,4 +910,5 @@ void write_betweenness(string filename, const vector &bc){ } outfile.close(); -} +} // write_betweenness + diff --git a/util/src/graph_stats.cpp b/util/src/graph_stats.cpp index 373484f..49e0278 100644 --- a/util/src/graph_stats.cpp +++ b/util/src/graph_stats.cpp @@ -165,6 +165,7 @@ int main(int argc, char **argv){ int degeneracy; vector k_cores; double avg_path_length; + vector betweenness; vector< vector > shortest_path_distances; @@ -258,7 +259,7 @@ int main(int argc, char **argv){ } #ifdef HAS_BOOST - if((req_methods["shortest_paths_boost"] == true) or (req_methods["betweenness"] == true)){ + if((req_methods["shortest_paths_boost"] == true)){ cout << "Creating BOOST representation of g" << endl; ORB_read(t1); gu.populate_boost(&g); @@ -269,15 +270,25 @@ int main(int argc, char **argv){ gp.paths_dijkstra_boost_all(&g, shortest_path_distances); ORB_read(t2); print_time("Time(shortest_paths_dijkstra_boost)", t1, t2); - if(req_methods["betweenness"]) { - string of = outprefix + ".betweenness"; - outfile << "betweenness_file " << of << endl; - write_betweenness(of, g.get_betweenness_ref()); - } } - #else - cerr << "Error: BOOST support was not compiled, cannot run shortest_paths_boost or betweenness" << endl; - #endif + if(req_methods["betweenness"]){ + /* cout << "Creating BOOST representation of g" << endl; + ORB_read(t1); + gu.populate_boost(&g); + ORB_read(t2); + print_time("Time(populate_boost)", t1, t2); + */cout << "Calculating betweeneess centrality" << endl; + ORB_read(t1); + gp.betweenness_centrality(&g, betweenness); + ORB_read(t2); + print_time("Time(betweenness_centrality",t1,t2); + string of = outprefix + ".betweenness"; + outfile << "betweenness_file " << of << endl; + write_betweenness(of, g.get_betweenness_ref()); + } + #else // ifdef HAS_BOOST + cerr << "Error: BOOST support was not compiled, cannot run shortest_paths_boost or betweenness" << endl; + #endif // ifdef HAS_BOOST if(req_methods["eccentricity"] == true){ cout << "Calculating eccentricities" << endl; From cf6a2afe2a506cd53ff6bb06f02623bc438a68ea Mon Sep 17 00:00:00 2001 From: Jonathan Schrock Date: Fri, 19 Jul 2013 15:23:00 -0400 Subject: [PATCH 33/73] Added delta hyperbolicity code along with corresponding gtests. The gtests cover connected and disconnected graphs. Currently, requires omp to compile and run. --- lib_graphd/inc/GraphDecomposition.h | 2 +- lib_graphd/inc/GraphProperties.h | 6 +- lib_graphd/src/GraphProperties.cpp | 359 +++++++++++++++++++++++++- lib_graphd/test/GraphPropertyTest.cpp | 18 ++ 4 files changed, 381 insertions(+), 4 deletions(-) diff --git a/lib_graphd/inc/GraphDecomposition.h b/lib_graphd/inc/GraphDecomposition.h index 54906ae..aa059b4 100644 --- a/lib_graphd/inc/GraphDecomposition.h +++ b/lib_graphd/inc/GraphDecomposition.h @@ -120,7 +120,7 @@ static const char EO_NAMES[][30] = { // Include header files #include "GraphDecomposition.h" #include "Graph.h" -#include "Graph.h" +//#include "Graph.h" #include "DIMACSGraphReader.h" #include "DIMACSGraphWriter.h" #include "GraphDisplay.h" diff --git a/lib_graphd/inc/GraphProperties.h b/lib_graphd/inc/GraphProperties.h index 7706e7f..28e087a 100644 --- a/lib_graphd/inc/GraphProperties.h +++ b/lib_graphd/inc/GraphProperties.h @@ -125,13 +125,17 @@ namespace Graph { /** * \brief Fits the degree distribution of the specified graph to a power law distribution */ - //void powerlaw(Graph *g, double start = 1.5, double inc = 0.01, double end = 3.5, int &xmin, double &alpha, double &KS ); void powerlaw(Graph *g, int &xmin, double &alpha, double &KS, double start = 1.5, double inc = 0.01, double end = 3.5); /** * \brief Returns the degree assortativity coefficient of a graph */ void deg_assortativity(Graph *g, double &coeff); + + /** + * \brief Returns the delta hyperbolicity of a graph + */ + void delta_hyperbolicity(Graph *g, double &max_delta, vector > &delta); }; } diff --git a/lib_graphd/src/GraphProperties.cpp b/lib_graphd/src/GraphProperties.cpp index ac2716f..8d8f113 100644 --- a/lib_graphd/src/GraphProperties.cpp +++ b/lib_graphd/src/GraphProperties.cpp @@ -623,8 +623,7 @@ namespace Graph { */ void GraphProperties::paths_dijkstra_single(Graph *g, vector &p, int source){ - //int inf = 100000; - int inf = INT_MAX; + int inf = INDDGO_INFINITY; int nVisited = 0; int minD; int nvisiting; @@ -814,6 +813,7 @@ namespace Graph { for(i = 0; i < size; i++){ for(j = 0; j < i; j++){ temp = dist_mat[i][j]; + if((temp > diam) && (temp < INDDGO_INFINITY)){ diam = temp; } @@ -1083,4 +1083,359 @@ namespace Graph { coeff = (n1 - n2) / (de - n2); } // deg_assortativity + + /** + * Calculates the delta hyperbolicity of a graph g and returns the hyperbolicity distribution + * \param[in] g Pointer to a graph + * \param[out] mex_delta Double value holding the maximum delta value encountered + * \param[out] delta Vector of vectors of doubles holding the delta hyperbolicity distribution + */ + void GraphProperties::delta_hyperbolicity(Graph *g, double &max_delta, vector > &delta){ + vector< vector > dist_mat = g->get_shortest_path_dist_ref(); + int size = dist_mat.size(); + int mat_size = dist_mat.size(); + int counter = 0; + int row = 0; + int diam; + + if(g->num_nodes < 4){ + cerr << "Graph is too small for hyperbolicity, returning zero\n"; + vector delta_vec(1, 0); + delta.push_back(delta_vec); + return; + } + + if(!is_connected(g)){ + cerr << "Graph passed to calc_gromov has multiple components\n"; + + //Find the largest connected component + int temp = 0; + size = 0; + for(int i = 0; i < mat_size; i++){ + temp = 0; + for(int j = 0; j < mat_size; j++){ + if(dist_mat[i][j] != INDDGO_INFINITY){ + temp++; + } + } + //temp++; //count the vertex currently being tested + if(temp > size){ + size = temp; + row = i; + } + } + } + + //build vertex set of largest connected component and find its diameter + int temp_diam = 0; + vector vert_vec(size); + for(int j = 0; j < mat_size; j++){ + if(dist_mat[row][j] != INDDGO_INFINITY){ + vert_vec[counter] = j; + counter++; + if(dist_mat[row][j] > temp_diam){ + temp_diam = dist_mat[row][j]; + } + } + else if(j == row){ + vert_vec[counter] = j; + counter++; + } + } + diam = temp_diam; + + max_delta = 0; + + for(int i = 0; i < diam; i++){ + vector zero_dist(2 * diam + 1,0); + delta.push_back(zero_dist); + } + + int num_threads = omp_get_max_threads(); + + //////////////////////////////////////////////////////////// + //These are the shared variables between threads. Each thread has access to a certain pointer. + //The pointer should then point to a copy of the variable for the thread's private (local) use. + //Shared max_delta and shared_delta are updated by each thread, must be careful to avoid contention. + //////////////////////////////////////////////////////////// + + int size_of_array = 64 / sizeof(double *); //64 is cacheline size, needs to be updated on different machines for performance + int type_size = sizeof(double *); + if(type_size < sizeof(vector< vector > *)){ + type_size = sizeof(vector< vector > *); + } + + counter = 1; + while(num_threads * type_size > size_of_array){ + ++counter; + size_of_array = counter * 64 / sizeof(double *); + } + + //////////////////////////////////////////////////////////// + //Pointers to shared data arrays that have copy of the delta information for each thread, + //ie, if there are 8 threads, there will be an 8 (pointers to) arrays each accessed by only one thread, + //At the end of the parallel section of code, the 8 arrays will be combined into a single array + /////////////////////////////////////////////////////////// + + double **shared_max_delta; + shared_max_delta = new double * [size_of_array]; + + vector< vector > **shared_delta; + shared_delta = new vector< vector > * [size_of_array]; + + #if defined (TASK_PROFILE) || defined(TASK_PROFILE_OVERHEAD) + int num_tasks1[1024][1024]; + int num_tasks2[1024][1024]; + int num_tasks1_switch[1024][1024]; + int num_tasks2_switch[1024][1024]; + int total_threads = 0; + double task_time[1024][512]; + double time_starts = 0.0; + double time_stops = 0.0; + #endif + + //OMP parallel region, this current implementation generates tasks at two of the four levels of the nested for loop, + // these tasks are then passed to threads which execute them and update their private copy of the results array + //After the tasks have all been generated and executed the results are collated + #pragma omp parallel shared(delta, max_delta, shared_max_delta, diam, shared_delta, dist_mat, vert_vec, size) + { + double max_delta_loc = 0; + + vector zero_dist(2 * diam + 1,0); + zero_dist.reserve(256 / sizeof(double)); + + vector< vector > delta_loc(diam,zero_dist); + + int thread_id = omp_get_thread_num(); + + #ifdef TASK_PROFILE + num_tasks1[thread_id][0] = 0; + num_tasks2[thread_id][0] = 0; + num_tasks1_switch[thread_id][0] = 0; + num_tasks2_switch[thread_id][0] = 0; + int total_threads = 0; + #endif + #ifdef TASK_PROFILE_OVERHEAD + task_time[thread_id][0] = 0.0; + #endif + + shared_max_delta[thread_id] = &max_delta_loc; + + shared_delta[thread_id] = &delta_loc; + + //size_t size = vert_vec.size(); + + #pragma omp single + { + #ifdef TASK_PROFILE_OVERHEAD + time_starts = omp_get_wtime(); + #endif + + for(int i = 0; i < size; ++i){ + #if defined (TASK_PROFILE) || defined (TASK_PROFILE_OVERHEAD) + #pragma omp task shared(shared_delta, shared_max_delta, dist_mat, vert_vec, size, num_tasks1, num_tasks2, task_time) + #else + #pragma omp task shared(shared_delta, shared_max_delta, dist_mat, vert_vec, size) + #endif + { + #ifdef TASK_PROFILE + int thread_id = omp_get_thread_num(); + num_tasks1[thread_id][0]++; + #endif + #ifdef TASK_PROFILE_OVERHEAD + double tt1 = omp_get_wtime(); + #endif + + for(int j = i + 1; j < size; ++j){ + #if defined (TASK_PROFILE) || defined (TASK_PROFILE_OVERHEAD) + #pragma omp task shared(shared_delta, shared_max_delta, dist_mat, vert_vec, size, num_tasks1, num_tasks2, task_time) + #else + #pragma omp task shared(shared_delta, shared_max_delta, dist_mat, vert_vec, size) + #endif + { + int thread_num = omp_get_thread_num(); + + #ifdef TASK_PROFILE + num_tasks2[thread_num][0]++; + #endif + #ifdef TASK_PROFILE_OVERHEAD + double ttt1 = omp_get_wtime(); + #endif + + vector > &loc_delta = *shared_delta[thread_num]; + + double &max_delta_loc = *shared_max_delta[thread_num]; + + for(int k = j + 1; k < size; ++k){ + for(int l = k + 1; l < size; ++l){ + const int ui = vert_vec[i]; + + const int vi = vert_vec[j]; + const int uv = (dist_mat)[ui][vi]; + + const int xi = vert_vec[k]; + const int ux = (dist_mat)[ui][xi]; + const int vx = (dist_mat)[vi][xi]; + + const int yi = vert_vec[l]; + const int uy = (dist_mat)[ui][yi]; + const int vy = (dist_mat)[vi][yi]; + const int xy = (dist_mat)[xi][yi]; + + const int s1 = uv + xy; + const int s2 = ux + vy; + const int s3 = uy + vx; + + double currDelta = 0; + unsigned long maxPair = 1; + + //find max pair distance + maxPair = uv; + + if(xy > maxPair){ + maxPair = xy; + } + + if(ux > maxPair){ + maxPair = ux; + } + + if(vy > maxPair){ + maxPair = vy; + } + + if(uy > maxPair){ + maxPair = uy; + } + + if(vx > maxPair){ + maxPair = vx; + } + + //Delta calculations + + if((s1 >= s2) && (s3 >= s2) ){ + currDelta = abs(s1 - s3) / 2.0; //works since s1 and s2 are positive + } + else if((s2 >= s1) && (s3 >= s1) ){ + currDelta = abs(s2 - s3) / 2.0; + } + else { + currDelta = abs(s1 - s2) / 2.0; + } + + ++(loc_delta)[maxPair - 1][2 * currDelta + 1]; + + if(currDelta > max_delta_loc){ + max_delta_loc = currDelta; + } + + ++(loc_delta)[maxPair - 1][0]; + } + } + + #ifdef TASK_PROFILE_OVERHEAD + double ttt2 = omp_get_wtime(); + task_time[thread_num][0] += (ttt2 - ttt1); + #endif + #ifdef TASK_PROFILE + int thread_id_end = omp_get_thread_num(); + if(thread_id != thread_id_end){ + num_tasks2_switch[thread_id_end][0]++; + } + #endif + } // end task + } + + #ifdef TASK_PROFILE_OVERHEAD + //double tt2 = omp_get_wtime(); + //task_time[thread_id][0]+= (tt2 - tt1); + #endif + #ifdef TASK_PROFILE + int thread_id_end = omp_get_thread_num(); + if(thread_id != thread_id_end){ + num_tasks1_switch[thread_id_end][0]++; + } + #endif + } // end task + } + } // end single + + #ifdef TASK_PROFILE_OVERHEAD + #pragma omp single nowait + { + time_stops = omp_get_wtime(); + } + #endif + + double t1 = time(NULL); + + #pragma omp critical (collate_delta) + { + int thread_num = omp_get_thread_num(); + vector > *delta_point = shared_delta[thread_num]; + vector > &loc_delta = *delta_point; + + int i_size = loc_delta.size(); + for(int i = 0; i < i_size; ++i){ + int j_size = loc_delta[i].size(); + for(int j = 0; j < j_size; ++j){ + delta[i][j] += loc_delta[i][j]; + } + } + + if(max_delta_loc > max_delta){ + max_delta = max_delta_loc; + } + } + + double t2 = time(NULL); + + #pragma omp single + { + cout << "Critical Region time: " << t2 - t1 << "\n"; + } + } //END OF FIRST PRAGMA + + //take care of pointer! + delete [] shared_delta; + delete [] shared_max_delta; + + //Needs removed before parallel code is implemented + for(int i = 0; i < diam; ++i){ + delta[i].erase(delta[i].begin() + 2 * max_delta + 2, delta[i].end()); + } + + #if defined (TASK_PROFILE) || defined (TASK_PROFILE_OVERHEAD) + + #pragma omp parallel shared(total_threads) + { + #pragma omp master + { + total_threads = omp_get_num_threads(); + } + } + + cout << endl << endl << "******Tasks Statistics: (num_task, num_tasks, migrated_tasks, switched_task, task_time)" << endl; + + for(int i = 0; i < total_threads; i++){ + cout << i + #endif + #ifdef TASK_PROFILE + << "," << num_tasks1[i][0] << "," << num_tasks2[i][0] << "," << num_tasks1_switch[i][0] << "," << num_tasks2_switch[i][0] + #endif + #ifdef TASK_PROFILE_OVERHEAD + << "," << task_time[i][0] + #endif + #if defined (TASK_PROFILE) || defined (TASK_PROFILE_OVERHEAD) + << endl; + } // delta_hyperbolicity + + cout << endl; + + #endif + #ifdef TASK_PROFILE_OVERHEAD + cout << "Time in task region = " << time_stops - time_starts << endl; + #endif + } } diff --git a/lib_graphd/test/GraphPropertyTest.cpp b/lib_graphd/test/GraphPropertyTest.cpp index 89cf67d..1300cda 100644 --- a/lib_graphd/test/GraphPropertyTest.cpp +++ b/lib_graphd/test/GraphPropertyTest.cpp @@ -186,3 +186,21 @@ TEST_F(GraphPropertyTest, testPowerLaw){ EXPECT_LT(abs(3.5 - alpha), 0.1); EXPECT_LT(abs(0.470626 - KS), 0.000001); } + +TEST_F(GraphPropertyTest, testDeltaHyperbolicity){ + double max_delta; + vector > delta; + + properties.delta_hyperbolicity(mg, max_delta, delta); + EXPECT_LT(abs(2.0 - max_delta), 0.1); + EXPECT_LT(abs(204.0 - delta[3][5]), 0.1); + + creator.set_file_name("data/1et.64.txt"); + creator.set_graph_type("DIMACS"); + mg = creator.create_mutable_graph(); + + delta.clear(); + properties.delta_hyperbolicity(mg, max_delta, delta); + EXPECT_LT(abs(1.0 - max_delta), 0.1); + EXPECT_LT(abs(126.0 - delta[1][3]), 0.1); +} From aba88b75002c832fa379cb3470c96315876f4b00 Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Fri, 19 Jul 2013 15:30:51 -0400 Subject: [PATCH 34/73] Fix valgrind complaints about memory leaks --- lib_graphd/src/Graph.cpp | 6 ++++++ lib_graphd/src/GraphProperties.cpp | 9 ++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/lib_graphd/src/Graph.cpp b/lib_graphd/src/Graph.cpp index 9e68983..da68e67 100644 --- a/lib_graphd/src/Graph.cpp +++ b/lib_graphd/src/Graph.cpp @@ -39,6 +39,7 @@ namespace Graph { this->simple = true; //FIXME: check if this is correct behavior this->canonical = true; this->key = 0; + this->boost_graph = NULL; } Graph::Graph(int n){ @@ -52,9 +53,14 @@ namespace Graph { nodes[i].set_label(i + 1); } this->next_label = n + 1; + this->boost_graph = NULL; } Graph::~Graph(){ + #ifdef HAS_BOOST + delete boost_graph; + boost_graph = NULL; + #endif } void Graph::set_canonical(bool c){ diff --git a/lib_graphd/src/GraphProperties.cpp b/lib_graphd/src/GraphProperties.cpp index f605251..c0c2cff 100644 --- a/lib_graphd/src/GraphProperties.cpp +++ b/lib_graphd/src/GraphProperties.cpp @@ -25,6 +25,10 @@ #include #include +#include +#include +#include + #include #ifdef HAS_SLEPC #include @@ -836,11 +840,10 @@ namespace Graph { eccentricity(g,ecc); } + freq_ecc.resize(*(std::max_element(ecc.begin(), ecc.end())) + 1); + //compute diameter of each vertex for(int i = 0; i < ecc.size(); i++){ - if(ecc[i] > freq_ecc.size() ){ - freq_ecc.resize(ecc[i] + 1); //because vector numbering starts at 0 - } freq_ecc[ecc[i]]++; //add to tally for this diameter size } //printf("Graph diameter is %d\n", freq_ecc.size()-1); From 32f54808c5814f8a455902441f169a1d82f44a78 Mon Sep 17 00:00:00 2001 From: Jonathan Schrock Date: Fri, 19 Jul 2013 17:23:50 -0400 Subject: [PATCH 35/73] Added powerlaw and delta hyperbolicity to graph_stats.cpp --- util/src/graph_stats.cpp | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/util/src/graph_stats.cpp b/util/src/graph_stats.cpp index 1501097..b76b9ee 100644 --- a/util/src/graph_stats.cpp +++ b/util/src/graph_stats.cpp @@ -45,7 +45,7 @@ void print_time(string prefix, ORB_t start, ORB_t end){ cout << prefix + ": " << ORB_seconds(end, start) << endl; } -const string allowed_methods ("edge_density,avg_degree,degree_dist,global_cc,avg_cc,local_ccs,shortest_paths,assortativity,eccentricity,eccentricity_dist,expansion,avg_shortest_path,shortest_paths_boost,eigen_spectrum,k_cores,degeneracy"); +const string allowed_methods ("edge_density,avg_degree,degree_dist,global_cc,avg_cc,local_ccs,shortest_paths,assortativity,eccentricity,eccentricity_dist,expansion,avg_shortest_path,shortest_paths_boost,eigen_spectrum,k_cores,degeneracy,powerlaw,delta_hyperbolicity"); /** * Creates a map from a comma-separated string @@ -165,6 +165,9 @@ int main(int argc, char **argv){ int degeneracy; vector k_cores; double avg_path_length; + int xmin; + double alpha, KS, max_delta; + vector > delta; vector< vector > shortest_path_distances; @@ -270,7 +273,7 @@ int main(int argc, char **argv){ print_time("Time(shortest_paths_dijkstra_boost)", t1, t2); } #else - cerr << "Error: BOOST support was not compiled, cannot run shortest_paths_boost" << endl; + cerr << "Error: BOOST support was not compiled, cannot run shortest_paths_boost" << endl; #endif if(req_methods["eccentricity"] == true){ @@ -328,6 +331,30 @@ int main(int argc, char **argv){ outfile << "\n"; } #endif // ifdef HAS_PETSC + if(req_methods["powerlaw"] == true){ + cout << "Calculating power law parameters" << endl; + ORB_read(t1); + gp.powerlaw(&g, xmin, alpha, KS); + ORB_read(t2); + + print_time("Time(powerlaw)", t1, t2); + outfile << "powerlaw " << xmin << " " << alpha << " " << KS << endl; + } + if(req_methods["delta_hyperbolicity"] == true){ + cout << "Calculating delta hyperbolicity" << endl; + ORB_read(t1); + gp.delta_hyperbolicity(&g, max_delta, delta); + ORB_read(t2); + + print_time("Time(delta_hyperbolicity)", t1, t2); + outfile << "delta_hyperbolicity " << max_delta << endl; + for(int idx = 0; idx < delta.size(); idx++){ + for(int jdx = 0; jdx < delta[i].size(); jdx++){ + outfile << delta[i][j] << " "; + } + outfile << endl; + } + } outfile.close(); From 83eec4b70401af999603f3b785d4ca599c7ed8e2 Mon Sep 17 00:00:00 2001 From: Blair Sullivan Date: Mon, 22 Jul 2013 14:48:31 -0400 Subject: [PATCH 36/73] Fixing boost_graph not wrapped in ifdef and moving betweenness variable outside ifdef region in header. --- lib_graphd/inc/Graph.h | 3 ++- lib_graphd/src/Graph.cpp | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lib_graphd/inc/Graph.h b/lib_graphd/inc/Graph.h index 99b9008..059fde7 100644 --- a/lib_graphd/inc/Graph.h +++ b/lib_graphd/inc/Graph.h @@ -84,9 +84,10 @@ namespace Graph { vector adj_vec; vector< vector > apsp_dist; + // Currently this is only calculated if you have Boost. + vector betweenness; #ifdef HAS_BOOST BoostUndirected *boost_graph; - vector betweenness; #endif //HAS_BOOST #ifdef HAS_PETSC diff --git a/lib_graphd/src/Graph.cpp b/lib_graphd/src/Graph.cpp index da68e67..15f6691 100644 --- a/lib_graphd/src/Graph.cpp +++ b/lib_graphd/src/Graph.cpp @@ -39,7 +39,9 @@ namespace Graph { this->simple = true; //FIXME: check if this is correct behavior this->canonical = true; this->key = 0; + #ifdef HAS_BOOST this->boost_graph = NULL; + #endif } Graph::Graph(int n){ @@ -53,7 +55,9 @@ namespace Graph { nodes[i].set_label(i + 1); } this->next_label = n + 1; + #ifdef HAS_BOOST this->boost_graph = NULL; + #endif } Graph::~Graph(){ From 75255827a1ac7c0ca6341d356454c9991066ad87 Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Tue, 23 Jul 2013 09:48:39 -0400 Subject: [PATCH 37/73] Fixing METIS+ no OpenMP compilation --- lib_graphd/inc/Graph.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib_graphd/inc/Graph.h b/lib_graphd/inc/Graph.h index 7760825..eb4a5d9 100644 --- a/lib_graphd/inc/Graph.h +++ b/lib_graphd/inc/Graph.h @@ -25,10 +25,10 @@ #ifdef _OPENMP #include #else - #ifndef HAS_METIS - #define omp_get_num_threads() 1 - #define omp_get_thread_num() 0 - #endif + #ifndef HAS_METIS + #define omp_get_num_threads() 1 + #define omp_get_thread_num() 0 + #endif #endif #ifdef HAS_PETSC From 6c276efad9666951cd7891aeacb8dad3f4f1c539 Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Tue, 23 Jul 2013 12:06:06 -0400 Subject: [PATCH 38/73] Fix compile issue in graph_stats --- util/src/graph_stats.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/util/src/graph_stats.cpp b/util/src/graph_stats.cpp index dbc8db5..7a56384 100644 --- a/util/src/graph_stats.cpp +++ b/util/src/graph_stats.cpp @@ -368,8 +368,8 @@ int main(int argc, char **argv){ print_time("Time(delta_hyperbolicity)", t1, t2); outfile << "delta_hyperbolicity " << max_delta << endl; for(int idx = 0; idx < delta.size(); idx++){ - for(int jdx = 0; jdx < delta[i].size(); jdx++){ - outfile << delta[i][j] << " "; + for(int jdx = 0; jdx < delta[idx].size(); jdx++){ + outfile << delta[idx][jdx] << " "; } outfile << endl; } From 38c95ddcb23ac635cdd65c7cb5a9714b3aaf4fe3 Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Tue, 23 Jul 2013 15:56:11 -0400 Subject: [PATCH 39/73] Added some conditional defines to enable gtest and boost to co-exist in relative peace and tranquility --- lib_graphd/inc/GraphDecomposition.h | 8 +++++++- lib_graphd/inc/GraphProperties.h | 3 +++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/lib_graphd/inc/GraphDecomposition.h b/lib_graphd/inc/GraphDecomposition.h index aa059b4..8550893 100644 --- a/lib_graphd/inc/GraphDecomposition.h +++ b/lib_graphd/inc/GraphDecomposition.h @@ -47,7 +47,13 @@ #include #include -#include +#ifdef HAS_BOOST + #ifdef HAS_GTEST + #define GTEST_HAS_TR1_TUPLE 0 + #endif + #include +#endif + #include #include diff --git a/lib_graphd/inc/GraphProperties.h b/lib_graphd/inc/GraphProperties.h index 61b1686..412df36 100644 --- a/lib_graphd/inc/GraphProperties.h +++ b/lib_graphd/inc/GraphProperties.h @@ -24,6 +24,9 @@ #include "GraphDecomposition.h" #ifdef HAS_BOOST + #ifdef HAS_GTEST + #define GTEST_HAS_TR1_TUPLE 0 + #endif #include "boost/graph/adjacency_list.hpp" #include "boost/graph/topological_sort.hpp" #include "boost/graph/betweenness_centrality.hpp" From 4b0c72df12486be9c278d230bad79ad73697d374 Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Wed, 24 Jul 2013 09:29:57 -0400 Subject: [PATCH 40/73] Fixing GraphReaderTest - gtest apparently really likes pointers to be passed around instead of objects --- lib_graphd/test/GraphReaderTest.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib_graphd/test/GraphReaderTest.cpp b/lib_graphd/test/GraphReaderTest.cpp index 1bb6122..a630334 100644 --- a/lib_graphd/test/GraphReaderTest.cpp +++ b/lib_graphd/test/GraphReaderTest.cpp @@ -30,11 +30,12 @@ using namespace std; class GraphReaderTest : public testing::Test { public: Graph::GraphReader gr; -Graph::Graph g; +Graph::Graph *g; virtual void SetUp(){ + g = new Graph::Graph(); LOG_INIT("test.log", NULL, 0); - gr.read_graph(&g, string("data/1dc.128.txt"), string("DIMACS"), false ); + gr.read_graph(g, string("data/1dc.128.txt"), string("DIMACS"), false ); } virtual void TearDown(){ @@ -44,19 +45,20 @@ virtual void TearDown(){ TEST_F(GraphReaderTest, testCapacity) { - EXPECT_EQ(128, g.get_capacity()); + int capacity = g->get_capacity(); + EXPECT_EQ(128, capacity); } TEST_F(GraphReaderTest, testNumEdges) { - EXPECT_EQ(1471, g.get_num_edges()); + EXPECT_EQ(1471, g->get_num_edges()); } TEST_F(GraphReaderTest, testNodeNbrs) { vector n; int i; - n = g.get_nodes(); + n = g->get_nodes(); EXPECT_EQ(128, n.size()); From 076d2da90ad0553c39d8e79fae226d57a1b91fa2 Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Wed, 24 Jul 2013 09:30:38 -0400 Subject: [PATCH 41/73] Build C++ tests using CXXFLAGS instead of CFLAGS --- lib_graphd/test/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib_graphd/test/Makefile b/lib_graphd/test/Makefile index 739a5f1..d1773c6 100644 --- a/lib_graphd/test/Makefile +++ b/lib_graphd/test/Makefile @@ -29,7 +29,7 @@ include ../../make.inc CXXFLAGS = $(INCLUDES) -g INCLUDES = -I../inc -I. -I.. $(METIS_INCLUDES) $(SSPARSE_INCDIR) $(PARMETIS_INCDIR) -LIBDIR= -L. -L.. $(METIS_LIB_DIR) $(SSPARSE_LIB) -L../lib $(INDDGO_LIB) $(MPILIB_DIR) +LIBDIR= -L. -L.. -L$(METIS_LIB_DIR) $(SSPARSE_LIB) -L../lib $(INDDGO_LIB) $(MPILIB_DIR) LIB= $(MPILIBS) -lpthread -lgraphd -lgtest -lgtest_main $(METIS_LIB) LFLAGS = $(CFLAGS) @@ -67,7 +67,7 @@ bin: mkdir -p bin .cpp.o: - $(CXX) $(INCLUDES) $(CFLAGS) -O0 -c $< + $(CXX) $(INCLUDES) $(CXXFLAGS) -O0 -c $< bin/testDimacsReader: DIMACSReaderTest.o ${CXX} ${LFLAGS} -o $@ $< ${INCLUDES} $(LIBDIR) $(LIB) From dd7b690fdd258f5d0dc819984cebb03cab82832a Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Wed, 24 Jul 2013 09:30:55 -0400 Subject: [PATCH 42/73] Adding unit tests for clustering, based on results from networx --- lib_graphd/test/GraphPropertyTest.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib_graphd/test/GraphPropertyTest.cpp b/lib_graphd/test/GraphPropertyTest.cpp index 1300cda..4f16dd7 100644 --- a/lib_graphd/test/GraphPropertyTest.cpp +++ b/lib_graphd/test/GraphPropertyTest.cpp @@ -19,6 +19,8 @@ */ +#define GTEST_HAS_TR1_TUPLE 0 + #include #include "Log.h" @@ -204,3 +206,14 @@ TEST_F(GraphPropertyTest, testDeltaHyperbolicity){ EXPECT_LT(abs(1.0 - max_delta), 0.1); EXPECT_LT(abs(126.0 - delta[1][3]), 0.1); } + +TEST_F(GraphPropertyTest, testClustering){ + double global_cc; + double avg_cc; + vector local_ccs; + + properties.clustering_coefficients(mg, global_cc, avg_cc, local_ccs); + EXPECT_NEAR(0.56209150326797386, local_ccs[32], 0.0000001); + EXPECT_NEAR(0.491997272348, avg_cc, 0.00000001); + EXPECT_NEAR(0.460570029725, global_cc, 0.0000001); +} From 47e8acfb4e198533643455d1a074118f38b45a95 Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Wed, 24 Jul 2013 09:47:24 -0400 Subject: [PATCH 43/73] Cleaning up code --- lib_graphd/inc/GraphDecomposition.h | 9 ++++----- lib_graphd/inc/GraphProperties.h | 6 +++--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/lib_graphd/inc/GraphDecomposition.h b/lib_graphd/inc/GraphDecomposition.h index 8550893..eda7509 100644 --- a/lib_graphd/inc/GraphDecomposition.h +++ b/lib_graphd/inc/GraphDecomposition.h @@ -48,13 +48,12 @@ #include #ifdef HAS_BOOST - #ifdef HAS_GTEST - #define GTEST_HAS_TR1_TUPLE 0 - #endif - #include + #ifdef HAS_GTEST + #define GTEST_HAS_TR1_TUPLE 0 + #endif + #include #endif - #include #include #include diff --git a/lib_graphd/inc/GraphProperties.h b/lib_graphd/inc/GraphProperties.h index 412df36..9dc94eb 100644 --- a/lib_graphd/inc/GraphProperties.h +++ b/lib_graphd/inc/GraphProperties.h @@ -24,9 +24,9 @@ #include "GraphDecomposition.h" #ifdef HAS_BOOST - #ifdef HAS_GTEST - #define GTEST_HAS_TR1_TUPLE 0 - #endif + #ifdef HAS_GTEST + #define GTEST_HAS_TR1_TUPLE 0 + #endif #include "boost/graph/adjacency_list.hpp" #include "boost/graph/topological_sort.hpp" #include "boost/graph/betweenness_centrality.hpp" From 55315b55ea566f408c274af0f34ec8b1f520ff95 Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Wed, 24 Jul 2013 10:24:15 -0400 Subject: [PATCH 44/73] Fixing makefile to rebuild tests if libgraphd.a changed --- lib_graphd/test/Makefile | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/lib_graphd/test/Makefile b/lib_graphd/test/Makefile index d1773c6..69ba046 100644 --- a/lib_graphd/test/Makefile +++ b/lib_graphd/test/Makefile @@ -69,56 +69,56 @@ bin: .cpp.o: $(CXX) $(INCLUDES) $(CXXFLAGS) -O0 -c $< -bin/testDimacsReader: DIMACSReaderTest.o +bin/testDimacsReader: DIMACSReaderTest.o $(INDDGO_LIB_DIR)/libgraphd.a ${CXX} ${LFLAGS} -o $@ $< ${INCLUDES} $(LIBDIR) $(LIB) -bin/testGraphReader: GraphReaderTest.o +bin/testGraphReader: GraphReaderTest.o $(INDDGO_LIB_DIR)/libgraphd.a ${CXX} ${LFLAGS} -o $@ $< ${INCLUDES} $(LIBDIR) $(LIB) -bin/testGraphCreatorFile: GraphCreatorFileTest.o +bin/testGraphCreatorFile: GraphCreatorFileTest.o $(INDDGO_LIB_DIR)/libgraphd.a ${CXX} ${LFLAGS} -o $@ $< ${INCLUDES} $(LIBDIR) $(LIB) -bin/testGraph: GraphTest.o +bin/testGraph: GraphTest.o $(INDDGO_LIB_DIR)/libgraphd.a ${CXX} ${LFLAGS} -o $@ $< ${INCLUDES} $(LIBDIR) $(LIB) -bin/testWeightedGraph: WeightedGraphTest.o +bin/testWeightedGraph: WeightedGraphTest.o $(INDDGO_LIB_DIR)/libgraphd.a ${CXX} ${LFLAGS} -o $@ $< ${INCLUDES} $(LIBDIR) $(LIB) -bin/testMutableGraph: MutableGraphTest.o +bin/testMutableGraph: MutableGraphTest.o $(INDDGO_LIB_DIR)/libgraphd.a ${CXX} ${LFLAGS} -o $@ $< ${INCLUDES} $(LIBDIR) $(LIB) -bin/testVertexWeightedGraph: VertexWeightedGraphTest.o +bin/testVertexWeightedGraph: VertexWeightedGraphTest.o $(INDDGO_LIB_DIR)/libgraphd.a ${CXX} ${LFLAGS} -o $@ $< ${INCLUDES} $(LIBDIR) $(LIB) -bin/testAdjMatrixGraphWriter: AdjMatrixGraphWriterTest.o +bin/testAdjMatrixGraphWriter: AdjMatrixGraphWriterTest.o $(INDDGO_LIB_DIR)/libgraphd.a ${CXX} ${LFLAGS} -o $@ $< ${INCLUDES} $(LIBDIR) $(LIB) -bin/testAdjMatrixGraphReader: AdjMatrixGraphReaderTest.o +bin/testAdjMatrixGraphReader: AdjMatrixGraphReaderTest.o $(INDDGO_LIB_DIR)/libgraphd.a ${CXX} ${LFLAGS} -o $@ $< ${INCLUDES} $(LIBDIR) $(LIB) -bin/testDIMACSGraphWriter: DIMACSGraphWriterTest.o +bin/testDIMACSGraphWriter: DIMACSGraphWriterTest.o $(INDDGO_LIB_DIR)/libgraphd.a ${CXX} ${LFLAGS} -o $@ $< ${INCLUDES} $(LIBDIR) $(LIB) -bin/testGraphVizGraphWriter: GraphVizGraphWriterTest.o +bin/testGraphVizGraphWriter: GraphVizGraphWriterTest.o $(INDDGO_LIB_DIR)/libgraphd.a ${CXX} ${LFLAGS} -o $@ $< ${INCLUDES} $(LIBDIR) $(LIB) -bin/testGraphProperty: GraphPropertyTest.o +bin/testGraphProperty: GraphPropertyTest.o $(INDDGO_LIB_DIR)/libgraphd.a ${CXX} ${LFLAGS} -o $@ $< ${INCLUDES} $(LIBDIR) $(LIB) -bin/testGraphUtil: GraphUtilTest.o +bin/testGraphUtil: GraphUtilTest.o $(INDDGO_LIB_DIR)/libgraphd.a ${CXX} ${LFLAGS} -o $@ $< ${INCLUDES} $(LIBDIR) $(LIB) -bin/testMetisGraphWriter: MetisGraphWriterTest.o +bin/testMetisGraphWriter: MetisGraphWriterTest.o $(INDDGO_LIB_DIR)/libgraphd.a ${CXX} ${LFLAGS} -o $@ $< ${INCLUDES} $(LIBDIR) $(LIB) -bin/testMetisGraphReader: MetisGraphReaderTest.o +bin/testMetisGraphReader: MetisGraphReaderTest.o $(INDDGO_LIB_DIR)/libgraphd.a ${CXX} ${LFLAGS} -o $@ $< ${INCLUDES} $(LIBDIR) $(LIB) ifeq ($(HAS_PARMETIS), 1) -bin/testGraphEOUtil: GraphEOUtilTest.o +bin/testGraphEOUtil: GraphEOUtilTest.o $(INDDGO_LIB_DIR)/libgraphd.a ${CXX} ${LFLAGS} -o $@ $< $(PARMETISOBJ) ${INCLUDES} $(LIBDIR) $(LIB) -bin/testParMetis: ParmetisTest.o +bin/testParMetis: ParmetisTest.o $(INDDGO_LIB_DIR)/libgraphd.a ${CXX} ${LFLAGS} -o $@ $^ $(PARMETISOBJ) ${INCLUDES} $(LIBDIR) $(LIB) endif From 9d7da8e3f6e766003a7a180e0ef72a9efe749968 Mon Sep 17 00:00:00 2001 From: Jonathan Schrock Date: Wed, 24 Jul 2013 12:48:31 -0400 Subject: [PATCH 45/73] Added HAS_BOOST wrappers around powerlaw functions. Also, replaced EXPECT_LE with EXPECT_NEAR in several gtests --- lib_graphd/inc/GraphProperties.h | 2 ++ lib_graphd/src/GraphProperties.cpp | 2 ++ lib_graphd/test/GraphPropertyTest.cpp | 32 +++++++++++++-------------- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/lib_graphd/inc/GraphProperties.h b/lib_graphd/inc/GraphProperties.h index 9dc94eb..816ddc8 100644 --- a/lib_graphd/inc/GraphProperties.h +++ b/lib_graphd/inc/GraphProperties.h @@ -149,10 +149,12 @@ namespace Graph { */ void deg_dist(Graph *g, vector &dist); + #ifdef HAS_BOOST /** * \brief Fits the degree distribution of the specified graph to a power law distribution */ void powerlaw(Graph *g, int &xmin, double &alpha, double &KS, double start = 1.5, double inc = 0.01, double end = 3.5); + #endif /** * \brief Returns the degree assortativity coefficient of a graph diff --git a/lib_graphd/src/GraphProperties.cpp b/lib_graphd/src/GraphProperties.cpp index 12eca1f..e0bcb75 100644 --- a/lib_graphd/src/GraphProperties.cpp +++ b/lib_graphd/src/GraphProperties.cpp @@ -1007,6 +1007,7 @@ namespace Graph { } } + #ifdef HAS_BOOST /** * Fits the degree distribution of g to a power law distribution * \param[in] g Pointer to a graph @@ -1128,6 +1129,7 @@ namespace Graph { prev = x[xm]; } } // powerlaw + #endif // ifdef HAS_BOOST /** * Calculates the degree assortativity of a graph g diff --git a/lib_graphd/test/GraphPropertyTest.cpp b/lib_graphd/test/GraphPropertyTest.cpp index 4f16dd7..4156f34 100644 --- a/lib_graphd/test/GraphPropertyTest.cpp +++ b/lib_graphd/test/GraphPropertyTest.cpp @@ -35,6 +35,7 @@ class GraphPropertyTest : public testing::Test public: Graph::GraphCreatorFile creator; Graph::Graph *mg; +Graph::Graph *mg_dis; Graph::GraphProperties properties; virtual void SetUp(){ @@ -43,6 +44,11 @@ virtual void SetUp(){ creator.set_file_name("data/1dc.128.txt"); creator.set_graph_type("DIMACS"); mg = creator.create_mutable_graph(); + + //disconnected graph for testing + creator.set_file_name("data/1et.64.txt"); + creator.set_graph_type("DIMACS"); + mg_dis = creator.create_mutable_graph(); } virtual void TearDown(){ @@ -97,11 +103,7 @@ TEST_F(GraphPropertyTest, testClique) TEST_F(GraphPropertyTest, testIsConnected) { - creator.set_file_name("data/1et.64.txt"); - creator.set_graph_type("DIMACS"); - mg = creator.create_mutable_graph(); - - EXPECT_FALSE(properties.is_connected(mg)); + EXPECT_FALSE(properties.is_connected(mg_dis)); } TEST_F(GraphPropertyTest, testIsIndependentSet) @@ -180,31 +182,29 @@ TEST_F(GraphPropertyTest, testDegDist){ EXPECT_EQ(4, dist[33]); } +#ifdef HAS_BOOST TEST_F(GraphPropertyTest, testPowerLaw){ int xmin; double alpha, KS; properties.powerlaw(mg, xmin, alpha, KS); EXPECT_EQ(18, xmin); - EXPECT_LT(abs(3.5 - alpha), 0.1); - EXPECT_LT(abs(0.470626 - KS), 0.000001); + EXPECT_NEAR(3.5, alpha, 0.1); + EXPECT_NEAR(0.470626, KS, 0.000001); } +#endif // ifdef HAS_BOOST TEST_F(GraphPropertyTest, testDeltaHyperbolicity){ double max_delta; vector > delta; properties.delta_hyperbolicity(mg, max_delta, delta); - EXPECT_LT(abs(2.0 - max_delta), 0.1); - EXPECT_LT(abs(204.0 - delta[3][5]), 0.1); - - creator.set_file_name("data/1et.64.txt"); - creator.set_graph_type("DIMACS"); - mg = creator.create_mutable_graph(); + EXPECT_NEAR(2.0, max_delta, 0.1); + EXPECT_NEAR(204.0, delta[3][5], 0.1); delta.clear(); - properties.delta_hyperbolicity(mg, max_delta, delta); - EXPECT_LT(abs(1.0 - max_delta), 0.1); - EXPECT_LT(abs(126.0 - delta[1][3]), 0.1); + properties.delta_hyperbolicity(mg_dis, max_delta, delta); + EXPECT_NEAR(1.0, max_delta, 0.1); + EXPECT_NEAR(126.0, delta[1][3], 0.1); } TEST_F(GraphPropertyTest, testClustering){ From 9bd7fa354b4f09c582f3b1a29cfb3e76795098bc Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Wed, 24 Jul 2013 12:59:57 -0400 Subject: [PATCH 46/73] A couple more fixes to compile BOOST-y things with gtest --- lib_graphd/inc/GraphCreatorFile.h | 6 ++++++ lib_graphd/test/Makefile | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/lib_graphd/inc/GraphCreatorFile.h b/lib_graphd/inc/GraphCreatorFile.h index 609b173..c67a2b2 100644 --- a/lib_graphd/inc/GraphCreatorFile.h +++ b/lib_graphd/inc/GraphCreatorFile.h @@ -22,6 +22,12 @@ #ifndef GRAPHCREATORFILE_H_ #define GRAPHCREATORFILE_H_ +#ifdef HAS_BOOST + #ifdef HAS_GTEST + #define GTEST_HAS_TR1_TUPLE 0 + #endif +#endif + #include "GraphCreator.h" #include "GraphReader.h" #include diff --git a/lib_graphd/test/Makefile b/lib_graphd/test/Makefile index 69ba046..c3274f7 100644 --- a/lib_graphd/test/Makefile +++ b/lib_graphd/test/Makefile @@ -26,12 +26,12 @@ include ../../make.inc #----------------------------------------------------------------------------- # To build the test library -CXXFLAGS = $(INCLUDES) -g +CXXFLAGS := $(CFLAGS) -DHAS_GTEST -g INCLUDES = -I../inc -I. -I.. $(METIS_INCLUDES) $(SSPARSE_INCDIR) $(PARMETIS_INCDIR) LIBDIR= -L. -L.. -L$(METIS_LIB_DIR) $(SSPARSE_LIB) -L../lib $(INDDGO_LIB) $(MPILIB_DIR) LIB= $(MPILIBS) -lpthread -lgraphd -lgtest -lgtest_main $(METIS_LIB) -LFLAGS = $(CFLAGS) +LFLAGS = $(CXXFLAGS) #----changes are below this line---------------------------------------------- From e80d23abb9e4eef63105168b36c5ac8d8c6ad4bf Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Wed, 24 Jul 2013 13:03:43 -0400 Subject: [PATCH 47/73] Protect powerlaw call in graph_stats with #ifdef; clean GraphProperties code --- lib_graphd/src/GraphProperties.cpp | 1 + util/src/graph_stats.cpp | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/lib_graphd/src/GraphProperties.cpp b/lib_graphd/src/GraphProperties.cpp index e0bcb75..20d28fe 100644 --- a/lib_graphd/src/GraphProperties.cpp +++ b/lib_graphd/src/GraphProperties.cpp @@ -1129,6 +1129,7 @@ namespace Graph { prev = x[xm]; } } // powerlaw + #endif // ifdef HAS_BOOST /** diff --git a/util/src/graph_stats.cpp b/util/src/graph_stats.cpp index 7a56384..989e676 100644 --- a/util/src/graph_stats.cpp +++ b/util/src/graph_stats.cpp @@ -350,6 +350,7 @@ int main(int argc, char **argv){ } #endif // ifdef HAS_PETSC + #ifdef HAS_BOOST if(req_methods["powerlaw"] == true){ cout << "Calculating power law parameters" << endl; ORB_read(t1); @@ -359,6 +360,9 @@ int main(int argc, char **argv){ print_time("Time(powerlaw)", t1, t2); outfile << "powerlaw " << xmin << " " << alpha << " " << KS << endl; } + #else + cerr << "Error: BOOST support was not compiled, cannot run shortest_paths_boost or betweenness" << endl; + #endif //HAS_BOOST if(req_methods["delta_hyperbolicity"] == true){ cout << "Calculating delta hyperbolicity" << endl; ORB_read(t1); From 125383790df88ce68ba412a60023a04fd472a5d8 Mon Sep 17 00:00:00 2001 From: Matthew Baker Date: Tue, 27 Aug 2013 12:38:56 -0400 Subject: [PATCH 48/73] Add a -a option to append stats to an existing file. --- util/src/graph_stats.cpp | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/util/src/graph_stats.cpp b/util/src/graph_stats.cpp index 989e676..69b2837 100644 --- a/util/src/graph_stats.cpp +++ b/util/src/graph_stats.cpp @@ -76,9 +76,9 @@ void print_usage(char **argv){ * \param[out] methods list of methods we want to run. Valid values currently: edge_density,avg_degree,degree_dist,global_cc, avg_cc, local_ccs */ -int parse_options(int argc, char **argv, string& infile, string& intype, string& outfilename, string &outprefix, std::map& methods, int *spectrum_spread){ +int parse_options(int argc, char **argv, string& infile, string& intype, string& outfilename, string &outprefix, std::map& methods, int *spectrum_spread, int *file_append){ int flags, opt; - while((opt = getopt(argc, argv, "hi:t:o:m:p:s:")) != -1){ + while((opt = getopt(argc, argv, "hi:t:o:m:p:s:a")) != -1){ switch(opt){ case 'h': print_usage(argv); @@ -99,9 +99,12 @@ int parse_options(int argc, char **argv, string& infile, string& intype, string& create_map(optarg, methods); break; case 's': - cout << "optarg=" << optarg << endl; + //cout << "optarg=" << optarg << endl; *spectrum_spread = atoi(optarg); break; + case 'a': + *file_append = 1; + break; } } @@ -118,8 +121,9 @@ int main(int argc, char **argv){ std::map val_methods; ORB_t t1, t2; int spectrum_spread = 0; + int file_append = 0; create_map(allowed_methods, val_methods); - parse_options(argc, argv, infile, intype, outfilename, outprefix, req_methods, &spectrum_spread); + parse_options(argc, argv, infile, intype, outfilename, outprefix, req_methods, &spectrum_spread, &file_append); if(outprefix.length() == 0){ outprefix = infile; } @@ -131,6 +135,12 @@ int main(int argc, char **argv){ cout << "Input file: " << infile << endl; cout << "Input type: " << intype << endl; cout << "Output file: " << outfilename << endl; + cout << "Appending : "; + if(file_append == 0) { + cout << "fasle" << endl; + } else { + cout << "true" << endl; + } cout << "Methods :"; for(map::iterator it = req_methods.begin(); it != req_methods.end(); ++it){ cout << " " << it->first; @@ -172,7 +182,11 @@ int main(int argc, char **argv){ vector< vector > shortest_path_distances; - outfile.open(outfilename.c_str()); + if(file_append == 0) { + outfile.open(outfilename.c_str()); + } else { + outfile.open(outfilename.c_str(), ios_base::out|ios_base::app); + } if(!outfile.is_open()){ cerr << "Error opening " << outfilename << " for writing, exiting" << endl; exit(1); @@ -186,9 +200,11 @@ int main(int argc, char **argv){ ORB_read(t2); print_time("Time(make_simple)", t1, t2); - outfile << "filename" << infile << endl; - outfile << "num_nodes " << g.get_num_nodes() << endl; - outfile << "num_edges " << g.get_num_edges() << endl; + if(outfile.tellp() == 0) { + outfile << "filename" << infile << endl; + outfile << "num_nodes " << g.get_num_nodes() << endl; + outfile << "num_edges " << g.get_num_edges() << endl; + } if(req_methods["edge_density"] == true){ cout << "Calculating edge density" << endl; From 2ee644c29230346cd3f21e79e347dda2993307ca Mon Sep 17 00:00:00 2001 From: Matthew Baker Date: Tue, 27 Aug 2013 13:26:09 -0400 Subject: [PATCH 49/73] Merge remote-tracking branches 'upstream/master' and 'origin' From 0c60eeb37879411517238fcfbb25188d0790eaf8 Mon Sep 17 00:00:00 2001 From: Matthew Baker Date: Tue, 27 Aug 2013 13:30:21 -0400 Subject: [PATCH 50/73] remove random debug line that should have been removed long ago --- util/src/graph_stats.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/util/src/graph_stats.cpp b/util/src/graph_stats.cpp index 69b2837..e41df7a 100644 --- a/util/src/graph_stats.cpp +++ b/util/src/graph_stats.cpp @@ -99,7 +99,6 @@ int parse_options(int argc, char **argv, string& infile, string& intype, string& create_map(optarg, methods); break; case 's': - //cout << "optarg=" << optarg << endl; *spectrum_spread = atoi(optarg); break; case 'a': From 6589c373c6c61af972bc1814038167b6840e8e13 Mon Sep 17 00:00:00 2001 From: Matthew Baker Date: Tue, 27 Aug 2013 14:06:10 -0400 Subject: [PATCH 51/73] Fixing type on string --- util/src/graph_stats.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/src/graph_stats.cpp b/util/src/graph_stats.cpp index e41df7a..2e1936b 100644 --- a/util/src/graph_stats.cpp +++ b/util/src/graph_stats.cpp @@ -136,7 +136,7 @@ int main(int argc, char **argv){ cout << "Output file: " << outfilename << endl; cout << "Appending : "; if(file_append == 0) { - cout << "fasle" << endl; + cout << "false" << endl; } else { cout << "true" << endl; } From da0a92b4c2ee8b9eed1615305b9796b9e2a43969 Mon Sep 17 00:00:00 2001 From: "tdgoodrich@gmail.com" Date: Wed, 31 Jul 2013 11:52:27 -0400 Subject: [PATCH 52/73] Revised random number generator initialization for speedup. Added R-MAT and RIG generators to GraphCreator. --- lib_graphd/inc/GraphCreator.h | 3 + lib_graphd/inc/RndNumGen.h | 1 + lib_graphd/src/GraphCreator.cpp | 100 ++++++++++++++++++++++++++++++++ lib_graphd/src/RndNumGen.cpp | 12 ++++ 4 files changed, 116 insertions(+) diff --git a/lib_graphd/inc/GraphCreator.h b/lib_graphd/inc/GraphCreator.h index 3984e07..e6cfd0b 100644 --- a/lib_graphd/inc/GraphCreator.h +++ b/lib_graphd/inc/GraphCreator.h @@ -33,6 +33,9 @@ namespace Graph { public: virtual VertexWeightedGraph *create_random_edge_subgraph(VertexWeightedGraph *wmg, int percent_edges); virtual VertexWeightedGraph *initialize_ktree(int n, int tw); + virtual Graph *initialize_rig(int n, int seed, list *probs); + virtual Graph *initialize_rmat(int l, int m, double *probs, int seed, bool self_loop); + // Creates the induced subgraph on the given list of vertices (by position in adj_list). // Does not check connectedness. Caller must allocate space for the graph G. virtual VertexWeightedGraph *create_induced_subgraph(VertexWeightedGraph *wmg, list *members, bool make_simple); diff --git a/lib_graphd/inc/RndNumGen.h b/lib_graphd/inc/RndNumGen.h index 6fc9686..9ccee69 100644 --- a/lib_graphd/inc/RndNumGen.h +++ b/lib_graphd/inc/RndNumGen.h @@ -23,6 +23,7 @@ #define RNDNUMGEN_H_ namespace Graph { + void init_lcgrand(int stream, int seed); double lcgrand(int stream); void random_permutation(int *perm, int n); int rand_int(int min, int max); diff --git a/lib_graphd/src/GraphCreator.cpp b/lib_graphd/src/GraphCreator.cpp index d6d29f9..18eabf6 100644 --- a/lib_graphd/src/GraphCreator.cpp +++ b/lib_graphd/src/GraphCreator.cpp @@ -29,6 +29,106 @@ namespace Graph { GraphCreator::GraphCreator(){ } + /** + * Initialization of an R-MAT graph with 2^l vertices and <= m edges. + * Four probabilities in *probs used for quadrants, must sum to 1. + * lc rng initialized with seed. Setting self_loop true throws another + * edge if a self loop occurs. + */ + Graph *GraphCreator::initialize_rmat(int l, int m, double *probs, int seed, bool self_loop) { + try { + //check neighborhood to account for float errors + if(probs[0]+probs[1]+probs[2]+probs[3] > 1.001 || probs[0]+probs[1]+probs[2]+probs[3] < 0.999) { + fatal_error("initialize_rmat: Probabilities did not sum to 1: %f, %f, %f, %f", probs[0], probs[1], probs[2], probs[3]); + } + } catch(...) { + fatal_error("initialize_rmat: Error occured when checking probabilities"); + } + + //set up quadrants + const double q1 = probs[0]; + const double q2 = probs[0] + probs[1]; + const double q3 = probs[0] + probs[1] + probs[2]; + set< pair > edges; + + //set up rng + init_lcgrand(0,seed); + + //throw m edges + for(int i = 0; i < m; i++) { + unsigned long x = 0; + unsigned long y = 0; + for(int j = l-1; j >= 0; j--) { + double r = lcgrand(0); + if(r < q1) { + } else if(r < q2) { + x += pow(2,j); + } else if(r < q3) { + y += pow(2,j); + } else { + x += pow(2,j); + y += pow(2,j); + } + } + + //keep edges in order so we don't have a (x,y) and (y,x) duplicate + if(x == y) { + if(self_loop) { + i--; + } + } else if(y > x) { + edges.insert(make_pair(x,y)); + } else { + edges.insert(make_pair(y,x)); + } + } + + Graph *g = new Graph(pow(2,l)); + set< pair >::const_iterator it; + for(it = edges.begin(); it != edges.end(); it++) { + g->add_edge(it->first,it->second); + } + + return g; + } //initialize_rmat + + + /** + * Initialization of a random intersection graph with n vertices, probs->size() attributes, + * with probabilities on the attributes. lc rng initialized with seed. + */ + Graph *GraphCreator::initialize_rig(int n, int seed, list *probs) { + set< pair > edges; + init_lcgrand(0, seed); + + //for all the attributes, construct a clique in G + list::const_iterator it; + for(it = probs->begin(); it != probs->end(); it++) { + //compute which actors have a given attribute + vector connect; + for(unsigned long i = 0; i < n; i++) { + if(lcgrand(0) < *it) { + connect.push_back(i); + } + } + //attach these actors to the graph + for(int i = 0; i < connect.size(); i++) { + for(int j = i + 1; j < connect.size(); j++) { + edges.insert(make_pair(connect[i],connect[j])); + } + } + } + + Graph *g = new Graph(n); + set< pair >::const_iterator edge_it; + for(edge_it = edges.begin(); edge_it != edges.end(); edge_it++) { + g->add_edge(edge_it->first,edge_it->second); + } + + return g; + } //initialize_rig + + /** * Initialization of a k-tree with n vertices. RNG seeded with seed. * mg starts with a clique on vertices 0 through k and iteratively diff --git a/lib_graphd/src/RndNumGen.cpp b/lib_graphd/src/RndNumGen.cpp index deb0b64..8ec6e2c 100644 --- a/lib_graphd/src/RndNumGen.cpp +++ b/lib_graphd/src/RndNumGen.cpp @@ -27,6 +27,7 @@ // A collection of random seeds from Mathematica for the LCG - +static int zrng_count = 300; static long long zrng[] = { 1585898122, 977263903, 1405617513, 992686252, 18121536, 2063068841, 754752318, @@ -86,11 +87,22 @@ static int initialized = 0; #endif namespace Graph { + void init_lcgrand(int stream, int seed) { + if(stream < 0 || stream > zrng_count) { + fatal_error("lcgrand: Stream was %d, must be in range 0-%d", stream, zrng_count-1); + } + zrng[stream] = seed; + } + double lcgrand(int stream){ /// /// A run of the mill LCG. Returns a uniformly distributed double in (0,1). /// + if(stream < 0 || stream > zrng_count) { + fatal_error("lcgrand: Stream was %d, must be in range 0-%d", stream, zrng_count-1); + } + long long zi; #if TD_ADD_ENTROPY // Add a time component to the RNG to get different From 3c62493e488d5b0d4516a6d231c6c18dd4bb6c6b Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Thu, 29 Aug 2013 15:01:32 -0400 Subject: [PATCH 53/73] Fixing code to work with disconnected graphs/take largest components let avg_path_length handle disconnected graphs Fix avg_path_length so it compiles Changes to accomodate getting a largest component from a graph without first writing it to do, or requiring weights Don't try to record number of hops for vertices an infinite distance away correct some output functions Ensure that boost algorithm uses our distance for infinity Add option to graph_stats to record timing to file in addition to stdout cleaning up code --- lib_graphd/inc/Graph.h | 1 + lib_graphd/inc/GraphCreator.h | 8 + lib_graphd/inc/GraphUtil.h | 5 + lib_graphd/inc/Util.h | 4 + lib_graphd/src/Graph.cpp | 4 + lib_graphd/src/GraphCreator.cpp | 205 ++++++++++++++---- lib_graphd/src/GraphProperties.cpp | 16 +- lib_graphd/src/GraphUtil.cpp | 37 ++++ lib_graphd/src/RndNumGen.cpp | 10 +- lib_graphd/src/Util.cpp | 27 +++ util/src/graph_stats.cpp | 326 ++++++++++++++++++----------- 11 files changed, 481 insertions(+), 162 deletions(-) diff --git a/lib_graphd/inc/Graph.h b/lib_graphd/inc/Graph.h index 0518386..99f68d0 100644 --- a/lib_graphd/inc/Graph.h +++ b/lib_graphd/inc/Graph.h @@ -141,6 +141,7 @@ namespace Graph { int get_num_edges() const; int get_num_edges_in_subgraph(list *vertices); int get_num_nodes() const; + int get_num_connected_components() const; vector get_xadj() const; /** \brief get a const ref to the betweenness vector **/ diff --git a/lib_graphd/inc/GraphCreator.h b/lib_graphd/inc/GraphCreator.h index e6cfd0b..c45f1ba 100644 --- a/lib_graphd/inc/GraphCreator.h +++ b/lib_graphd/inc/GraphCreator.h @@ -43,6 +43,14 @@ namespace Graph { // Specialized induced subgraph functionality for components. Sets num_connected_components to 1. virtual VertexWeightedGraph *create_component(VertexWeightedGraph *g, list *members, bool make_simple); + /** + * \brief Create an induced subgraph on g + */ + virtual Graph *create_induced_subgraph(Graph *g, list *members, bool make_simple); + /** + * \brief Create a component graph of g + */ + virtual Graph *create_component(Graph *g, list *members, bool make_simple); // Recursive and non-recursive functions that create all connected components of the graph, // which it places in the given vector diff --git a/lib_graphd/inc/GraphUtil.h b/lib_graphd/inc/GraphUtil.h index ab8c9a3..ba3880a 100644 --- a/lib_graphd/inc/GraphUtil.h +++ b/lib_graphd/inc/GraphUtil.h @@ -104,6 +104,11 @@ namespace Graph { * \brief Releases PetscMat. */ void free_PetscMat(Graph *g); + + /** + * \brief returns a new graph that is the largest component of g + */ + Graph *get_largest_component_graph(Graph *g); }; void create_largestcomponent_graph(char *graph_file, VertexWeightedGraph *&G); diff --git a/lib_graphd/inc/Util.h b/lib_graphd/inc/Util.h index 2fa188c..d88ed4b 100644 --- a/lib_graphd/inc/Util.h +++ b/lib_graphd/inc/Util.h @@ -107,6 +107,10 @@ void write_kcores(string filename, const vector &kcores); */ void write_betweenness(string filename, const vector &bc); +/** + * \brief write a delta hyperbolicity distribution out to a file + */ +void write_delta_hyperbolicity(string filename, const vector< vector > &delta); int_int mylog2(int x); #endif /* UTIL_H_ */ diff --git a/lib_graphd/src/Graph.cpp b/lib_graphd/src/Graph.cpp index be3eb33..9e8586d 100644 --- a/lib_graphd/src/Graph.cpp +++ b/lib_graphd/src/Graph.cpp @@ -164,6 +164,10 @@ namespace Graph { return this->degree[v]; } + int Graph::get_num_connected_components() const { + return this->num_connected_components; + } + /** * \param[in] n number of elements * */ diff --git a/lib_graphd/src/GraphCreator.cpp b/lib_graphd/src/GraphCreator.cpp index 18eabf6..d9ca860 100644 --- a/lib_graphd/src/GraphCreator.cpp +++ b/lib_graphd/src/GraphCreator.cpp @@ -25,25 +25,28 @@ #include "GraphUtil.h" #include "VertexWeightedGraph.h" +#include + namespace Graph { GraphCreator::GraphCreator(){ } /** * Initialization of an R-MAT graph with 2^l vertices and <= m edges. - * Four probabilities in *probs used for quadrants, must sum to 1. + * Four probabilities in *probs used for quadrants, must sum to 1. * lc rng initialized with seed. Setting self_loop true throws another - * edge if a self loop occurs. + * edge if a self loop occurs. */ - Graph *GraphCreator::initialize_rmat(int l, int m, double *probs, int seed, bool self_loop) { + Graph *GraphCreator::initialize_rmat(int l, int m, double *probs, int seed, bool self_loop){ try { - //check neighborhood to account for float errors - if(probs[0]+probs[1]+probs[2]+probs[3] > 1.001 || probs[0]+probs[1]+probs[2]+probs[3] < 0.999) { - fatal_error("initialize_rmat: Probabilities did not sum to 1: %f, %f, %f, %f", probs[0], probs[1], probs[2], probs[3]); - } - } catch(...) { - fatal_error("initialize_rmat: Error occured when checking probabilities"); - } + //check neighborhood to account for float errors + if((probs[0] + probs[1] + probs[2] + probs[3] > 1.001) || (probs[0] + probs[1] + probs[2] + probs[3] < 0.999)){ + fatal_error("initialize_rmat: Probabilities did not sum to 1: %f, %f, %f, %f", probs[0], probs[1], probs[2], probs[3]); + } + } + catch(...){ + fatal_error("initialize_rmat: Error occured when checking probabilities"); + } //set up quadrants const double q1 = probs[0]; @@ -55,65 +58,69 @@ namespace Graph { init_lcgrand(0,seed); //throw m edges - for(int i = 0; i < m; i++) { + for(int i = 0; i < m; i++){ unsigned long x = 0; unsigned long y = 0; - for(int j = l-1; j >= 0; j--) { + for(int j = l - 1; j >= 0; j--){ double r = lcgrand(0); - if(r < q1) { - } else if(r < q2) { + if(r < q1){ + } + else if(r < q2){ x += pow(2,j); - } else if(r < q3) { + } + else if(r < q3){ y += pow(2,j); - } else { + } + else { x += pow(2,j); y += pow(2,j); } } //keep edges in order so we don't have a (x,y) and (y,x) duplicate - if(x == y) { - if(self_loop) { + if(x == y){ + if(self_loop){ i--; } - } else if(y > x) { - edges.insert(make_pair(x,y)); - } else { + } + else if(y > x){ + edges.insert(make_pair(x,y)); + } + else { edges.insert(make_pair(y,x)); } - } + } Graph *g = new Graph(pow(2,l)); set< pair >::const_iterator it; - for(it = edges.begin(); it != edges.end(); it++) { + for(it = edges.begin(); it != edges.end(); it++){ g->add_edge(it->first,it->second); } return g; } //initialize_rmat - /** - * Initialization of a random intersection graph with n vertices, probs->size() attributes, - * with probabilities on the attributes. lc rng initialized with seed. + * Initialization of a random intersection graph with n vertices, probs->size() attributes, + * with probabilities on the attributes. lc rng initialized with seed. */ - Graph *GraphCreator::initialize_rig(int n, int seed, list *probs) { + Graph *GraphCreator::initialize_rig(int n, int seed, list *probs){ set< pair > edges; init_lcgrand(0, seed); //for all the attributes, construct a clique in G list::const_iterator it; - for(it = probs->begin(); it != probs->end(); it++) { + for(it = probs->begin(); it != probs->end(); it++){ //compute which actors have a given attribute vector connect; - for(unsigned long i = 0; i < n; i++) { - if(lcgrand(0) < *it) { + for(unsigned long i = 0; i < n; i++){ + if(lcgrand(0) < *it){ connect.push_back(i); } } //attach these actors to the graph - for(int i = 0; i < connect.size(); i++) { - for(int j = i + 1; j < connect.size(); j++) { + for(int i = 0; i < connect.size(); i++){ + for(int j = i + 1; j < connect.size(); j++){ edges.insert(make_pair(connect[i],connect[j])); } } @@ -121,14 +128,13 @@ namespace Graph { Graph *g = new Graph(n); set< pair >::const_iterator edge_it; - for(edge_it = edges.begin(); edge_it != edges.end(); edge_it++) { - g->add_edge(edge_it->first,edge_it->second); + for(edge_it = edges.begin(); edge_it != edges.end(); edge_it++){ + g->add_edge(edge_it->first,edge_it->second); } return g; } //initialize_rig - /** * Initialization of a k-tree with n vertices. RNG seeded with seed. * mg starts with a clique on vertices 0 through k and iteratively @@ -392,12 +398,141 @@ namespace Graph { VertexWeightedGraph *GraphCreator::create_component(VertexWeightedGraph *g, list *members, bool make_simple){ VertexWeightedGraph *wmg; + cout << typeid(g).name() << endl; wmg = create_induced_subgraph(g, members, make_simple); // Set num_connected_components to 1 since g is known - not verified - should it be?? wmg->num_connected_components = 1; + cout << "create_component called for vwg" << endl; return wmg; } + /** + * Creates a graph G with vertex set equal to the set in the members list. + * The entries in the members list are the positions in the nodes[] array. + * The edges in G are created by constructing the subgraph induced + * by the members list. If make_simple is true, then the resulting graph + * is guaranteed to be simple. + */ + Graph *GraphCreator::create_induced_subgraph(Graph *g, list *members, bool make_simple){ + Graph *wmg = new Graph(members->size()); + // The caller of g function is responsible for allocating a Graph + // of the appropriate size - make sure! + + if(wmg->capacity != (int) (((members->size())))){ + fatal_error( + "%s: Graph of members->size() must be allocated before calling\ncreate_component\n", + __FUNCTION__); + } + + // Sort the members - not necessary, but convenient? + members->sort(); + // Create a subgraph_labels[] array and a graph_indices[] + // array + + int *subgraph_labels = new int[members->size()]; + memset(subgraph_labels, GD_UNDEFINED, members->size() * sizeof(int)); + int *graph_indices = new int[g->capacity]; + memset(graph_indices, GD_UNDEFINED, g->capacity * sizeof(int)); + list::iterator i, j; + int k = 0; + for(i = members->begin(); i != members->end(); ++i){ + subgraph_labels[k] = g->nodes[*i].label; + graph_indices[*i] = k; + k++; + } + + k = 0; + int new_i, new_j; + // Use g for make_simple checking + char *neighbor_vec = new char[g->capacity]; + bool multiple_edges = false; + wmg->num_edges = 0; + for(i = members->begin(); i != members->end(); ++i){ + memset(neighbor_vec, 0, g->capacity * sizeof(char)); + new_i = graph_indices[*i]; + if(new_i == GD_UNDEFINED){ + fatal_error( + "%s: Encountered GD_UNDEFINED entry for new_i at position %d in graph_indices array\n", + __FUNCTION__, *i); + } + + wmg->nodes[new_i].label = subgraph_labels[k]; + for(j = g->nodes[*i].nbrs.begin(); j != g->nodes[*i].nbrs.end(); ++j){ + // We have an edge between *i and *j in the original graph + // g should be stored as an edge between + // graph_indices[*i] and graph_indices[*j] in the subgraph + + new_j = graph_indices[*j]; + print_message(1, "Translating old edge %d-%d to new edge %d-%d\n", + *i, *j, new_i, new_j); + + if(new_j == GD_UNDEFINED){ + print_message( + 1, + "%s: Encountered GD_UNDEFINED entry for new_j at position %d in graph_indices array\n", + __FUNCTION__, *j); + } + else { + if(new_i <= new_j){ + if(!make_simple || (neighbor_vec[*j] == 0) ){ + if(neighbor_vec[*j] == 1){ + // We are adding a duplicate edge to G - G will not be simple + multiple_edges = true; + } + // CSG added make_simple functionality - just check if we have seen g edge before by checking + // the neighbor_vec + wmg->num_edges++; + wmg->nodes[new_i].nbrs.push_back(new_j); + if(new_i != new_j){ // added check Dec 29 + wmg->nodes[new_j].nbrs.push_back(new_i); + } + } + } + } + neighbor_vec[*j] = 1; + } + // k is used for the subgraph labels + k++; + } + // If the original was simple, G will be. If make_simple, then it had better be simple! + // Otherwise, unknown. + if((g->simple == GD_TRUE) || make_simple){ + wmg->simple = GD_TRUE; + } + else { + wmg->simple = false; + wmg->canonical = false; + } + if(multiple_edges){ + wmg->simple = false; + wmg->canonical = false; + } + // We don't know number of components + wmg->num_connected_components = GD_UNDEFINED; + GraphUtil util; + util.recompute_degrees(wmg); + + delete[] subgraph_labels; + delete[] graph_indices; + delete[] neighbor_vec; + + return wmg; + } // create_induced_subgraph + + /** + * Creates the subgraph G induced by the members list where it is known + * that g subgraph is a connected component. Sets G->num_components=1 + * although g is not verified! If make_simple is true, then the component + * is guaranteed to be simple. + */ + Graph *GraphCreator::create_component(Graph *g, list *members, bool make_simple){ + Graph *comp; + comp = create_induced_subgraph(g, members, make_simple); + // Set num_connected_components to 1 since g is known - not verified - should it be?? + comp->num_connected_components = 1; + return comp; + } + /** * Fills the provided list with graphs that correspond to the connected * components of the graph. Sets num_connected_components to the correct value diff --git a/lib_graphd/src/GraphProperties.cpp b/lib_graphd/src/GraphProperties.cpp index 20d28fe..cc1c578 100644 --- a/lib_graphd/src/GraphProperties.cpp +++ b/lib_graphd/src/GraphProperties.cpp @@ -637,7 +637,7 @@ namespace Graph { dists.resize(g->get_num_nodes()); //std::vector d(boost::num_vertices(*bg)); vertex_descriptor s = vertex(source, *bg); - boost::dijkstra_shortest_paths(*bg, s, boost::predecessor_map(&preds[0]).distance_map(&dists[0])); + boost::dijkstra_shortest_paths(*bg, s, boost::predecessor_map(&preds[0]).distance_map(&dists[0]).distance_inf(INDDGO_INFINITY)); int i; //for(i=0;i > short_paths = g->get_shortest_path_dist_ref(); //computes if not already vector hops(n,0); //largest possible dist is n-1 norm_hops.resize(n); + int k; //for each vertex, find the number of vertices reachable for all hops; add to tally for(int i = 0; i < n; i++){ for(int j = 0; j < n; j++){ - hops[ short_paths[i][j] ]++; + k = short_paths[i][j]; + if(k != INDDGO_INFINITY){ + hops[k]++; + } } } @@ -975,17 +979,21 @@ namespace Graph { double sum = 0; double intermediate = 0.0; int i, j; + int inf_path = 0; - #pragma omp parallel for schedule(dynamic, 16) default(none) private(j) reduction(+:sum) + #pragma omp parallel for schedule(dynamic, 16) default(none) private(j) reduction(+:sum,inf_path) for(i = 0; i < n; i++){ for(j = 0; j < n; j++){ if(INDDGO_INFINITY != short_paths[i][j]){ sum += short_paths[i][j]; } + else { + inf_path++; + } } } - sum = sum / (double)(n * (n - 1)); + sum = sum / (double)((n * (n - 1)) - inf_path); pl = sum; } // avg_path_length diff --git a/lib_graphd/src/GraphUtil.cpp b/lib_graphd/src/GraphUtil.cpp index cd09663..6393983 100644 --- a/lib_graphd/src/GraphUtil.cpp +++ b/lib_graphd/src/GraphUtil.cpp @@ -918,6 +918,43 @@ namespace Graph { } return k; } // find_degen + + /** + * \input g input graph + * \output new graph consisting of largest component, or NULL if the input graph is connected + * NOTE: this function *will* canonicalize your graph!!! + **/ + Graph *GraphUtil::get_largest_component_graph(Graph *g){ + GraphProperties properties; + GraphCreatorFile creator; + Graph *largecomp; + list *maxlist = NULL; + size_t maxlen = 0; + + if(!properties.is_connected(g)){ + properties.make_canonical(g); + vector *> members; + vector *>::iterator vlit; + find_all_components(g, &members); + // traverse the list and find the one with the most members + for(vlit = members.begin(); vlit != members.end(); ++vlit){ + cout << "Got list with size: " << ((*vlit)->size()) << endl; + if(((*vlit)->size()) >= maxlen){ + maxlen = (*vlit)->size(); + cout << "New list with maxlen > " << maxlen << endl; + maxlist = *vlit; + cout << maxlist << endl; + } + } + + // found the max component, let's create the graph + largecomp = creator.create_component((Graph *)g, maxlist, true); + return largecomp; + } + else { + return NULL; + } + } // get_largest_component_graph } using namespace std; /** diff --git a/lib_graphd/src/RndNumGen.cpp b/lib_graphd/src/RndNumGen.cpp index 8ec6e2c..96f67c1 100644 --- a/lib_graphd/src/RndNumGen.cpp +++ b/lib_graphd/src/RndNumGen.cpp @@ -87,9 +87,9 @@ static int initialized = 0; #endif namespace Graph { - void init_lcgrand(int stream, int seed) { - if(stream < 0 || stream > zrng_count) { - fatal_error("lcgrand: Stream was %d, must be in range 0-%d", stream, zrng_count-1); + void init_lcgrand(int stream, int seed){ + if((stream < 0) || (stream > zrng_count)){ + fatal_error("lcgrand: Stream was %d, must be in range 0-%d", stream, zrng_count - 1); } zrng[stream] = seed; } @@ -99,8 +99,8 @@ namespace Graph { /// A run of the mill LCG. Returns a uniformly distributed double in (0,1). /// - if(stream < 0 || stream > zrng_count) { - fatal_error("lcgrand: Stream was %d, must be in range 0-%d", stream, zrng_count-1); + if((stream < 0) || (stream > zrng_count)){ + fatal_error("lcgrand: Stream was %d, must be in range 0-%d", stream, zrng_count - 1); } long long zi; diff --git a/lib_graphd/src/Util.cpp b/lib_graphd/src/Util.cpp index 2be89b3..2947a3b 100644 --- a/lib_graphd/src/Util.cpp +++ b/lib_graphd/src/Util.cpp @@ -912,3 +912,30 @@ void write_betweenness(string filename, const vector &bc){ outfile.close(); } // write_betweenness +/** + * Write a delta hyperbolicity vector out to file. + * + * \param[in] filename filename to write output to + * \param[in] bc a vector, indexed on vertex number + */ +void write_delta_hyperbolicity(string filename, const vector< vector > &delta){ + ofstream outfile; + + outfile.open(filename.c_str()); + + if(!outfile.is_open()){ + cerr << "Error opening " << filename << "for writing\n"; + } + else { + outfile.precision(10); + for(int idx = 0; idx < delta.size(); idx++){ + for(int jdx = 0; jdx < delta[idx].size(); jdx++){ + outfile << delta[idx][jdx] << " "; + } + outfile << endl; + } + } + + outfile.close(); +} // write_betweenness + diff --git a/util/src/graph_stats.cpp b/util/src/graph_stats.cpp index 989e676..0099936 100644 --- a/util/src/graph_stats.cpp +++ b/util/src/graph_stats.cpp @@ -41,8 +41,11 @@ using namespace std; -void print_time(string prefix, ORB_t start, ORB_t end){ +void print_time(ofstream &of, string prefix, ORB_t start, ORB_t end){ cout << prefix + ": " << ORB_seconds(end, start) << endl; + if(of.is_open()){ + of << prefix + ": " << ORB_seconds(end, start) << endl; + } } const string allowed_methods ("edge_density,avg_degree,degree_dist,global_cc,avg_cc,local_ccs,shortest_paths,assortativity,eccentricity,eccentricity_dist,expansion,avg_shortest_path,shortest_paths_boost,eigen_spectrum,k_cores,degeneracy,betweenness,powerlaw,delta_hyperbolicity"); @@ -61,7 +64,7 @@ void create_map(string list, map &outmap){ } void print_usage(char **argv){ - cerr << "Usage: " << argv[0] << " [-h] -i infile [-t input-type] [-o outfile] [-p output-prefix] [-m methods] [-s eigen spectrum size]" << endl; + cerr << "Usage: " << argv[0] << " [-h] -i infile [-t input-type] [-o outfile] [-p output-prefix] [-m methods] [-s eigen spectrum size] [-r]" << endl; cerr << "Allowed methods: " << allowed_methods << endl; cerr << "Input type should be one of: edge, adjlist, adjmatrix, dimacs" << endl; } @@ -76,9 +79,9 @@ void print_usage(char **argv){ * \param[out] methods list of methods we want to run. Valid values currently: edge_density,avg_degree,degree_dist,global_cc, avg_cc, local_ccs */ -int parse_options(int argc, char **argv, string& infile, string& intype, string& outfilename, string &outprefix, std::map& methods, int *spectrum_spread){ +int parse_options(int argc, char **argv, string& infile, string& intype, string& outfilename, string &outprefix, std::map& methods, bool& record_timings, int *spectrum_spread){ int flags, opt; - while((opt = getopt(argc, argv, "hi:t:o:m:p:s:")) != -1){ + while((opt = getopt(argc, argv, "hi:t:o:m:p:s:r")) != -1){ switch(opt){ case 'h': print_usage(argv); @@ -98,6 +101,9 @@ int parse_options(int argc, char **argv, string& infile, string& intype, string& case 'm': create_map(optarg, methods); break; + case 'r': + record_timings = true; + break; case 's': cout << "optarg=" << optarg << endl; *spectrum_spread = atoi(optarg); @@ -108,54 +114,11 @@ int parse_options(int argc, char **argv, string& infile, string& intype, string& return 0; } // parse_options -int main(int argc, char **argv){ - string infile; - string outfilename ("graph-stats.txt"); - string outprefix; - ofstream outfile; - string intype ("edge"); - std::map req_methods; - std::map val_methods; - ORB_t t1, t2; - int spectrum_spread = 0; - create_map(allowed_methods, val_methods); - parse_options(argc, argv, infile, intype, outfilename, outprefix, req_methods, &spectrum_spread); - if(outprefix.length() == 0){ - outprefix = infile; - } - - // we'd like higher precision when printing values - std::cout.precision(10); - - cout << "done parsing options" << endl; - cout << "Input file: " << infile << endl; - cout << "Input type: " << intype << endl; - cout << "Output file: " << outfilename << endl; - cout << "Methods :"; - for(map::iterator it = req_methods.begin(); it != req_methods.end(); ++it){ - cout << " " << it->first; - if(val_methods[it->first] != true){ - cerr << "Error: " << it->first << " is not a valid method! " << endl; - } - } - cout << endl; - cout << "Calibrating timers" << endl; - ORB_calibrate(); - - // let's do some calculations - - Graph::Graph g; +void run_all_methods(Graph::Graph *g, ofstream &outfile, ofstream &timing_file, string outprefix, std::map req_methods, int spectrum_spread){ Graph::GraphReader gr; Graph::GraphProperties gp; Graph::GraphUtil gu; - - cout << "Reading graph" << endl; - ORB_read(t1); - if(gr.read_graph(&g, infile, intype, false) == -1){ - exit(1); - } - ORB_read(t2); - print_time("Time(read_graph)", t1, t2); + ORB_t t1, t2; double global_cc, avg_cc, assortativity; @@ -170,48 +133,43 @@ int main(int argc, char **argv){ vector > delta; vector betweenness; - vector< vector > shortest_path_distances; + Graph::Graph *largest_component; - outfile.open(outfilename.c_str()); - if(!outfile.is_open()){ - cerr << "Error opening " << outfilename << " for writing, exiting" << endl; - exit(1); - } - - outfile.precision(16); + vector< vector > shortest_path_distances; cout << "Simplifying graph" << endl; ORB_read(t1); - gp.make_simple(&g); + gp.make_simple(g); ORB_read(t2); - print_time("Time(make_simple)", t1, t2); + print_time(timing_file, "Time(make_simple)", t1, t2); + int num_components = g->get_num_connected_components(); + outfile << "connected_components " << num_components << endl; - outfile << "filename" << infile << endl; - outfile << "num_nodes " << g.get_num_nodes() << endl; - outfile << "num_edges " << g.get_num_edges() << endl; + outfile << "num_nodes " << g->get_num_nodes() << endl; + outfile << "num_edges " << g->get_num_edges() << endl; if(req_methods["edge_density"] == true){ cout << "Calculating edge density" << endl; ORB_read(t1); - gp.edge_density(&g, edge_density); + gp.edge_density(g, edge_density); ORB_read(t2); - print_time("Time(edge_density)", t1, t2); + print_time(timing_file, "Time(edge_density)", t1, t2); outfile << "edge_density " << edge_density << endl; } if(req_methods["avg_degree"] == true){ cout << "Calculating average degree" << endl; ORB_read(t1); - gp.avg_degree(&g, avg_degree); + gp.avg_degree(g, avg_degree); ORB_read(t2); - print_time("Time(average_degree)", t1, t2); + print_time(timing_file, "Time(average_degree)", t1, t2); outfile << "avg_degree " << avg_degree << endl; } if(req_methods["degree_dist"] == true){ cout << "Calculating degree distribution" << endl; ORB_read(t1); - gp.deg_dist(&g, deg_dist); + gp.deg_dist(g, deg_dist); ORB_read(t2); - print_time("Time(degree_distribution)", t1, t2); + print_time(timing_file, "Time(degree_distribution)", t1, t2); string of = outprefix + ".deg_dist"; write_degree_distribution(of, deg_dist); outfile << "degree_distribution " << of << endl; @@ -219,17 +177,17 @@ int main(int argc, char **argv){ if(req_methods["assortativity"] == true){ cout << "Calculating degree assortativity" << endl; ORB_read(t1); - gp.deg_assortativity(&g, assortativity); + gp.deg_assortativity(g, assortativity); ORB_read(t2); - print_time("Time(assortativity)", t1, t2); + print_time(timing_file, "Time(assortativity)", t1, t2); outfile << "assortativity " << assortativity << endl; } if((req_methods["degeneracy"] == true) || (req_methods["k_cores"] == true)){ cout << "Calculating k_cores and degeneracy" << endl; ORB_read(t1); - degeneracy = gu.find_kcore(&g, &k_cores); + degeneracy = gu.find_kcore(g, &k_cores); ORB_read(t2); - print_time("Time(find_kcore)", t1, t2); + print_time(timing_file, "Time(find_kcore)", t1, t2); outfile << "degeneracy " << degeneracy << endl; if(req_methods["k_cores"] == true){ string of = outprefix + ".kcores"; @@ -241,9 +199,9 @@ int main(int argc, char **argv){ if((req_methods["global_cc"] == true) || (req_methods["local_ccs"] == true) || (req_methods["avg_cc"] == true)){ cout << "Calculating clustering coefficients" << endl; ORB_read(t1); - gp.clustering_coefficients(&g, global_cc, avg_cc, local_cc); + gp.clustering_coefficients(g, global_cc, avg_cc, local_cc); ORB_read(t2); - print_time("Time(clustering_coeffecients)", t1, t2); + print_time(timing_file, "Time(clustering_coeffecients)", t1, t2); if(req_methods["global_cc"] == true){ outfile << "global_clustering_coefficient " << global_cc << endl; } @@ -256,70 +214,76 @@ int main(int argc, char **argv){ if(req_methods["shortest_paths"] == true){ cout << "Calculating shortest paths" << endl; ORB_read(t1); - gp.paths_dijkstra_all(&g, shortest_path_distances); + gp.paths_dijkstra_all(g, shortest_path_distances); ORB_read(t2); - print_time("Time(shortest_paths_dijkstra)", t1, t2); + print_time(timing_file, "Time(shortest_paths_dijkstra)", t1, t2); } #ifdef HAS_BOOST if((req_methods["shortest_paths_boost"] == true)){ cout << "Creating BOOST representation of g" << endl; ORB_read(t1); - gu.populate_boost(&g); + gu.populate_boost(g); ORB_read(t2); - print_time("Time(populate_boost)", t1, t2); + print_time(timing_file, "Time(populate_boost)", t1, t2); cout << "Calculating shortest paths (boost)" << endl; ORB_read(t1); - gp.paths_dijkstra_boost_all(&g, shortest_path_distances); + gp.paths_dijkstra_boost_all(g, shortest_path_distances); ORB_read(t2); - print_time("Time(shortest_paths_dijkstra_boost)", t1, t2); + print_time(timing_file, "Time(shortest_paths_dijkstra_boost)", t1, t2); } if(req_methods["betweenness"]){ /* cout << "Creating BOOST representation of g" << endl; ORB_read(t1); - gu.populate_boost(&g); + gu.populate_boost(g); ORB_read(t2); - print_time("Time(populate_boost)", t1, t2); + print_time(timing_file, "Time(populate_boost)", t1, t2); */cout << "Calculating betweeneess centrality" << endl; ORB_read(t1); - gp.betweenness_centrality(&g, betweenness); + gp.betweenness_centrality(g, betweenness); ORB_read(t2); - print_time("Time(betweenness_centrality",t1,t2); + print_time(timing_file, "Time(betweenness_centrality",t1,t2); string of = outprefix + ".betweenness"; outfile << "betweenness_file " << of << endl; - write_betweenness(of, g.get_betweenness_ref()); + write_betweenness(of, g->get_betweenness_ref()); } #else // ifdef HAS_BOOST cerr << "Error: BOOST support was not compiled, cannot run shortest_paths_boost or betweenness" << endl; #endif // ifdef HAS_BOOST - if(req_methods["eccentricity"] == true){ - cout << "Calculating eccentricities" << endl; - ORB_read(t1); - gp.eccentricity(&g, ecc); - ORB_read(t2); - print_time("Time(eccentricity)",t1,t2); + if(num_components == 1){ + if(req_methods["eccentricity"] == true){ + cout << "Calculating eccentricities" << endl; + ORB_read(t1); + gp.eccentricity(g, ecc); + ORB_read(t2); + print_time(timing_file, "Time(eccentricity)",t1,t2); + } + if(req_methods["eccentricity_dist"] == true){ + cout << "Calculating distribution of eccentricities" << endl; + ORB_read(t1); + gp.eccentricity_dist(g, ecc, freq_ecc); + ORB_read(t2); + print_time(timing_file, "Time(eccentricity distribution)",t1,t2); + } } - if(req_methods["eccentricity_dist"] == true){ - cout << "Calculating distribution of eccentricities" << endl; - ORB_read(t1); - gp.eccentricity_dist(&g, ecc, freq_ecc); - ORB_read(t2); - print_time("Time(eccentricity distribution)",t1,t2); + else { + cout << "Graph is disconnected - not calculating eccentricities" << endl; } + if(req_methods["expansion"] == true){ cout << "Calculating normalized expansion (distance distribution) - no self loops allowed" << endl; ORB_read(t1); - gp.expansion(&g, norm_hops); + gp.expansion(g, norm_hops); ORB_read(t2); - print_time("Time(expansion)",t1,t2); + print_time(timing_file, "Time(expansion)",t1,t2); } if(req_methods["avg_shortest_path"] == true){ cout << "Calculating average shortest path length" << endl; ORB_read(t1); - gp.avg_path_length(&g, avg_path_length); + gp.avg_path_length(g, avg_path_length); ORB_read(t2); - print_time("Time(avg_path_length)", t1, t2); + print_time(timing_file, "Time(avg_path_length)", t1, t2); outfile << "avg_path_length " << avg_path_length << endl; } @@ -339,9 +303,9 @@ int main(int argc, char **argv){ cout << "Calculating adjacency matrix eigen spectrum\n"; ORB_read(t1); - gp.eigen_spectrum(&g, eigen_spectrum, spectrum_spread); + gp.eigen_spectrum(g, eigen_spectrum, spectrum_spread); ORB_read(t2); - print_time("Time(eigen spectrum)",t1,t2); + print_time(timing_file, "Time(eigen spectrum)",t1,t2); outfile << "eigen_spectrum "; for(int idx = 0; idx < eigen_spectrum.size(); idx++){ outfile << eigen_spectrum[idx]; @@ -354,30 +318,38 @@ int main(int argc, char **argv){ if(req_methods["powerlaw"] == true){ cout << "Calculating power law parameters" << endl; ORB_read(t1); - gp.powerlaw(&g, xmin, alpha, KS); + gp.powerlaw(g, xmin, alpha, KS); ORB_read(t2); - print_time("Time(powerlaw)", t1, t2); + print_time(timing_file, "Time(powerlaw)", t1, t2); outfile << "powerlaw " << xmin << " " << alpha << " " << KS << endl; } #else cerr << "Error: BOOST support was not compiled, cannot run shortest_paths_boost or betweenness" << endl; #endif //HAS_BOOST - if(req_methods["delta_hyperbolicity"] == true){ - cout << "Calculating delta hyperbolicity" << endl; - ORB_read(t1); - gp.delta_hyperbolicity(&g, max_delta, delta); - ORB_read(t2); - - print_time("Time(delta_hyperbolicity)", t1, t2); - outfile << "delta_hyperbolicity " << max_delta << endl; - for(int idx = 0; idx < delta.size(); idx++){ - for(int jdx = 0; jdx < delta[idx].size(); jdx++){ - outfile << delta[idx][jdx] << " "; - } - outfile << endl; + if(num_components == 1){ + if(req_methods["delta_hyperbolicity"] == true){ + cout << "Calculating delta hyperbolicity" << endl; + ORB_read(t1); + gp.delta_hyperbolicity(g, max_delta, delta); + ORB_read(t2); + + print_time(timing_file, "Time(delta_hyperbolicity)", t1, t2); + //outfile << "delta_hyperbolicity " << max_delta << endl; + //for(int idx = 0; idx < delta.size(); idx++){ + // for(int jdx = 0; jdx < delta[idx].size(); jdx++){ + // outfile << delta[idx][jdx] << " "; + // } + // outfile << endl; + //} + string of = outprefix + ".delta_hyp"; + write_delta_hyperbolicity(of, delta); + outfile << "max_delta_hyperbolicity " << max_delta; } } + else { + cout << "Graph is disconnected - not calculating delta hyperbolicity" << endl; + } outfile.close(); @@ -386,6 +358,124 @@ int main(int argc, char **argv){ #elif HAVE_PETSC PetscFinalize(); #endif +} // run_all_methods + +int main(int argc, char **argv){ + string infile; + string outfilename ("graph-stats.txt"); + string outprefix; + ofstream outfile; + ofstream timing_file; + bool record_timings = false; + string intype ("edge"); + std::map req_methods; + std::map val_methods; + ORB_t t1, t2; + int spectrum_spread = 0; + create_map(allowed_methods, val_methods); + parse_options(argc, argv, infile, intype, outfilename, outprefix, req_methods, record_timings, &spectrum_spread); + if(outprefix.length() == 0){ + outprefix = infile; + } + + // we'd like higher precision when printing values + std::cout.precision(10); + + cout << "done parsing options" << endl; + cout << "Input file: " << infile << endl; + cout << "Input type: " << intype << endl; + cout << "Output file: " << outfilename << endl; + cout << "Methods :"; + for(map::iterator it = req_methods.begin(); it != req_methods.end(); ++it){ + cout << " " << it->first; + if(val_methods[it->first] != true){ + cerr << "Error: " << it->first << " is not a valid method! " << endl; + } + } + cout << endl; + cout << "Calibrating timers" << endl; + ORB_calibrate(); + + // let's do some calculations + + Graph::Graph *g = new(Graph::Graph); + Graph::GraphReader gr; + Graph::GraphProperties gp; + Graph::GraphUtil gu; + + // Set up output streams + outfile.open(outfilename.c_str()); + if(!outfile.is_open()){ + cerr << "Error opening " << outfilename << " for writing, exiting" << endl; + exit(1); + } + if(record_timings){ + string of = outfilename + ".timings"; + timing_file.open(of.c_str()); + if(!timing_file.is_open()){ + cerr << "Error opening " << timing_file << " for writing, exiting" << endl; + exit(1); + } + outfile << "Recording timings to " << of << endl; + } + + // Read in the graph and start recording things to output streams + cout << "Reading graph" << endl; + ORB_read(t1); + if(gr.read_graph(g, infile, intype, false) == -1){ + exit(1); + } + ORB_read(t2); + print_time(timing_file, "Time(read_graph)", t1, t2); + + outfile.precision(16); + outfile << "filename " << infile << endl; + vector components; + cout << "Graph is connected?: " << std::boolalpha << gp.is_connected(g) << endl; + ORB_read(t1); + cout << "GU.label_all_components says: " << gu.label_all_components(g, &components) << endl; + ORB_read(t2); + print_time(timing_file, "Time(label_all_components)", t1, t2); + bool is_connected = gp.is_connected(g); + cout << "Connected components: " << g->get_num_connected_components() << endl; + cout << "Graph is connected?: " << std::boolalpha << is_connected << endl; + + cout << "Creating largest connected component graph" << endl; + run_all_methods(g, outfile, timing_file, outprefix, req_methods, spectrum_spread); + outfile.close(); + timing_file.close(); + + // some algorithms only make sense to run on a connected graph/component + if(not is_connected){ // run everything against the other algorithms + cout << "Graph is not connected, re-running stats on largest connected component" << endl; + outfilename += ".largest_component"; + outfile.open(outfilename.c_str()); + if(!outfile.is_open()){ + cerr << "Error opening " << outfilename << " for writing, exiting" << endl; + exit(1); + } + if(record_timings){ + string of = outfilename + ".timings"; + timing_file.open(of.c_str()); + if(!timing_file.is_open()){ + cerr << "Error opening " << timing_file << " for writing, exiting" << endl; + exit(1); + } + outfile << "Recording timings to " << of << endl; + } + + outprefix = outprefix + ".largest_component"; + + outfile.precision(16); + outfile << "filename" << infile << endl; + Graph::Graph *largest_component = gu.get_largest_component_graph(g); + delete(g); // delete g here to save on memory + + run_all_methods(largest_component, outfile, timing_file, outprefix, req_methods, spectrum_spread); + outfile.close(); + timing_file.close(); + } + exit(0); } // main From 8961b6d67d265d9c4c8e1eb128bfd10ccd64057d Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Thu, 19 Sep 2013 13:14:55 -0400 Subject: [PATCH 54/73] Change deg. dist output to: 'degree value' instead of just 'value' --- lib_graphd/src/GraphUtil.cpp | 6 +++--- lib_graphd/src/Util.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib_graphd/src/GraphUtil.cpp b/lib_graphd/src/GraphUtil.cpp index 6393983..92cb4ca 100644 --- a/lib_graphd/src/GraphUtil.cpp +++ b/lib_graphd/src/GraphUtil.cpp @@ -938,12 +938,12 @@ namespace Graph { find_all_components(g, &members); // traverse the list and find the one with the most members for(vlit = members.begin(); vlit != members.end(); ++vlit){ - cout << "Got list with size: " << ((*vlit)->size()) << endl; + //cout << "Got list with size: " << ((*vlit)->size()) << endl; if(((*vlit)->size()) >= maxlen){ maxlen = (*vlit)->size(); - cout << "New list with maxlen > " << maxlen << endl; + //cout << "New list with maxlen > " << maxlen << endl; maxlist = *vlit; - cout << maxlist << endl; + //cout << maxlist << endl; } } diff --git a/lib_graphd/src/Util.cpp b/lib_graphd/src/Util.cpp index 2947a3b..b677060 100644 --- a/lib_graphd/src/Util.cpp +++ b/lib_graphd/src/Util.cpp @@ -857,7 +857,7 @@ void write_degree_distribution(string filename, const vector &dist){ else { int i; for(i = 0; i < dist.size(); i++){ - outfile << dist[i] << "\n"; + outfile << i << " " << dist[i] << "\n"; } } From d285cf20c199840b31bd279007b0e44614d26b07 Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Fri, 20 Sep 2013 11:05:04 -0400 Subject: [PATCH 55/73] Add APSP matrix output functions --- lib_graphd/inc/Util.h | 5 +++++ lib_graphd/src/Util.cpp | 30 ++++++++++++++++++++++++++++++ util/src/graph_stats.cpp | 4 ++++ 3 files changed, 39 insertions(+) diff --git a/lib_graphd/inc/Util.h b/lib_graphd/inc/Util.h index d88ed4b..9532fa0 100644 --- a/lib_graphd/inc/Util.h +++ b/lib_graphd/inc/Util.h @@ -111,6 +111,11 @@ void write_betweenness(string filename, const vector &bc); * \brief write a delta hyperbolicity distribution out to a file */ void write_delta_hyperbolicity(string filename, const vector< vector > &delta); + +/** + * \brief Write an all pairs shortest path matrix out to file. + */ +void write_apsp_matrix(string filename, vector< vector > &apsp); int_int mylog2(int x); #endif /* UTIL_H_ */ diff --git a/lib_graphd/src/Util.cpp b/lib_graphd/src/Util.cpp index b677060..3bf63e3 100644 --- a/lib_graphd/src/Util.cpp +++ b/lib_graphd/src/Util.cpp @@ -24,6 +24,7 @@ #include #include #include +#include /*BDS - added to get memory highwater mark*/ int parseLine(char *line){ @@ -939,3 +940,32 @@ void write_delta_hyperbolicity(string filename, const vector< vector > & outfile.close(); } // write_betweenness +/** + * Write a all pairs shortest path matrix out to file. + * + * \param[in] filename filename to write output to + * \param[in] apsp a vector< vector >, indexed on vertex number, assumed to be |V|x|V| + */ +void write_apsp_matrix(string filename, vector< vector > &apsp){ + int i; + int n = apsp.size(); //assuming it's sized correctly + cerr << "Writing apsp matrix of size: " << n << endl; + + FILE * outfile; + outfile = fopen(filename.c_str(), "w+"); + + if(!outfile){ + cerr << "Error opening " << filename << "for writing\n"; + } + + fwrite((void *) &n, 1, sizeof(int), outfile); + + //#pragma omp parallel for default(none) share(n, apsp) + int ret; + for(i=0; i< n; i++) { + int * arr = &apsp[i].front(); + fwrite(arr, n, sizeof(int), outfile); + } + + fclose(outfile); +} diff --git a/util/src/graph_stats.cpp b/util/src/graph_stats.cpp index 0099936..cc63a1c 100644 --- a/util/src/graph_stats.cpp +++ b/util/src/graph_stats.cpp @@ -231,6 +231,10 @@ void run_all_methods(Graph::Graph *g, ofstream &outfile, ofstream &timing_file, gp.paths_dijkstra_boost_all(g, shortest_path_distances); ORB_read(t2); print_time(timing_file, "Time(shortest_paths_dijkstra_boost)", t1, t2); + string of = outprefix + ".apsp"; + write_apsp_matrix(of, shortest_path_distances); + ORB_read(t2); + print_time(timing_file, "Time(write_apsp_matrix)", t1, t2); } if(req_methods["betweenness"]){ /* cout << "Creating BOOST representation of g" << endl; From b91b31341dab96b72b8778a43aa2c8865f0ce8ca Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Fri, 20 Sep 2013 14:14:53 -0400 Subject: [PATCH 56/73] add new method to specify writing of apsp matrix --- util/src/graph_stats.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/util/src/graph_stats.cpp b/util/src/graph_stats.cpp index cc63a1c..ddc4cff 100644 --- a/util/src/graph_stats.cpp +++ b/util/src/graph_stats.cpp @@ -48,7 +48,7 @@ void print_time(ofstream &of, string prefix, ORB_t start, ORB_t end){ } } -const string allowed_methods ("edge_density,avg_degree,degree_dist,global_cc,avg_cc,local_ccs,shortest_paths,assortativity,eccentricity,eccentricity_dist,expansion,avg_shortest_path,shortest_paths_boost,eigen_spectrum,k_cores,degeneracy,betweenness,powerlaw,delta_hyperbolicity"); +const string allowed_methods ("edge_density,avg_degree,degree_dist,global_cc,avg_cc,local_ccs,shortest_paths,assortativity,eccentricity,eccentricity_dist,expansion,apsp_output,avg_shortest_path,shortest_paths_boost,eigen_spectrum,k_cores,degeneracy,betweenness,powerlaw,delta_hyperbolicity"); /** * Creates a map from a comma-separated string @@ -231,10 +231,12 @@ void run_all_methods(Graph::Graph *g, ofstream &outfile, ofstream &timing_file, gp.paths_dijkstra_boost_all(g, shortest_path_distances); ORB_read(t2); print_time(timing_file, "Time(shortest_paths_dijkstra_boost)", t1, t2); - string of = outprefix + ".apsp"; - write_apsp_matrix(of, shortest_path_distances); - ORB_read(t2); - print_time(timing_file, "Time(write_apsp_matrix)", t1, t2); + if((req_methods["apsp_output"] == true)){ + string of = outprefix + ".apsp"; + write_apsp_matrix(of, shortest_path_distances); + ORB_read(t2); + print_time(timing_file, "Time(write_apsp_matrix)", t1, t2); + } } if(req_methods["betweenness"]){ /* cout << "Creating BOOST representation of g" << endl; From 7af3ad2d10bd35b4a8410e3e7baee7fb76e169fc Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Fri, 20 Sep 2013 14:35:35 -0400 Subject: [PATCH 57/73] clean-code --- lib_graphd/src/Util.cpp | 9 +++++---- util/src/graph_stats.cpp | 41 ++++++++++++++++++++-------------------- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/lib_graphd/src/Util.cpp b/lib_graphd/src/Util.cpp index 3bf63e3..16cc63e 100644 --- a/lib_graphd/src/Util.cpp +++ b/lib_graphd/src/Util.cpp @@ -951,7 +951,7 @@ void write_apsp_matrix(string filename, vector< vector > &apsp){ int n = apsp.size(); //assuming it's sized correctly cerr << "Writing apsp matrix of size: " << n << endl; - FILE * outfile; + FILE *outfile; outfile = fopen(filename.c_str(), "w+"); if(!outfile){ @@ -962,10 +962,11 @@ void write_apsp_matrix(string filename, vector< vector > &apsp){ //#pragma omp parallel for default(none) share(n, apsp) int ret; - for(i=0; i< n; i++) { - int * arr = &apsp[i].front(); + for(i = 0; i < n; i++){ + int *arr = &apsp[i].front(); fwrite(arr, n, sizeof(int), outfile); } fclose(outfile); -} +} // write_apsp_matrix + diff --git a/util/src/graph_stats.cpp b/util/src/graph_stats.cpp index d7ba137..ccf084a 100644 --- a/util/src/graph_stats.cpp +++ b/util/src/graph_stats.cpp @@ -107,9 +107,9 @@ int parse_options(int argc, char **argv, string& infile, string& intype, string& case 's': *spectrum_spread = atoi(optarg); break; - case 'a': + case 'a': file_append = true; - break; + break; } } @@ -147,7 +147,6 @@ void run_all_methods(Graph::Graph *g, ofstream &outfile, ofstream &timing_file, int num_components = g->get_num_connected_components(); outfile << "connected_components " << num_components << endl; - if(req_methods["edge_density"] == true){ cout << "Calculating edge density" << endl; ORB_read(t1); @@ -380,7 +379,7 @@ int main(int argc, char **argv){ ORB_t t1, t2; int spectrum_spread = 0; create_map(allowed_methods, val_methods); - parse_options(argc, argv, infile, intype, outfilename, outprefix, req_methods, record_timings, file_append, &spectrum_spread) ; + parse_options(argc, argv, infile, intype, outfilename, outprefix, req_methods, record_timings, file_append, &spectrum_spread); if(outprefix.length() == 0){ outprefix = infile; } @@ -413,20 +412,21 @@ int main(int argc, char **argv){ Graph::GraphUtil gu; // Set up output streams - if(file_append == true) { - outfile.open(outfilename.c_str()); - } else { - outfile.open(outfilename.c_str(), ios_base::out|ios_base::app); + if(file_append == true){ + outfile.open(outfilename.c_str()); + } + else { + outfile.open(outfilename.c_str(), ios_base::out | ios_base::app); } if(!outfile.is_open()){ cerr << "Error opening " << outfilename << " for writing, exiting" << endl; exit(1); } - if(outfile.tellp() == 0) { - outfile << "filename" << infile << endl; - outfile << "num_nodes " << g->get_num_nodes() << endl; - outfile << "num_edges " << g->get_num_edges() << endl; + if(outfile.tellp() == 0){ + outfile << "filename" << infile << endl; + outfile << "num_nodes " << g->get_num_nodes() << endl; + outfile << "num_edges " << g->get_num_edges() << endl; } if(record_timings){ @@ -469,19 +469,20 @@ int main(int argc, char **argv){ if(not is_connected){ // run everything against the other algorithms cout << "Graph is not connected, re-running stats on largest connected component" << endl; outfilename += ".largest_component"; - if(file_append == true) { - outfile.open(outfilename.c_str()); - } else { - outfile.open(outfilename.c_str(), ios_base::out|ios_base::app); + if(file_append == true){ + outfile.open(outfilename.c_str()); + } + else { + outfile.open(outfilename.c_str(), ios_base::out | ios_base::app); } if(!outfile.is_open()){ cerr << "Error opening " << outfilename << " for writing, exiting" << endl; exit(1); } - if(outfile.tellp() == 0) { - outfile << "filename " << infile << endl; - outfile << "num_nodes " << g->get_num_nodes() << endl; - outfile << "num_edges " << g->get_num_edges() << endl; + if(outfile.tellp() == 0){ + outfile << "filename " << infile << endl; + outfile << "num_nodes " << g->get_num_nodes() << endl; + outfile << "num_edges " << g->get_num_edges() << endl; } if(record_timings){ string of = outfilename + ".timings"; From fd330bebf1ea6e81c7e1c61f5b51e48eebbfb1e6 Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Fri, 20 Sep 2013 20:36:08 -0400 Subject: [PATCH 58/73] fix my backwards append logic --- util/src/graph_stats.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/util/src/graph_stats.cpp b/util/src/graph_stats.cpp index 1b9d715..2125d70 100644 --- a/util/src/graph_stats.cpp +++ b/util/src/graph_stats.cpp @@ -413,7 +413,7 @@ int main(int argc, char **argv){ Graph::GraphUtil gu; // Set up output streams - if(file_append == true){ + if(file_append == false){ outfile.open(outfilename.c_str()); } else { @@ -432,7 +432,11 @@ int main(int argc, char **argv){ if(record_timings){ string of = outfilename + ".timings"; - timing_file.open(of.c_str()); + if(file_append == false){ + timing_file.open(of.c_str()); + } else { + timing_file.open(of.c_str(), ios_base::out | ios_base::app); + } if(!timing_file.is_open()){ cerr << "Error opening " << timing_file << " for writing, exiting" << endl; exit(1); @@ -470,7 +474,7 @@ int main(int argc, char **argv){ if(not is_connected){ // run everything against the other algorithms cout << "Graph is not connected, re-running stats on largest connected component" << endl; outfilename += ".largest_component"; - if(file_append == true){ + if(file_append == false){ outfile.open(outfilename.c_str()); } else { @@ -487,7 +491,12 @@ int main(int argc, char **argv){ } if(record_timings){ string of = outfilename + ".timings"; - timing_file.open(of.c_str()); + if(file_append == false){ + timing_file.open(of.c_str()); + } else { + timing_file.open(of.c_str(), ios_base::out | ios_base::app); + } + if(!timing_file.is_open()){ cerr << "Error opening " << timing_file << " for writing, exiting" << endl; exit(1); From 2010ac1aa7b37c4d8b2e53a7153da9f16bced42b Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Sat, 21 Sep 2013 16:04:15 -0400 Subject: [PATCH 59/73] default output file stats to outprefix instead of graph-stats.txt --- util/src/graph_stats.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/util/src/graph_stats.cpp b/util/src/graph_stats.cpp index 2125d70..bf9eefa 100644 --- a/util/src/graph_stats.cpp +++ b/util/src/graph_stats.cpp @@ -368,7 +368,7 @@ void run_all_methods(Graph::Graph *g, ofstream &outfile, ofstream &timing_file, int main(int argc, char **argv){ string infile; - string outfilename ("graph-stats.txt"); + string outfilename; string outprefix; ofstream outfile; ofstream timing_file; @@ -381,6 +381,13 @@ int main(int argc, char **argv){ int spectrum_spread = 0; create_map(allowed_methods, val_methods); parse_options(argc, argv, infile, intype, outfilename, outprefix, req_methods, record_timings, file_append, &spectrum_spread); + if(outfilename.length() == 0){ + if(outprefix.length() != 0) { + outfilename = outprefix+".stats"; + } else { + outfilename = "graph-stats.txt"; + } + } if(outprefix.length() == 0){ outprefix = infile; } @@ -425,7 +432,7 @@ int main(int argc, char **argv){ } if(outfile.tellp() == 0){ - outfile << "filename" << infile << endl; + outfile << "filename " << infile << endl; outfile << "num_nodes " << g->get_num_nodes() << endl; outfile << "num_edges " << g->get_num_edges() << endl; } @@ -473,7 +480,7 @@ int main(int argc, char **argv){ // some algorithms only make sense to run on a connected graph/component if(not is_connected){ // run everything against the other algorithms cout << "Graph is not connected, re-running stats on largest connected component" << endl; - outfilename += ".largest_component"; + outfilename = outprefix+".largest_component.stats"; if(file_append == false){ outfile.open(outfilename.c_str()); } From bda62d01c482ba8e5bf5363f1b3bf6de1aad8d6c Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Sat, 21 Sep 2013 16:55:26 -0400 Subject: [PATCH 60/73] write apsp matrix after other stats calculations, and fix its timing --- util/src/graph_stats.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/util/src/graph_stats.cpp b/util/src/graph_stats.cpp index bf9eefa..4844699 100644 --- a/util/src/graph_stats.cpp +++ b/util/src/graph_stats.cpp @@ -231,12 +231,6 @@ void run_all_methods(Graph::Graph *g, ofstream &outfile, ofstream &timing_file, gp.paths_dijkstra_boost_all(g, shortest_path_distances); ORB_read(t2); print_time(timing_file, "Time(shortest_paths_dijkstra_boost)", t1, t2); - if((req_methods["apsp_output"] == true)){ - string of = outprefix + ".apsp"; - write_apsp_matrix(of, shortest_path_distances); - ORB_read(t2); - print_time(timing_file, "Time(write_apsp_matrix)", t1, t2); - } } if(req_methods["betweenness"]){ /* cout << "Creating BOOST representation of g" << endl; @@ -292,6 +286,13 @@ void run_all_methods(Graph::Graph *g, ofstream &outfile, ofstream &timing_file, print_time(timing_file, "Time(avg_path_length)", t1, t2); outfile << "avg_path_length " << avg_path_length << endl; } + if((req_methods["apsp_output"] == true)){ + string of = outprefix + ".apsp"; + ORB_read(t1); + write_apsp_matrix(of, shortest_path_distances); + ORB_read(t2); + print_time(timing_file, "Time(write_apsp_matrix)", t1, t2); + } #ifdef HAS_PETSC if(req_methods["eigen_spectrum"] == true){ From 715854f2d5e54cf08a8e60231fc05dee70c72458 Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Sun, 22 Sep 2013 15:39:14 -0400 Subject: [PATCH 61/73] fix output of nodes and edges --- util/src/graph_stats.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/util/src/graph_stats.cpp b/util/src/graph_stats.cpp index 4844699..bd81538 100644 --- a/util/src/graph_stats.cpp +++ b/util/src/graph_stats.cpp @@ -432,11 +432,6 @@ int main(int argc, char **argv){ exit(1); } - if(outfile.tellp() == 0){ - outfile << "filename " << infile << endl; - outfile << "num_nodes " << g->get_num_nodes() << endl; - outfile << "num_edges " << g->get_num_edges() << endl; - } if(record_timings){ string of = outfilename + ".timings"; @@ -461,8 +456,13 @@ int main(int argc, char **argv){ ORB_read(t2); print_time(timing_file, "Time(read_graph)", t1, t2); + if(outfile.tellp() == 0){ + outfile << "filename " << infile << endl; + outfile << "num_nodes " << g->get_num_nodes() << endl; + outfile << "num_edges " << g->get_num_edges() << endl; + } + outfile.precision(16); - outfile << "filename " << infile << endl; vector components; cout << "Graph is connected?: " << std::boolalpha << gp.is_connected(g) << endl; ORB_read(t1); From 58e01512b93b380d7e7b0714d7b67d12e5cffc16 Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Sun, 22 Sep 2013 15:47:32 -0400 Subject: [PATCH 62/73] fix timing output/node output --- util/src/graph_stats.cpp | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/util/src/graph_stats.cpp b/util/src/graph_stats.cpp index bd81538..d6d628c 100644 --- a/util/src/graph_stats.cpp +++ b/util/src/graph_stats.cpp @@ -433,6 +433,20 @@ int main(int argc, char **argv){ } + // Read in the graph and start recording things to output streams + cout << "Reading graph" << endl; + ORB_read(t1); + if(gr.read_graph(g, infile, intype, false) == -1){ + exit(1); + } + ORB_read(t2); + + if(outfile.tellp() == 0){ + outfile << "filename " << infile << endl; + outfile << "num_nodes " << g->get_num_nodes() << endl; + outfile << "num_edges " << g->get_num_edges() << endl; + } + if(record_timings){ string of = outfilename + ".timings"; if(file_append == false){ @@ -444,23 +458,11 @@ int main(int argc, char **argv){ cerr << "Error opening " << timing_file << " for writing, exiting" << endl; exit(1); } - outfile << "Recording timings to " << of << endl; + outfile << "timing_file " << of << endl; } - // Read in the graph and start recording things to output streams - cout << "Reading graph" << endl; - ORB_read(t1); - if(gr.read_graph(g, infile, intype, false) == -1){ - exit(1); - } - ORB_read(t2); print_time(timing_file, "Time(read_graph)", t1, t2); - if(outfile.tellp() == 0){ - outfile << "filename " << infile << endl; - outfile << "num_nodes " << g->get_num_nodes() << endl; - outfile << "num_edges " << g->get_num_edges() << endl; - } outfile.precision(16); vector components; @@ -509,7 +511,7 @@ int main(int argc, char **argv){ cerr << "Error opening " << timing_file << " for writing, exiting" << endl; exit(1); } - outfile << "Recording timings to " << of << endl; + outfile << "timing_file " << of << endl; } outprefix = outprefix + ".largest_component"; From 628a9a65c12a366227b6b25a0b8633a6afc05d41 Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Tue, 24 Sep 2013 16:14:03 -0400 Subject: [PATCH 63/73] Hopefully fixing memory issues with large APSP matrices Remove extraneous debug infoz --- lib_graphd/inc/Graph.h | 4 ++-- lib_graphd/src/Graph.cpp | 22 +++++++++++++--------- lib_graphd/src/GraphCreator.cpp | 2 -- lib_graphd/src/GraphProperties.cpp | 4 ++-- 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/lib_graphd/inc/Graph.h b/lib_graphd/inc/Graph.h index 182b181..6c25d47 100644 --- a/lib_graphd/inc/Graph.h +++ b/lib_graphd/inc/Graph.h @@ -97,7 +97,7 @@ namespace Graph { vector xadj; vector adjncy; vector adj_vec; - vector< vector > apsp_dist; + vector< vector > *apsp_dist; // Currently this is only calculated if you have Boost. vector betweenness; @@ -133,7 +133,7 @@ namespace Graph { /** \brief Try to pre-allocate memory for node and degree vectors **/ void resize(int n); /** \brief set shortest path distances **/ - void set_shortest_path_dist(vector< vector > apsp_dist); + void set_shortest_path_dist(vector< vector > *apsp_dist); /** \brief set betweenness centrality vector **/ void set_betweenness(vector bc); diff --git a/lib_graphd/src/Graph.cpp b/lib_graphd/src/Graph.cpp index d001c5e..c58a050 100644 --- a/lib_graphd/src/Graph.cpp +++ b/lib_graphd/src/Graph.cpp @@ -85,6 +85,7 @@ namespace Graph { this->simple = true; //FIXME: check if this is correct behavior this->canonical = true; this->key = 0; + this->apsp_dist = NULL; #ifdef HAS_BOOST this->boost_graph = NULL; #endif @@ -752,7 +753,7 @@ namespace Graph { /** * \param[in] apsp_dist all pairs shortest paths distances **/ - void Graph::set_shortest_path_dist(vector< vector > apsp_dist){ + void Graph::set_shortest_path_dist(vector< vector > *apsp_dist){ this->apsp_dist = apsp_dist; } @@ -777,24 +778,27 @@ namespace Graph { * otherwise computes then returns **/ const vector< vector > &Graph::get_shortest_path_dist_ref(){ - if(this->apsp_dist.empty()){ + if(this->apsp_dist == NULL) { + this->apsp_dist = new(vector< vector >); + } + if(this->apsp_dist->empty()){ cout << "Empty -- calling function to compute shortest paths" << endl; GraphProperties properties; - properties.paths_dijkstra_all(this,this->apsp_dist); //sets this>apsp_dist with values - return this->apsp_dist; + properties.paths_dijkstra_all(this,*(this->apsp_dist)); //sets this>apsp_dist with values } - return this->apsp_dist; + return *(this->apsp_dist); } const vector &Graph::get_u_shortest_path_dist(int u){ + if(this->apsp_dist == NULL) { + this->apsp_dist = new(vector< vector >); + } if(this->apsp_dist[u].empty()){ cout << "u Empty -- calling function to compute shortest paths" << endl; GraphProperties properties; - properties.paths_dijkstra_single(this,this->apsp_dist[u], u); //sets this>apsp_dist[u] with values - - return this->apsp_dist[u]; + properties.paths_dijkstra_single(this,(*(this->apsp_dist))[u], u); //sets this>apsp_dist[u] with values } - return this->apsp_dist[u]; + return (*(this->apsp_dist))[u]; } } diff --git a/lib_graphd/src/GraphCreator.cpp b/lib_graphd/src/GraphCreator.cpp index dc79b68..e68254c 100644 --- a/lib_graphd/src/GraphCreator.cpp +++ b/lib_graphd/src/GraphCreator.cpp @@ -397,11 +397,9 @@ namespace Graph { VertexWeightedGraph *GraphCreator::create_component(VertexWeightedGraph *g, list *members, bool make_simple){ VertexWeightedGraph *wmg; - cout << typeid(g).name() << endl; wmg = create_induced_subgraph(g, members, make_simple); // Set num_connected_components to 1 since g is known - not verified - should it be?? wmg->num_connected_components = 1; - cout << "create_component called for vwg" << endl; return wmg; } diff --git a/lib_graphd/src/GraphProperties.cpp b/lib_graphd/src/GraphProperties.cpp index 46448ca..c1f0dc2 100644 --- a/lib_graphd/src/GraphProperties.cpp +++ b/lib_graphd/src/GraphProperties.cpp @@ -673,7 +673,7 @@ namespace Graph { } } //store the results - g->set_shortest_path_dist(pAll); + g->set_shortest_path_dist(&pAll); } // paths_dijkstra_boost_all /** @@ -785,7 +785,7 @@ namespace Graph { } //end loop over vertices //store the results - g->set_shortest_path_dist(pAll); + g->set_shortest_path_dist(&pAll); //print out results //for(int i = 0; i < n; i++){ From 67f6212c7e7a66ab0d33aac8cca372e2bd9a7056 Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Wed, 25 Sep 2013 00:05:17 -0400 Subject: [PATCH 64/73] Check some more type declarations for apsp matrix --- lib_graphd/src/GraphProperties.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib_graphd/src/GraphProperties.cpp b/lib_graphd/src/GraphProperties.cpp index c1f0dc2..6fe82c5 100644 --- a/lib_graphd/src/GraphProperties.cpp +++ b/lib_graphd/src/GraphProperties.cpp @@ -804,7 +804,7 @@ namespace Graph { */ void GraphProperties::eccentricity(Graph *g, vector &ecc){ const int n = g->get_num_nodes(); - vector< vector > short_paths = g->get_shortest_path_dist_ref(); //computes if not already + const vector< vector > &short_paths = g->get_shortest_path_dist_ref(); //computes if not already int bestMax = 0; ecc.resize(n); @@ -863,7 +863,7 @@ namespace Graph { */ void GraphProperties::expansion(Graph *g, vector &norm_hops){ const int n = g->get_num_nodes(); - vector< vector > short_paths = g->get_shortest_path_dist_ref(); //computes if not already + const vector< vector > &short_paths = g->get_shortest_path_dist_ref(); //computes if not already vector hops(n,0); //largest possible dist is n-1 norm_hops.resize(n); int k; @@ -895,7 +895,7 @@ namespace Graph { */ void GraphProperties::diameter(Graph *g, int &diam){ int i, j, size, temp; - vector< vector > dist_mat = g->get_shortest_path_dist_ref(); //computes if not already + const vector< vector > &dist_mat = g->get_shortest_path_dist_ref(); //computes if not already size = dist_mat.size(); diam = dist_mat[0][0]; @@ -920,7 +920,7 @@ namespace Graph { int i, j, d, size, temp, diam = 0; int n0, numer, tot_con_pairs = 0; float gd; - vector< vector > dist_mat = g->get_shortest_path_dist_ref(); //computes if not already + const vector< vector > &dist_mat = g->get_shortest_path_dist_ref(); //computes if not already vector bins (g->num_nodes, 0); size = dist_mat.size(); @@ -977,13 +977,13 @@ namespace Graph { void GraphProperties::avg_path_length(Graph *g, double &pl){ const int n = g->get_num_nodes(); - const vector< vector > short_paths = g->get_shortest_path_dist_ref(); + const vector< vector > &short_paths = g->get_shortest_path_dist_ref(); double sum = 0; double intermediate = 0.0; int i, j; int inf_path = 0; - #pragma omp parallel for schedule(dynamic, 16) default(none) private(j) reduction(+:sum,inf_path) + #pragma omp parallel for schedule(dynamic, 16) default(none) private(j) reduction(+:sum,inf_path) shared(short_paths) for(i = 0; i < n; i++){ for(j = 0; j < n; j++){ if(INDDGO_INFINITY != short_paths[i][j]){ @@ -1186,7 +1186,7 @@ namespace Graph { * \param[out] delta Vector of vectors of doubles holding the delta hyperbolicity distribution */ void GraphProperties::delta_hyperbolicity(Graph *g, double &max_delta, vector > &delta){ - vector< vector > dist_mat = g->get_shortest_path_dist_ref(); + const vector< vector > &dist_mat = g->get_shortest_path_dist_ref(); int size = dist_mat.size(); int mat_size = dist_mat.size(); int counter = 0; From 5aec096eb88bb48c203336680a109bb10d44de5b Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Wed, 25 Sep 2013 09:57:28 -0400 Subject: [PATCH 65/73] fix output for largest components --- util/src/graph_stats.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/util/src/graph_stats.cpp b/util/src/graph_stats.cpp index d6d628c..48c65dc 100644 --- a/util/src/graph_stats.cpp +++ b/util/src/graph_stats.cpp @@ -494,10 +494,15 @@ int main(int argc, char **argv){ cerr << "Error opening " << outfilename << " for writing, exiting" << endl; exit(1); } + + // get the largest component + Graph::Graph *largest_component = gu.get_largest_component_graph(g); + delete(g); // delete g here to save on memory + if(outfile.tellp() == 0){ outfile << "filename " << infile << endl; - outfile << "num_nodes " << g->get_num_nodes() << endl; - outfile << "num_edges " << g->get_num_edges() << endl; + outfile << "num_nodes " << largest_component->get_num_nodes() << endl; + outfile << "num_edges " << largest_component->get_num_edges() << endl; } if(record_timings){ string of = outfilename + ".timings"; @@ -517,10 +522,6 @@ int main(int argc, char **argv){ outprefix = outprefix + ".largest_component"; outfile.precision(16); - outfile << "filename" << infile << endl; - Graph::Graph *largest_component = gu.get_largest_component_graph(g); - delete(g); // delete g here to save on memory - run_all_methods(largest_component, outfile, timing_file, outprefix, req_methods, file_append, spectrum_spread); outfile.close(); timing_file.close(); From 29087c638889ecb18318cbb5c9191ed52ba19c4d Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Wed, 25 Sep 2013 12:19:09 -0400 Subject: [PATCH 66/73] potential fix for overflow in avg_path_length --- lib_graphd/src/GraphProperties.cpp | 32 ++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/lib_graphd/src/GraphProperties.cpp b/lib_graphd/src/GraphProperties.cpp index 6fe82c5..cff26b5 100644 --- a/lib_graphd/src/GraphProperties.cpp +++ b/lib_graphd/src/GraphProperties.cpp @@ -979,23 +979,35 @@ namespace Graph { const int n = g->get_num_nodes(); const vector< vector > &short_paths = g->get_shortest_path_dist_ref(); double sum = 0; - double intermediate = 0.0; + int intermediate = 0; int i, j; int inf_path = 0; - #pragma omp parallel for schedule(dynamic, 16) default(none) private(j) reduction(+:sum,inf_path) shared(short_paths) - for(i = 0; i < n; i++){ - for(j = 0; j < n; j++){ - if(INDDGO_INFINITY != short_paths[i][j]){ - sum += short_paths[i][j]; + #pragma omp parallel default(none) private(j, intermediate) reduction(+:sum) shared(short_paths, inf_path) + { + #pragma omp for reduction(+:inf_path) + for(i=0; i Date: Wed, 25 Sep 2013 15:01:01 -0400 Subject: [PATCH 67/73] Adding routines to read in APSP matrices --- lib_graphd/inc/Util.h | 6 ++++++ lib_graphd/src/Util.cpp | 45 ++++++++++++++++++++++++++++++++++------ util/src/graph_stats.cpp | 23 ++++++++++++++++---- 3 files changed, 64 insertions(+), 10 deletions(-) diff --git a/lib_graphd/inc/Util.h b/lib_graphd/inc/Util.h index 9532fa0..89dd8f5 100644 --- a/lib_graphd/inc/Util.h +++ b/lib_graphd/inc/Util.h @@ -116,6 +116,12 @@ void write_delta_hyperbolicity(string filename, const vector< vector > & * \brief Write an all pairs shortest path matrix out to file. */ void write_apsp_matrix(string filename, vector< vector > &apsp); + +/** + * \brief Reads an all pairs shortest path matrix from file + */ +void read_apsp_matrix(string filename, vector< vector > &apsp); + int_int mylog2(int x); #endif /* UTIL_H_ */ diff --git a/lib_graphd/src/Util.cpp b/lib_graphd/src/Util.cpp index 68e59a9..8ce6c0d 100644 --- a/lib_graphd/src/Util.cpp +++ b/lib_graphd/src/Util.cpp @@ -37,11 +37,11 @@ int parseLine(char *line){ return i; } -int getHWmem(){ -#if WIN32 - return -1; -#endif - //Note: this value is in KB! +int getHWmem(){ + #if WIN32 + return -1; + #endif + //Note: this value is in KB! FILE *file = fopen("/proc/self/status", "r"); if(file == NULL){ fprintf(stderr, "Error opening processor status file!\n"); @@ -945,7 +945,7 @@ void write_delta_hyperbolicity(string filename, const vector< vector > & } // write_betweenness /** - * Write a all pairs shortest path matrix out to file. + * Write an all pairs shortest path matrix out to file. * * \param[in] filename filename to write output to * \param[in] apsp a vector< vector >, indexed on vertex number, assumed to be |V|x|V| @@ -974,3 +974,36 @@ void write_apsp_matrix(string filename, vector< vector > &apsp){ fclose(outfile); } // write_apsp_matrix +/** + * Read an all pairs shortest path matrixfrom file. + * + * \param[in] filename filename to read + * \param[out] apsp a vector< vector >, indexed on vertex number, assumed to be |V|x|V| + */ +void read_apsp_matrix(string filename, vector< vector > &apsp){ + int i; + int n; + + FILE *infile; + infile = fopen(filename.c_str(), "r"); + + if(!infile){ + cerr << "Error opening " << filename << "for writing\n"; + } + + fread((void *) &n, 1, sizeof(int), infile); + cerr << "Reading apsp matrix of size: " << n << endl; + + apsp.resize(n); + + //#pragma omp parallel for default(none) share(n, apsp) + int ret; + for(i = 0; i < n; i++){ + apsp[i].resize(n); + int *arr = &apsp[i].front(); + fread(arr, n, sizeof(int), infile); + } + + fclose(infile); +} // write_apsp_matrix + diff --git a/util/src/graph_stats.cpp b/util/src/graph_stats.cpp index d6d628c..237fb65 100644 --- a/util/src/graph_stats.cpp +++ b/util/src/graph_stats.cpp @@ -65,7 +65,7 @@ void create_map(string list, map &outmap){ } void print_usage(char **argv){ - cerr << "Usage: " << argv[0] << " [-h] -i infile [-t input-type] [-o outfile] [-p output-prefix] [-m methods] [-s eigen spectrum size] [-r]" << endl; + cerr << "Usage: " << argv[0] << " [-h] -i infile [-t input-type] [-o outfile] [-p output-prefix] [-m methods] [-s eigen spectrum size] [-r] [-x APSP matrix input]" << endl; cerr << "Allowed methods: " << allowed_methods << endl; cerr << "Input type should be one of: edge, adjlist, adjmatrix, dimacs" << endl; } @@ -80,9 +80,9 @@ void print_usage(char **argv){ * \param[out] methods list of methods we want to run. Valid values currently: edge_density,avg_degree,degree_dist,global_cc, avg_cc, local_ccs */ -int parse_options(int argc, char **argv, string& infile, string& intype, string& outfilename, string &outprefix, std::map& methods, bool& record_timings, bool &file_append, int *spectrum_spread){ +int parse_options(int argc, char **argv, string& infile, string& intype, string& outfilename, string &outprefix, std::map& methods, bool& record_timings, bool &file_append, int *spectrum_spread, string &apsp_input){ int flags, opt; - while((opt = getopt(argc, argv, "hi:t:o:m:p:s:ra")) != -1){ + while((opt = getopt(argc, argv, "hi:t:o:m:p:s:rax:")) != -1){ switch(opt){ case 'h': print_usage(argv); @@ -111,6 +111,9 @@ int parse_options(int argc, char **argv, string& infile, string& intype, string& case 'a': file_append = true; break; + case 'x': + apsp_input = optarg; + break; } } @@ -371,6 +374,7 @@ int main(int argc, char **argv){ string infile; string outfilename; string outprefix; + string apspinputfilename; ofstream outfile; ofstream timing_file; bool record_timings = false; @@ -381,7 +385,7 @@ int main(int argc, char **argv){ ORB_t t1, t2; int spectrum_spread = 0; create_map(allowed_methods, val_methods); - parse_options(argc, argv, infile, intype, outfilename, outprefix, req_methods, record_timings, file_append, &spectrum_spread); + parse_options(argc, argv, infile, intype, outfilename, outprefix, req_methods, record_timings, file_append, &spectrum_spread, apspinputfilename); if(outfilename.length() == 0){ if(outprefix.length() != 0) { outfilename = outprefix+".stats"; @@ -463,6 +467,17 @@ int main(int argc, char **argv){ print_time(timing_file, "Time(read_graph)", t1, t2); + if(apspinputfilename.length() != 0){ + cout << "Reading APSP matrix from " << apspinputfilename << endl; + vector< vector > *apsp_dists = new vector< vector >; + ORB_read(t1); + read_apsp_matrix(apspinputfilename, *apsp_dists); + ORB_read(t2); + print_time(timing_file, "Time(read_apsp_matrix)", t1, t2); + g->set_shortest_path_dist(apsp_dists); + } + + outfile.precision(16); vector components; From e8c27f818ee523319bd41af66960089a5d649c47 Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Wed, 25 Sep 2013 15:01:59 -0400 Subject: [PATCH 68/73] cleaning up tons of merged code --- lib_graphd/inc/Graph.h | 71 +++-- lib_graphd/inc/GraphReader.h | 2 +- lib_graphd/inc/GraphWriter.h | 2 +- lib_graphd/src/Graph.cpp | 5 +- lib_graphd/src/GraphCreator.cpp | 19 +- lib_graphd/src/GraphProperties.cpp | 12 +- lib_graphd/src/GraphReader.cpp | 2 +- lib_graphd/src/GraphUtil.cpp | 131 ++++----- lib_graphd/src/Util.cpp | 10 +- util/src/CPX_solve_wis.cpp | 425 ++++++++++++++--------------- util/src/complement.cpp | 87 +++--- util/src/count-tri.cpp | 45 ++- util/src/gconvert.cpp | 15 +- util/src/gen_pkt.cpp | 15 +- util/src/graph_stats.cpp | 39 +-- util/src/orbtimer.cpp | 24 +- 16 files changed, 446 insertions(+), 458 deletions(-) mode change 100755 => 100644 util/src/CPX_solve_wis.cpp mode change 100755 => 100644 util/src/complement.cpp diff --git a/lib_graphd/inc/Graph.h b/lib_graphd/inc/Graph.h index 6c25d47..4660632 100644 --- a/lib_graphd/inc/Graph.h +++ b/lib_graphd/inc/Graph.h @@ -21,60 +21,59 @@ /*This fixes any issues with MSVC always having HAS_METIS defined*/ #ifdef _MSC_VER - #if !HAS_METIS - #undef HAS_METIS + #if !HAS_METIS + #undef HAS_METIS #endif -#endif - +#endif #ifndef GRAPH_H_ -#define GRAPH_H_ - -#ifdef _OPENMP - #include -#else - #ifndef HAS_METIS - #define omp_get_num_threads() 1 - #define omp_get_thread_num() 0 - #define omp_get_max_threads() 1 + #define GRAPH_H_ + + #ifdef _OPENMP + #include + #else + #ifndef HAS_METIS + #define omp_get_num_threads() 1 + #define omp_get_thread_num() 0 + #define omp_get_max_threads() 1 + #endif #endif -#endif -#ifdef HAS_PETSC - #include -#endif + #ifdef HAS_PETSC + #include + #endif -#if WIN32 -#define strncasecmp strncmp -#endif + #if WIN32 + #define strncasecmp strncmp + #endif -#include "GraphInterface.h" -#include "Node.h" -#include "GraphException.h" -#include "Log.h" -#include + #include "GraphInterface.h" + #include "Node.h" + #include "GraphException.h" + #include "Log.h" + #include -#ifdef HAS_BOOST - #include - #include - #include + #ifdef HAS_BOOST + #include + #include + #include - #include "boost/graph/adjacency_list.hpp" - #include "boost/graph/topological_sort.hpp" - #include -#endif + #include "boost/graph/adjacency_list.hpp" + #include "boost/graph/topological_sort.hpp" + #include + #endif using namespace std; -#define INDDGO_INFINITY INT_MAX - 16 + #define INDDGO_INFINITY INT_MAX - 16 -#ifdef HAS_BOOST + #ifdef HAS_BOOST typedef boost::property EdgeWeightProperty; typedef boost::property CentralityMap; typedef boost::adjacency_list BoostUndirected; typedef boost::graph_traits < BoostUndirected >::vertex_descriptor vertex_descriptor; typedef boost::graph_traits < BoostUndirected >::edge_descriptor edge_descriptor; -#endif //HAS_BOOST + #endif //HAS_BOOST namespace Graph { class Graph : public GraphInterface diff --git a/lib_graphd/inc/GraphReader.h b/lib_graphd/inc/GraphReader.h index 2ee7f18..57f2a59 100644 --- a/lib_graphd/inc/GraphReader.h +++ b/lib_graphd/inc/GraphReader.h @@ -29,7 +29,7 @@ #include "Debug.h" #include #if !WIN32 -#include + #include #endif #include #include diff --git a/lib_graphd/inc/GraphWriter.h b/lib_graphd/inc/GraphWriter.h index b82fe97..1954ebc 100644 --- a/lib_graphd/inc/GraphWriter.h +++ b/lib_graphd/inc/GraphWriter.h @@ -29,7 +29,7 @@ #include "Debug.h" #include #if !WIN32 -#include + #include #endif #include #include diff --git a/lib_graphd/src/Graph.cpp b/lib_graphd/src/Graph.cpp index c58a050..e21633a 100644 --- a/lib_graphd/src/Graph.cpp +++ b/lib_graphd/src/Graph.cpp @@ -28,7 +28,6 @@ #include #include - #ifndef _OPENMP #ifdef HAS_METIS void omp_set_num_threads(int num_threads){ @@ -778,7 +777,7 @@ namespace Graph { * otherwise computes then returns **/ const vector< vector > &Graph::get_shortest_path_dist_ref(){ - if(this->apsp_dist == NULL) { + if(this->apsp_dist == NULL){ this->apsp_dist = new(vector< vector >); } if(this->apsp_dist->empty()){ @@ -790,7 +789,7 @@ namespace Graph { } const vector &Graph::get_u_shortest_path_dist(int u){ - if(this->apsp_dist == NULL) { + if(this->apsp_dist == NULL){ this->apsp_dist = new(vector< vector >); } if(this->apsp_dist[u].empty()){ diff --git a/lib_graphd/src/GraphCreator.cpp b/lib_graphd/src/GraphCreator.cpp index e68254c..e77f852 100644 --- a/lib_graphd/src/GraphCreator.cpp +++ b/lib_graphd/src/GraphCreator.cpp @@ -63,13 +63,16 @@ namespace Graph { unsigned long y = 0; for(int j = l - 1; j >= 0; j--){ double r = lcgrand(0); - if(r < q1) { - } else if(r < q2) { - // pow(2,j)?? 1< #if !WIN32 -#include + #include #endif #include @@ -496,7 +496,7 @@ namespace Graph { } //if revmap } //for vtxs } //for fakev - int tsize=(int)t.size(); + int tsize = (int)t.size(); #pragma omp for for(i = 0; i < tsize; i++){ for(int j = 0; j < omp_get_num_threads(); j++){ @@ -840,14 +840,14 @@ namespace Graph { freq_ecc.resize(*(std::max_element(ecc.begin(), ecc.end())) + 1); //compute diameter of each vertex - int eccsize=ecc.size(); - // This could be slow with resizing - for(int i = 0; i < eccsize ; i++){ + int eccsize = ecc.size(); + // This could be slow with resizing + for(int i = 0; i < eccsize; i++){ freq_ecc[ecc[i]]++; //add to tally for this diameter size } //printf("Graph diameter is %d\n", freq_ecc.size()-1); - int freq_ecc_size=freq_ecc.size(); + int freq_ecc_size = freq_ecc.size(); #pragma omp parallel for default(none) shared(freq_ecc, freq_ecc_size) for(int i = 0; i <= freq_ecc_size - 1; i++){ freq_ecc[i] = freq_ecc[i] / n; diff --git a/lib_graphd/src/GraphReader.cpp b/lib_graphd/src/GraphReader.cpp index 7712af7..66267ad 100644 --- a/lib_graphd/src/GraphReader.cpp +++ b/lib_graphd/src/GraphReader.cpp @@ -24,7 +24,7 @@ #include "Debug.h" #include "Util.h" #if !WIN32 -#include + #include #endif #include #include diff --git a/lib_graphd/src/GraphUtil.cpp b/lib_graphd/src/GraphUtil.cpp index 463167d..f46b6cc 100644 --- a/lib_graphd/src/GraphUtil.cpp +++ b/lib_graphd/src/GraphUtil.cpp @@ -857,71 +857,72 @@ namespace Graph { return max; } // subset_max_dist - /** - * Calculates the k-core number of every vertex and stores in kcore vector - * Return value is degeneracy (maximum non-empty k-core). - * Uses algorithm of Batagelj and Zaversnik (2003) - * Implemented by Timothy Goodrich and Matthew Farrell (2013) - */ - int GraphUtil::find_kcore(Graph *g, vector *kcore) { - int n = g->num_nodes; - int k = 0; - int last_deg = 0; - kcore->resize(n); - - vector deg_lookup(n); - int max_deg = 0; - int deg_size=deg_lookup.size(); - for(int i = 0; i < deg_size; i++) { - deg_lookup[i] = g->degree[i]; - if(deg_lookup[i] > max_deg) - max_deg = deg_lookup[i]; - } - vector > D; - D.resize(max_deg+1); - - int *depth; - depth=new int[n]; - //int depth[n]; - //can also create an L output list for coloring number optimal ordering - - for(int i = 0; i < n; i++) { - deg_lookup[i] = g->degree[i]; - D[deg_lookup[i]].push_back(i); - depth[i] = D[deg_lookup[i]].size()-1; - } - - for(int i = 0; i < n; i++) { - int v; - for(int j = last_deg; j <= max_deg; j++) { - if(D[j].size() != 0) { - v = D[j].back(); - D[j].pop_back(); - break; - } - } - - (*kcore)[v] = k = max(k,deg_lookup[v]); - last_deg = max(0, deg_lookup[v]-1); - deg_lookup[v] = -1; - - //shift each of v's neighbors down one degree - list * nbrs = g->nodes[v].get_nbrs_ptr(); - list::const_iterator it; - for(it = nbrs->begin(); it != nbrs->end(); it++) { - if(deg_lookup[*it] != -1) { - int it_deg = deg_lookup[*it]--; - D[it_deg][depth[*it]] = D[it_deg][D[it_deg].size()-1]; - depth[D[it_deg][depth[*it]]] = depth[*it]; - D[it_deg].pop_back(); - D[it_deg-1].push_back(*it); - depth[*it] = D[it_deg-1].size()-1; - } - } - } - delete [] depth; - return k; - } // find_degen + /** + * Calculates the k-core number of every vertex and stores in kcore vector + * Return value is degeneracy (maximum non-empty k-core). + * Uses algorithm of Batagelj and Zaversnik (2003) + * Implemented by Timothy Goodrich and Matthew Farrell (2013) + */ + int GraphUtil::find_kcore(Graph *g, vector *kcore){ + int n = g->num_nodes; + int k = 0; + int last_deg = 0; + kcore->resize(n); + + vector deg_lookup(n); + int max_deg = 0; + int deg_size = deg_lookup.size(); + for(int i = 0; i < deg_size; i++){ + deg_lookup[i] = g->degree[i]; + if(deg_lookup[i] > max_deg){ + max_deg = deg_lookup[i]; + } + } + vector > D; + D.resize(max_deg + 1); + + int *depth; + depth = new int[n]; + //int depth[n]; + //can also create an L output list for coloring number optimal ordering + + for(int i = 0; i < n; i++){ + deg_lookup[i] = g->degree[i]; + D[deg_lookup[i]].push_back(i); + depth[i] = D[deg_lookup[i]].size() - 1; + } + + for(int i = 0; i < n; i++){ + int v; + for(int j = last_deg; j <= max_deg; j++){ + if(D[j].size() != 0){ + v = D[j].back(); + D[j].pop_back(); + break; + } + } + + (*kcore)[v] = k = max(k,deg_lookup[v]); + last_deg = max(0, deg_lookup[v] - 1); + deg_lookup[v] = -1; + + //shift each of v's neighbors down one degree + list *nbrs = g->nodes[v].get_nbrs_ptr(); + list::const_iterator it; + for(it = nbrs->begin(); it != nbrs->end(); it++){ + if(deg_lookup[*it] != -1){ + int it_deg = deg_lookup[*it]--; + D[it_deg][depth[*it]] = D[it_deg][D[it_deg].size() - 1]; + depth[D[it_deg][depth[*it]]] = depth[*it]; + D[it_deg].pop_back(); + D[it_deg - 1].push_back(*it); + depth[*it] = D[it_deg - 1].size() - 1; + } + } + } + delete [] depth; + return k; + } // find_degen /** * \input g input graph diff --git a/lib_graphd/src/Util.cpp b/lib_graphd/src/Util.cpp index 68e59a9..d5f90d0 100644 --- a/lib_graphd/src/Util.cpp +++ b/lib_graphd/src/Util.cpp @@ -37,11 +37,11 @@ int parseLine(char *line){ return i; } -int getHWmem(){ -#if WIN32 - return -1; -#endif - //Note: this value is in KB! +int getHWmem(){ + #if WIN32 + return -1; + #endif + //Note: this value is in KB! FILE *file = fopen("/proc/self/status", "r"); if(file == NULL){ fprintf(stderr, "Error opening processor status file!\n"); diff --git a/util/src/CPX_solve_wis.cpp b/util/src/CPX_solve_wis.cpp old mode 100755 new mode 100644 index 89e88ec..802d63b --- a/util/src/CPX_solve_wis.cpp +++ b/util/src/CPX_solve_wis.cpp @@ -8,231 +8,220 @@ #include "GraphDecomposition.h" -void check_CPX_status(char *func, int status) -{ - if (status) - { - fprintf (stderr, "CPX nonzero status after %s: %d\n",func,status); - exit(-1); - } +void check_CPX_status(char *func, int status){ + if(status){ + fprintf (stderr, "CPX nonzero status after %s: %d\n",func,status); + exit(-1); + } }; void write_ind_set_model(const char *DIMACS_file, const char *model_file, - Graph::VertexWeightedGraph *G) -{ - int i, j; - - FILE *out = fopen(model_file, "w"); - if (!out) - fatal_error("Can't open %s for writing\n", model_file); - - // Write out the model - fprintf(out, - "# Automatically generated model file for max independent set\n" - "# Assumes 1-based node names with no holes!!\n" - "# Original graph file is %s\n" - "# Model section\n\n" - "param num_nodes ;\n" - "set Nodes := 1..num_nodes ;\n" - "set E within Nodes cross Nodes ;\n" - "param w{Nodes};\n" - "var x{i in Nodes} binary;\n\n" - // Change to minimization for archaic MPS reasons - "minimize Cost: sum{i in Nodes} -x[i]*w[i];\n\n" - "subject to Independent{i in Nodes, j in Nodes: (i,j) in E}:\n" - "x[i]+x[j]<=1;\n\n" - "solve;\n\n", DIMACS_file); - /* - fprintf( - out, - "printf \" \\nMaximum Independent Set: %%d\\n\", sum{i in Nodes} x[i]*w[i] > \"%s\";\n", - sol_file); - fprintf(out, "for { i in Nodes }\n" - "{\n" - " printf{0..0: x[i]!=0} \"%%d (%%3.1f)\\n\", i, w[i] >> \"%s\";\n", - sol_file); - fprintf(out, "}\n\n");*/ - fflush(out); - fprintf(stderr,"Writing data section\n"); - - fprintf(out, "# Data Section\n\ndata;\n\n"); - fflush(out); - // Write out the problem data - fprintf(out, "param num_nodes:=%d;\n", G->get_num_nodes()); - fflush(out); - fprintf(out, "param w:=\n"); - fflush(out); - vector nodes = G->get_nodes(); - vector weight = G->get_weight(); - - for (i = 0; i < G->get_num_nodes(); i++) - { - fprintf(out, "%d %d\n",nodes[i].get_label(), weight[i]); - } - fprintf(out, ";\n"); - fprintf(out, "set E:=\n"); - Graph::GraphProperties properties; - - vector adj_vec; - for (i = 0; i < G->get_num_nodes(); i++) - { - // This assumes 1-based labeling! - int current_key = properties.fill_adj_vec(G, i); - //int current_key=G->fill_adj_vec(i); - adj_vec = G->get_adj_vec(); - for (j = i + 1; j < G->get_num_nodes(); j++) - { - if (adj_vec[j] == current_key) - fprintf(out, "(%d,%d)\n", i + 1, j + 1); - } - fprintf(out, "\n"); - } - fprintf(out, ";\nend;\n"); - fclose(out); + Graph::VertexWeightedGraph *G){ + int i, j; + + FILE *out = fopen(model_file, "w"); + if(!out){ + fatal_error("Can't open %s for writing\n", model_file); + } + + // Write out the model + fprintf(out, + "# Automatically generated model file for max independent set\n" + "# Assumes 1-based node names with no holes!!\n" + "# Original graph file is %s\n" + "# Model section\n\n" + "param num_nodes ;\n" + "set Nodes := 1..num_nodes ;\n" + "set E within Nodes cross Nodes ;\n" + "param w{Nodes};\n" + "var x{i in Nodes} binary;\n\n" + // Change to minimization for archaic MPS reasons + "minimize Cost: sum{i in Nodes} -x[i]*w[i];\n\n" + "subject to Independent{i in Nodes, j in Nodes: (i,j) in E}:\n" + "x[i]+x[j]<=1;\n\n" + "solve;\n\n", DIMACS_file); + /* + fprintf( + out, + "printf \" \\nMaximum Independent Set: %%d\\n\", sum{i in Nodes} x[i]*w[i] > \"%s\";\n", + sol_file); + fprintf(out, "for { i in Nodes }\n" + "{\n" + " printf{0..0: x[i]!=0} \"%%d (%%3.1f)\\n\", i, w[i] >> \"%s\";\n", + sol_file); + fprintf(out, "}\n\n");*/ + fflush(out); + fprintf(stderr,"Writing data section\n"); + + fprintf(out, "# Data Section\n\ndata;\n\n"); + fflush(out); + // Write out the problem data + fprintf(out, "param num_nodes:=%d;\n", G->get_num_nodes()); + fflush(out); + fprintf(out, "param w:=\n"); + fflush(out); + vector nodes = G->get_nodes(); + vector weight = G->get_weight(); + + for(i = 0; i < G->get_num_nodes(); i++){ + fprintf(out, "%d %d\n",nodes[i].get_label(), weight[i]); + } + fprintf(out, ";\n"); + fprintf(out, "set E:=\n"); + Graph::GraphProperties properties; + + vector adj_vec; + for(i = 0; i < G->get_num_nodes(); i++){ + // This assumes 1-based labeling! + int current_key = properties.fill_adj_vec(G, i); + //int current_key=G->fill_adj_vec(i); + adj_vec = G->get_adj_vec(); + for(j = i + 1; j < G->get_num_nodes(); j++){ + if(adj_vec[j] == current_key){ + fprintf(out, "(%d,%d)\n", i + 1, j + 1); + } + } + fprintf(out, "\n"); + } + fprintf(out, ";\nend;\n"); + fclose(out); }; -void read_DIMACS(const char *DIMACS_file, Graph::VertexWeightedGraph *G) -{ - int i; - Graph::GraphCreatorFile creator; - creator.set_file_name(DIMACS_file); - creator.set_graph_type("DIMACS"); - - G = creator.create_weighted_mutable_graph(); - if (!G) - { - fprintf(stderr,"Could not create graph for DIMACS file %s\n",DIMACS_file); - exit(-1); - } - - // Add weights of 1 to all vertices if we didn't load any from the file - bool has_weights = false; - vector weight = (G)->get_weight(); - for (i = 0; i < (G)->get_capacity(); i++) - { - if (weight[i] != 0) - { - has_weights = true; - break; - } - } - - if (!has_weights) - for (i = 0; i < (G)->get_capacity(); i++) - weight[i] = 1; - - fprintf(stderr,"Graph loaded with %d nodes, %d edges\n",G->get_num_nodes(), - G->get_num_edges()); +void read_DIMACS(const char *DIMACS_file, Graph::VertexWeightedGraph *G){ + int i; + Graph::GraphCreatorFile creator; + creator.set_file_name(DIMACS_file); + creator.set_graph_type("DIMACS"); + + G = creator.create_weighted_mutable_graph(); + if(!G){ + fprintf(stderr,"Could not create graph for DIMACS file %s\n",DIMACS_file); + exit(-1); + } + + // Add weights of 1 to all vertices if we didn't load any from the file + bool has_weights = false; + vector weight = (G)->get_weight(); + for(i = 0; i < (G)->get_capacity(); i++){ + if(weight[i] != 0){ + has_weights = true; + break; + } + } + + if(!has_weights){ + for(i = 0; i < (G)->get_capacity(); i++){ + weight[i] = 1; + } + } + + fprintf(stderr,"Graph loaded with %d nodes, %d edges\n",G->get_num_nodes(), + G->get_num_edges()); }; -void create_mps_file(char *gmpl_file, char *mps_file, bool verbose) -{ - // Read in the model - glp_prob *lp; - glp_tran *tran; - if(!verbose) - glp_term_out(GLP_OFF); - lp = glp_create_prob(); - tran = glp_mpl_alloc_wksp(); - fprintf(stderr,"reading model\n"); - int ret = glp_mpl_read_model(tran, gmpl_file , 0); - if (ret) - { - fprintf(stderr, "Error translating model\n"); - exit(-1); - } - ret = glp_mpl_generate(tran, NULL); - if (ret) - { - fprintf(stderr, "Error generating model\n"); - exit(-1); - } - - glp_mpl_build_prob(tran, lp); - ret = glp_write_mps(lp, GLP_MPS_FILE, NULL, mps_file); - if (ret) - { - fprintf(stderr, "Error on writing MPS file\n"); - exit(-1); - } - glp_mpl_free_wksp(tran); - glp_delete_prob(lp); - fprintf(stderr,"GLPK created MPS file %s\n",mps_file); +void create_mps_file(char *gmpl_file, char *mps_file, bool verbose){ + // Read in the model + glp_prob *lp; + glp_tran *tran; + if(!verbose){ + glp_term_out(GLP_OFF); + } + lp = glp_create_prob(); + tran = glp_mpl_alloc_wksp(); + fprintf(stderr,"reading model\n"); + int ret = glp_mpl_read_model(tran, gmpl_file, 0); + if(ret){ + fprintf(stderr, "Error translating model\n"); + exit(-1); + } + ret = glp_mpl_generate(tran, NULL); + if(ret){ + fprintf(stderr, "Error generating model\n"); + exit(-1); + } + + glp_mpl_build_prob(tran, lp); + ret = glp_write_mps(lp, GLP_MPS_FILE, NULL, mps_file); + if(ret){ + fprintf(stderr, "Error on writing MPS file\n"); + exit(-1); + } + glp_mpl_free_wksp(tran); + glp_delete_prob(lp); + fprintf(stderr,"GLPK created MPS file %s\n",mps_file); +} // create_mps_file + +void usage(char *str){ + fprintf(stderr,"%s [-n num_threads]\n" + "\t Uses CPLEX with num_threads to solve WIS with max_seconds time limit\n",str); + exit(-1); } -void usage(char *str) -{ - fprintf(stderr,"%s [-n num_threads]\n" - "\t Uses CPLEX with num_threads to solve WIS with max_seconds time limit\n",str); - exit(-1); -} - -int main(int argc,char *argv[]) -{ - if(argc<3) - usage(argv[0]); - char *DIMACS_file=argv[1]; - // set time limit - int max_secs=atoi(argv[2]); - int num_threads=-1; - if(argc>=4) - { - for(int i=3;iget_num_nodes(), - G->get_num_edges()); - - // Write a GMPL model - sprintf(mod_file,"%s.mod",DIMACS_file); - write_ind_set_model(DIMACS_file, mod_file, G); - // Write mps file - sprintf(mps_file,"%s.mps",DIMACS_file); - create_mps_file(mod_file,mps_file,false); - - CPXENVptr env = NULL; - env = CPXopenCPLEX (&status); - check_CPX_status("CPXopenCPLEX",status); - - CPXsetintparam (env, CPX_PARAM_SCRIND, CPX_OFF); - - clock_t start=clock(),stop; - CPXLPptr mip; - mip=CPXcreateprob(env,&status,mps_file); - status = CPXreadcopyprob (env, mip, mps_file, NULL); - check_CPX_status("CPXreadcopyprob",status); - CPXsetdblparam(env, CPX_PARAM_TILIM, max_secs); - - if(num_threads!=-1) - // Set # of threads - CPXsetintparam(env,CPX_PARAM_THREADS,num_threads); - - int num_cols=CPXgetnumcols(env,mip); - int num_rows=CPXgetnumrows(env,mip); - - int mip_status=CPXmipopt(env,mip); - double obj; - CPXgetobjval(env,mip,&obj); - int objval=(int)obj; - stop=clock(); - fprintf(stdout,"%s %d %d %d %d %d %3.3f\n",DIMACS_file,num_cols, num_rows,mip_status, - -objval,getHWmem(),(double)(stop-start)/CLOCKS_PER_SEC); - fflush(stdout); - exit(-1); -} - - - +int main(int argc,char *argv[]){ + if(argc < 3){ + usage(argv[0]); + } + char *DIMACS_file = argv[1]; + // set time limit + int max_secs = atoi(argv[2]); + int num_threads = -1; + if(argc >= 4){ + for(int i = 3; i < argc; i++){ + if(strcmp(argv[i],"-n") == 0){ + num_threads = atoi(argv[i + 1]); + } + } + } + + // Load the graph from DIMACS_file + Graph::VertexWeightedGraph *G; + Graph::GraphCreatorFile creator; + creator.set_file_name(DIMACS_file); + creator.set_graph_type("DIMACS"); + G = creator.create_weighted_mutable_graph(); + + char mps_file[100], mod_file[100]; + + int status; + fprintf(stderr,"G has %d nodes, %d edges\n",G->get_num_nodes(), + G->get_num_edges()); + + // Write a GMPL model + sprintf(mod_file,"%s.mod",DIMACS_file); + write_ind_set_model(DIMACS_file, mod_file, G); + // Write mps file + sprintf(mps_file,"%s.mps",DIMACS_file); + create_mps_file(mod_file,mps_file,false); + + CPXENVptr env = NULL; + env = CPXopenCPLEX (&status); + check_CPX_status("CPXopenCPLEX",status); + + CPXsetintparam (env, CPX_PARAM_SCRIND, CPX_OFF); + + clock_t start = clock(),stop; + CPXLPptr mip; + mip = CPXcreateprob(env,&status,mps_file); + status = CPXreadcopyprob (env, mip, mps_file, NULL); + check_CPX_status("CPXreadcopyprob",status); + CPXsetdblparam(env, CPX_PARAM_TILIM, max_secs); + + if(num_threads != -1){ + // Set # of threads + CPXsetintparam(env,CPX_PARAM_THREADS,num_threads); + } + + int num_cols = CPXgetnumcols(env,mip); + int num_rows = CPXgetnumrows(env,mip); + + int mip_status = CPXmipopt(env,mip); + double obj; + CPXgetobjval(env,mip,&obj); + int objval = (int)obj; + stop = clock(); + fprintf(stdout,"%s %d %d %d %d %d %3.3f\n",DIMACS_file,num_cols, num_rows,mip_status, + -objval,getHWmem(),(double)(stop - start) / CLOCKS_PER_SEC); + fflush(stdout); + exit(-1); +} // main diff --git a/util/src/complement.cpp b/util/src/complement.cpp old mode 100755 new mode 100644 index d63b6b5..843f731 --- a/util/src/complement.cpp +++ b/util/src/complement.cpp @@ -1,23 +1,23 @@ /* -This file is part of INDDGO. + This file is part of INDDGO. -Copyright (C) 2012, Oak Ridge National Laboratory + Copyright (C) 2012, Oak Ridge National Laboratory -This product includes software produced by UT-Battelle, LLC under Contract No. -DE-AC05-00OR22725 with the Department of Energy. + This product includes software produced by UT-Battelle, LLC under Contract No. + DE-AC05-00OR22725 with the Department of Energy. -This program is free software; you can redistribute it and/or modify -it under the terms of the New BSD 3-clause software license (LICENSE). + This program is free software; you can redistribute it and/or modify + it under the terms of the New BSD 3-clause software license (LICENSE). -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -LICENSE for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + LICENSE for more details. -For more information please contact the INDDGO developers at: -inddgo-info@googlegroups.com + For more information please contact the INDDGO developers at: + inddgo-info@googlegroups.com -*/ + */ #include "GraphDecomposition.h" #include "TreeDecomposition.h" @@ -28,39 +28,38 @@ inddgo-info@googlegroups.com #include "VertexWeightedGraph.h" -void usage(char *str) -{ - fprintf(stderr,"%s \n\tWrites the complement graph of the provided\n" - "\tDIMACS file to .comp.norm\n" - "\tin normalized DIMACS form\n", str); - exit(-1); +void usage(char *str){ + fprintf(stderr,"%s \n\tWrites the complement graph of the provided\n" + "\tDIMACS file to .comp.norm\n" + "\tin normalized DIMACS form\n", str); + exit(-1); }; -int main(int argc, char **argv) -{ - if(argc!=2 || strcmp(argv[1],"-h")==0 || strcmp(argv[1],"--help")==0) - usage(argv[0]); +int main(int argc, char **argv){ + if((argc != 2) || (strcmp(argv[1],"-h") == 0) || (strcmp(argv[1],"--help") == 0) ){ + usage(argv[0]); + } - Graph::VertexWeightedGraph *G; - - Graph::GraphCreatorFile creator; - creator.set_file_name(argv[1]); - creator.set_graph_type("DIMACS"); - G = creator.create_weighted_mutable_graph(); - G->complement(); - Graph::GraphWriter writer; - - char comp_DIMACS_file[200]; - char normalized_comp_DIMACS_file[200]; - sprintf(comp_DIMACS_file,"%s.comp",argv[1]); - writer.write_graph(G,comp_DIMACS_file,"DIMACS",true,false); - // Now normalize it - sprintf(normalized_comp_DIMACS_file,"%s.norm",comp_DIMACS_file); - normalize_DIMACS_file(comp_DIMACS_file,normalized_comp_DIMACS_file); - fprintf(stderr,"Complement graph of %s written to %s in normalized DIMACS form\n", - argv[1],normalized_comp_DIMACS_file); + Graph::VertexWeightedGraph *G; - delete G; - return 1; -} + Graph::GraphCreatorFile creator; + creator.set_file_name(argv[1]); + creator.set_graph_type("DIMACS"); + G = creator.create_weighted_mutable_graph(); + G->complement(); + Graph::GraphWriter writer; + + char comp_DIMACS_file[200]; + char normalized_comp_DIMACS_file[200]; + sprintf(comp_DIMACS_file,"%s.comp",argv[1]); + writer.write_graph(G,comp_DIMACS_file,"DIMACS",true,false); + // Now normalize it + sprintf(normalized_comp_DIMACS_file,"%s.norm",comp_DIMACS_file); + normalize_DIMACS_file(comp_DIMACS_file,normalized_comp_DIMACS_file); + fprintf(stderr,"Complement graph of %s written to %s in normalized DIMACS form\n", + argv[1],normalized_comp_DIMACS_file); + + delete G; + return 1; +} // main diff --git a/util/src/count-tri.cpp b/util/src/count-tri.cpp index e0bb0bf..20419a6 100644 --- a/util/src/count-tri.cpp +++ b/util/src/count-tri.cpp @@ -21,21 +21,21 @@ #if !WIN32 && !CYGWIN -#include "GraphDecomposition.h" -#include "GraphProperties.h" -#include "Log.h" -#include "VertexWeightedGraph.h" -#include "GraphException.h" -#include "GraphReader.h" -#include "GraphWriter.h" -#include -#include -#include -#include -#include -#include -#include "orbconfig.h" -#include "orbtimer.h" + #include "GraphDecomposition.h" + #include "GraphProperties.h" + #include "Log.h" + #include "VertexWeightedGraph.h" + #include "GraphException.h" + #include "GraphReader.h" + #include "GraphWriter.h" + #include + #include + #include + #include + #include + #include + #include "orbconfig.h" + #include "orbtimer.h" using namespace std; @@ -136,13 +136,12 @@ int main(int argc, char **argv){ return 0; } // main - -#else -#include -int main() -{ - fprintf(stderr,"Can't build under windows or cygwin\n"); - return 0; +#else // if !WIN32 && !CYGWIN + #include +int main(){ + fprintf(stderr,"Can't build under windows or cygwin\n"); + return 0; } -#endif + +#endif // if !WIN32 && !CYGWIN diff --git a/util/src/gconvert.cpp b/util/src/gconvert.cpp index dc5b14a..65a1ef7 100644 --- a/util/src/gconvert.cpp +++ b/util/src/gconvert.cpp @@ -28,13 +28,14 @@ #include "GraphWriter.h" #if !WIN32 && !CYGWIN -#include "orbconfig.h" -#include "orbtimer.h" + #include "orbconfig.h" + #include "orbtimer.h" using namespace std; void print_time(string prefix, ORB_t start, ORB_t end){ cout << prefix + ": " << ORB_seconds(end, start) << "\n"; } + #endif void usage(const char *s){ @@ -42,7 +43,7 @@ void usage(const char *s){ } int main(int argc, char **argv){ -#if !WIN32 & !CYGWIN + #if !WIN32 & !CYGWIN ORB_t t1, t2; char *intype, *outtype, *infile, *outfile; @@ -108,9 +109,9 @@ int main(int argc, char **argv){ print_time("Time(write_graph)", t1, t2); return 0; -#else - fprintf(stderr,"Can't build under Cygwin or Windows\n"); - return 1; -#endif + #else // if !WIN32 & !CYGWIN + fprintf(stderr,"Can't build under Cygwin or Windows\n"); + return 1; + #endif // if !WIN32 & !CYGWIN } // main diff --git a/util/src/gen_pkt.cpp b/util/src/gen_pkt.cpp index 1e1bd71..7b0b3f6 100644 --- a/util/src/gen_pkt.cpp +++ b/util/src/gen_pkt.cpp @@ -26,16 +26,15 @@ #include "GraphWriter.h" #if !WIN32 && !CYGWIN -#include "orbconfig.h" -#include "orbtimer.h" + #include "orbconfig.h" + #include "orbtimer.h" #else -#define ORB_t clock_t -#define ORB_seconds(x,y) "lame" -#define ORB_calibrate() -#define ORB_read(x) + #define ORB_t clock_t + #define ORB_seconds(x,y) "lame" + #define ORB_calibrate() + #define ORB_read(x) #endif - using namespace std; void usage(const char *s){ @@ -69,7 +68,7 @@ int main(int argc, char **argv){ exit(-1); } - ORB_t t1=0, t2=0, t3=0; + ORB_t t1 = 0, t2 = 0, t3 = 0; int i; int t = 1; int ktree_n = -1, ktree_k = -1, ktree_p = -1; diff --git a/util/src/graph_stats.cpp b/util/src/graph_stats.cpp index 48c65dc..7bf416c 100644 --- a/util/src/graph_stats.cpp +++ b/util/src/graph_stats.cpp @@ -33,12 +33,12 @@ #include "GraphException.h" #if !WIN32 && !CYGWIN -#include "orbconfig.h" -#include "orbtimer.h" + #include "orbconfig.h" + #include "orbtimer.h" -#ifdef HAS_SLEPC - #include -#endif + #ifdef HAS_SLEPC + #include + #endif using namespace std; @@ -383,9 +383,10 @@ int main(int argc, char **argv){ create_map(allowed_methods, val_methods); parse_options(argc, argv, infile, intype, outfilename, outprefix, req_methods, record_timings, file_append, &spectrum_spread); if(outfilename.length() == 0){ - if(outprefix.length() != 0) { - outfilename = outprefix+".stats"; - } else { + if(outprefix.length() != 0){ + outfilename = outprefix + ".stats"; + } + else { outfilename = "graph-stats.txt"; } } @@ -432,7 +433,6 @@ int main(int argc, char **argv){ exit(1); } - // Read in the graph and start recording things to output streams cout << "Reading graph" << endl; ORB_read(t1); @@ -451,7 +451,8 @@ int main(int argc, char **argv){ string of = outfilename + ".timings"; if(file_append == false){ timing_file.open(of.c_str()); - } else { + } + else { timing_file.open(of.c_str(), ios_base::out | ios_base::app); } if(!timing_file.is_open()){ @@ -463,7 +464,6 @@ int main(int argc, char **argv){ print_time(timing_file, "Time(read_graph)", t1, t2); - outfile.precision(16); vector components; cout << "Graph is connected?: " << std::boolalpha << gp.is_connected(g) << endl; @@ -483,7 +483,7 @@ int main(int argc, char **argv){ // some algorithms only make sense to run on a connected graph/component if(not is_connected){ // run everything against the other algorithms cout << "Graph is not connected, re-running stats on largest connected component" << endl; - outfilename = outprefix+".largest_component.stats"; + outfilename = outprefix + ".largest_component.stats"; if(file_append == false){ outfile.open(outfilename.c_str()); } @@ -508,7 +508,8 @@ int main(int argc, char **argv){ string of = outfilename + ".timings"; if(file_append == false){ timing_file.open(of.c_str()); - } else { + } + else { timing_file.open(of.c_str(), ios_base::out | ios_base::app); } @@ -530,10 +531,10 @@ int main(int argc, char **argv){ exit(0); } // main -#else -int main() -{ - fprintf(stderr,"Can't run under windows or cygwin\n"); - return 0; +#else // if !WIN32 && !CYGWIN +int main(){ + fprintf(stderr,"Can't run under windows or cygwin\n"); + return 0; } -#endif + +#endif // if !WIN32 && !CYGWIN diff --git a/util/src/orbtimer.cpp b/util/src/orbtimer.cpp index d53302a..0f6e1a8 100644 --- a/util/src/orbtimer.cpp +++ b/util/src/orbtimer.cpp @@ -28,26 +28,26 @@ * **************************************************************************/ #if !WIN32 -#if !CYGWIN + #if !CYGWIN -#include -#include -#include "orbconfig.h" + #include + #include + #include "orbconfig.h" -#define ORBTIMER_LIBRARY -#include "orbtimer.h" + #define ORBTIMER_LIBRARY + #include "orbtimer.h" static ORB_tick_t Csum = 0; static ORB_tick_t Gsum = 0; static ORB_tick_t nsamples = 0; static ORB_tick_t ndummy = 0; -#endif + #endif #endif void ORB_calibrate(){ -#if WIN32 || CYGWIN || _CYGWIN - return; -#else + #if WIN32 || CYGWIN || _CYGWIN + return; + #else int i, j; double seconds; struct timeval tv1, tv2; @@ -111,8 +111,6 @@ void ORB_calibrate(){ ORB_min_lat_sec = ORB_min_lat_cyc / ORB_ref_freq; GTD_avg_lat_sec = GTD_avg_lat_cyc / ORB_ref_freq; GTD_min_lat_sec = GTD_min_lat_cyc / ORB_ref_freq; -#endif + #endif // if WIN32 || CYGWIN || _CYGWIN } // ORB_calibrate - - From c0972c716537e802efec9d1a6a50326e04424810 Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Wed, 25 Sep 2013 09:57:28 -0400 Subject: [PATCH 69/73] fix output for largest components --- util/src/graph_stats.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/util/src/graph_stats.cpp b/util/src/graph_stats.cpp index 237fb65..9ebc35a 100644 --- a/util/src/graph_stats.cpp +++ b/util/src/graph_stats.cpp @@ -509,10 +509,15 @@ int main(int argc, char **argv){ cerr << "Error opening " << outfilename << " for writing, exiting" << endl; exit(1); } + + // get the largest component + Graph::Graph *largest_component = gu.get_largest_component_graph(g); + delete(g); // delete g here to save on memory + if(outfile.tellp() == 0){ outfile << "filename " << infile << endl; - outfile << "num_nodes " << g->get_num_nodes() << endl; - outfile << "num_edges " << g->get_num_edges() << endl; + outfile << "num_nodes " << largest_component->get_num_nodes() << endl; + outfile << "num_edges " << largest_component->get_num_edges() << endl; } if(record_timings){ string of = outfilename + ".timings"; @@ -532,10 +537,6 @@ int main(int argc, char **argv){ outprefix = outprefix + ".largest_component"; outfile.precision(16); - outfile << "filename" << infile << endl; - Graph::Graph *largest_component = gu.get_largest_component_graph(g); - delete(g); // delete g here to save on memory - run_all_methods(largest_component, outfile, timing_file, outprefix, req_methods, file_append, spectrum_spread); outfile.close(); timing_file.close(); From 23c7c4ef305a571c3c58c68513d9ebe93188e0a1 Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Thu, 26 Sep 2013 14:34:23 -0400 Subject: [PATCH 70/73] fix merge --- lib_graphd/inc/Graph.h | 71 +++-- lib_graphd/inc/GraphReader.h | 2 +- lib_graphd/inc/GraphWriter.h | 2 +- lib_graphd/src/Graph.cpp | 5 +- lib_graphd/src/GraphCreator.cpp | 19 +- lib_graphd/src/GraphProperties.cpp | 12 +- lib_graphd/src/GraphReader.cpp | 2 +- lib_graphd/src/GraphUtil.cpp | 131 ++++----- util/src/CPX_solve_wis.cpp | 425 ++++++++++++++--------------- util/src/complement.cpp | 87 +++--- util/src/count-tri.cpp | 45 ++- util/src/gconvert.cpp | 15 +- util/src/gen_pkt.cpp | 15 +- util/src/graph_stats.cpp | 40 +-- util/src/orbtimer.cpp | 24 +- 15 files changed, 441 insertions(+), 454 deletions(-) mode change 100755 => 100644 util/src/CPX_solve_wis.cpp mode change 100755 => 100644 util/src/complement.cpp diff --git a/lib_graphd/inc/Graph.h b/lib_graphd/inc/Graph.h index 6c25d47..4660632 100644 --- a/lib_graphd/inc/Graph.h +++ b/lib_graphd/inc/Graph.h @@ -21,60 +21,59 @@ /*This fixes any issues with MSVC always having HAS_METIS defined*/ #ifdef _MSC_VER - #if !HAS_METIS - #undef HAS_METIS + #if !HAS_METIS + #undef HAS_METIS #endif -#endif - +#endif #ifndef GRAPH_H_ -#define GRAPH_H_ - -#ifdef _OPENMP - #include -#else - #ifndef HAS_METIS - #define omp_get_num_threads() 1 - #define omp_get_thread_num() 0 - #define omp_get_max_threads() 1 + #define GRAPH_H_ + + #ifdef _OPENMP + #include + #else + #ifndef HAS_METIS + #define omp_get_num_threads() 1 + #define omp_get_thread_num() 0 + #define omp_get_max_threads() 1 + #endif #endif -#endif -#ifdef HAS_PETSC - #include -#endif + #ifdef HAS_PETSC + #include + #endif -#if WIN32 -#define strncasecmp strncmp -#endif + #if WIN32 + #define strncasecmp strncmp + #endif -#include "GraphInterface.h" -#include "Node.h" -#include "GraphException.h" -#include "Log.h" -#include + #include "GraphInterface.h" + #include "Node.h" + #include "GraphException.h" + #include "Log.h" + #include -#ifdef HAS_BOOST - #include - #include - #include + #ifdef HAS_BOOST + #include + #include + #include - #include "boost/graph/adjacency_list.hpp" - #include "boost/graph/topological_sort.hpp" - #include -#endif + #include "boost/graph/adjacency_list.hpp" + #include "boost/graph/topological_sort.hpp" + #include + #endif using namespace std; -#define INDDGO_INFINITY INT_MAX - 16 + #define INDDGO_INFINITY INT_MAX - 16 -#ifdef HAS_BOOST + #ifdef HAS_BOOST typedef boost::property EdgeWeightProperty; typedef boost::property CentralityMap; typedef boost::adjacency_list BoostUndirected; typedef boost::graph_traits < BoostUndirected >::vertex_descriptor vertex_descriptor; typedef boost::graph_traits < BoostUndirected >::edge_descriptor edge_descriptor; -#endif //HAS_BOOST + #endif //HAS_BOOST namespace Graph { class Graph : public GraphInterface diff --git a/lib_graphd/inc/GraphReader.h b/lib_graphd/inc/GraphReader.h index 2ee7f18..57f2a59 100644 --- a/lib_graphd/inc/GraphReader.h +++ b/lib_graphd/inc/GraphReader.h @@ -29,7 +29,7 @@ #include "Debug.h" #include #if !WIN32 -#include + #include #endif #include #include diff --git a/lib_graphd/inc/GraphWriter.h b/lib_graphd/inc/GraphWriter.h index b82fe97..1954ebc 100644 --- a/lib_graphd/inc/GraphWriter.h +++ b/lib_graphd/inc/GraphWriter.h @@ -29,7 +29,7 @@ #include "Debug.h" #include #if !WIN32 -#include + #include #endif #include #include diff --git a/lib_graphd/src/Graph.cpp b/lib_graphd/src/Graph.cpp index c58a050..e21633a 100644 --- a/lib_graphd/src/Graph.cpp +++ b/lib_graphd/src/Graph.cpp @@ -28,7 +28,6 @@ #include #include - #ifndef _OPENMP #ifdef HAS_METIS void omp_set_num_threads(int num_threads){ @@ -778,7 +777,7 @@ namespace Graph { * otherwise computes then returns **/ const vector< vector > &Graph::get_shortest_path_dist_ref(){ - if(this->apsp_dist == NULL) { + if(this->apsp_dist == NULL){ this->apsp_dist = new(vector< vector >); } if(this->apsp_dist->empty()){ @@ -790,7 +789,7 @@ namespace Graph { } const vector &Graph::get_u_shortest_path_dist(int u){ - if(this->apsp_dist == NULL) { + if(this->apsp_dist == NULL){ this->apsp_dist = new(vector< vector >); } if(this->apsp_dist[u].empty()){ diff --git a/lib_graphd/src/GraphCreator.cpp b/lib_graphd/src/GraphCreator.cpp index e68254c..e77f852 100644 --- a/lib_graphd/src/GraphCreator.cpp +++ b/lib_graphd/src/GraphCreator.cpp @@ -63,13 +63,16 @@ namespace Graph { unsigned long y = 0; for(int j = l - 1; j >= 0; j--){ double r = lcgrand(0); - if(r < q1) { - } else if(r < q2) { - // pow(2,j)?? 1< #if !WIN32 -#include + #include #endif #include @@ -496,7 +496,7 @@ namespace Graph { } //if revmap } //for vtxs } //for fakev - int tsize=(int)t.size(); + int tsize = (int)t.size(); #pragma omp for for(i = 0; i < tsize; i++){ for(int j = 0; j < omp_get_num_threads(); j++){ @@ -840,14 +840,14 @@ namespace Graph { freq_ecc.resize(*(std::max_element(ecc.begin(), ecc.end())) + 1); //compute diameter of each vertex - int eccsize=ecc.size(); - // This could be slow with resizing - for(int i = 0; i < eccsize ; i++){ + int eccsize = ecc.size(); + // This could be slow with resizing + for(int i = 0; i < eccsize; i++){ freq_ecc[ecc[i]]++; //add to tally for this diameter size } //printf("Graph diameter is %d\n", freq_ecc.size()-1); - int freq_ecc_size=freq_ecc.size(); + int freq_ecc_size = freq_ecc.size(); #pragma omp parallel for default(none) shared(freq_ecc, freq_ecc_size) for(int i = 0; i <= freq_ecc_size - 1; i++){ freq_ecc[i] = freq_ecc[i] / n; diff --git a/lib_graphd/src/GraphReader.cpp b/lib_graphd/src/GraphReader.cpp index 7712af7..66267ad 100644 --- a/lib_graphd/src/GraphReader.cpp +++ b/lib_graphd/src/GraphReader.cpp @@ -24,7 +24,7 @@ #include "Debug.h" #include "Util.h" #if !WIN32 -#include + #include #endif #include #include diff --git a/lib_graphd/src/GraphUtil.cpp b/lib_graphd/src/GraphUtil.cpp index 463167d..f46b6cc 100644 --- a/lib_graphd/src/GraphUtil.cpp +++ b/lib_graphd/src/GraphUtil.cpp @@ -857,71 +857,72 @@ namespace Graph { return max; } // subset_max_dist - /** - * Calculates the k-core number of every vertex and stores in kcore vector - * Return value is degeneracy (maximum non-empty k-core). - * Uses algorithm of Batagelj and Zaversnik (2003) - * Implemented by Timothy Goodrich and Matthew Farrell (2013) - */ - int GraphUtil::find_kcore(Graph *g, vector *kcore) { - int n = g->num_nodes; - int k = 0; - int last_deg = 0; - kcore->resize(n); - - vector deg_lookup(n); - int max_deg = 0; - int deg_size=deg_lookup.size(); - for(int i = 0; i < deg_size; i++) { - deg_lookup[i] = g->degree[i]; - if(deg_lookup[i] > max_deg) - max_deg = deg_lookup[i]; - } - vector > D; - D.resize(max_deg+1); - - int *depth; - depth=new int[n]; - //int depth[n]; - //can also create an L output list for coloring number optimal ordering - - for(int i = 0; i < n; i++) { - deg_lookup[i] = g->degree[i]; - D[deg_lookup[i]].push_back(i); - depth[i] = D[deg_lookup[i]].size()-1; - } - - for(int i = 0; i < n; i++) { - int v; - for(int j = last_deg; j <= max_deg; j++) { - if(D[j].size() != 0) { - v = D[j].back(); - D[j].pop_back(); - break; - } - } - - (*kcore)[v] = k = max(k,deg_lookup[v]); - last_deg = max(0, deg_lookup[v]-1); - deg_lookup[v] = -1; - - //shift each of v's neighbors down one degree - list * nbrs = g->nodes[v].get_nbrs_ptr(); - list::const_iterator it; - for(it = nbrs->begin(); it != nbrs->end(); it++) { - if(deg_lookup[*it] != -1) { - int it_deg = deg_lookup[*it]--; - D[it_deg][depth[*it]] = D[it_deg][D[it_deg].size()-1]; - depth[D[it_deg][depth[*it]]] = depth[*it]; - D[it_deg].pop_back(); - D[it_deg-1].push_back(*it); - depth[*it] = D[it_deg-1].size()-1; - } - } - } - delete [] depth; - return k; - } // find_degen + /** + * Calculates the k-core number of every vertex and stores in kcore vector + * Return value is degeneracy (maximum non-empty k-core). + * Uses algorithm of Batagelj and Zaversnik (2003) + * Implemented by Timothy Goodrich and Matthew Farrell (2013) + */ + int GraphUtil::find_kcore(Graph *g, vector *kcore){ + int n = g->num_nodes; + int k = 0; + int last_deg = 0; + kcore->resize(n); + + vector deg_lookup(n); + int max_deg = 0; + int deg_size = deg_lookup.size(); + for(int i = 0; i < deg_size; i++){ + deg_lookup[i] = g->degree[i]; + if(deg_lookup[i] > max_deg){ + max_deg = deg_lookup[i]; + } + } + vector > D; + D.resize(max_deg + 1); + + int *depth; + depth = new int[n]; + //int depth[n]; + //can also create an L output list for coloring number optimal ordering + + for(int i = 0; i < n; i++){ + deg_lookup[i] = g->degree[i]; + D[deg_lookup[i]].push_back(i); + depth[i] = D[deg_lookup[i]].size() - 1; + } + + for(int i = 0; i < n; i++){ + int v; + for(int j = last_deg; j <= max_deg; j++){ + if(D[j].size() != 0){ + v = D[j].back(); + D[j].pop_back(); + break; + } + } + + (*kcore)[v] = k = max(k,deg_lookup[v]); + last_deg = max(0, deg_lookup[v] - 1); + deg_lookup[v] = -1; + + //shift each of v's neighbors down one degree + list *nbrs = g->nodes[v].get_nbrs_ptr(); + list::const_iterator it; + for(it = nbrs->begin(); it != nbrs->end(); it++){ + if(deg_lookup[*it] != -1){ + int it_deg = deg_lookup[*it]--; + D[it_deg][depth[*it]] = D[it_deg][D[it_deg].size() - 1]; + depth[D[it_deg][depth[*it]]] = depth[*it]; + D[it_deg].pop_back(); + D[it_deg - 1].push_back(*it); + depth[*it] = D[it_deg - 1].size() - 1; + } + } + } + delete [] depth; + return k; + } // find_degen /** * \input g input graph diff --git a/util/src/CPX_solve_wis.cpp b/util/src/CPX_solve_wis.cpp old mode 100755 new mode 100644 index 89e88ec..802d63b --- a/util/src/CPX_solve_wis.cpp +++ b/util/src/CPX_solve_wis.cpp @@ -8,231 +8,220 @@ #include "GraphDecomposition.h" -void check_CPX_status(char *func, int status) -{ - if (status) - { - fprintf (stderr, "CPX nonzero status after %s: %d\n",func,status); - exit(-1); - } +void check_CPX_status(char *func, int status){ + if(status){ + fprintf (stderr, "CPX nonzero status after %s: %d\n",func,status); + exit(-1); + } }; void write_ind_set_model(const char *DIMACS_file, const char *model_file, - Graph::VertexWeightedGraph *G) -{ - int i, j; - - FILE *out = fopen(model_file, "w"); - if (!out) - fatal_error("Can't open %s for writing\n", model_file); - - // Write out the model - fprintf(out, - "# Automatically generated model file for max independent set\n" - "# Assumes 1-based node names with no holes!!\n" - "# Original graph file is %s\n" - "# Model section\n\n" - "param num_nodes ;\n" - "set Nodes := 1..num_nodes ;\n" - "set E within Nodes cross Nodes ;\n" - "param w{Nodes};\n" - "var x{i in Nodes} binary;\n\n" - // Change to minimization for archaic MPS reasons - "minimize Cost: sum{i in Nodes} -x[i]*w[i];\n\n" - "subject to Independent{i in Nodes, j in Nodes: (i,j) in E}:\n" - "x[i]+x[j]<=1;\n\n" - "solve;\n\n", DIMACS_file); - /* - fprintf( - out, - "printf \" \\nMaximum Independent Set: %%d\\n\", sum{i in Nodes} x[i]*w[i] > \"%s\";\n", - sol_file); - fprintf(out, "for { i in Nodes }\n" - "{\n" - " printf{0..0: x[i]!=0} \"%%d (%%3.1f)\\n\", i, w[i] >> \"%s\";\n", - sol_file); - fprintf(out, "}\n\n");*/ - fflush(out); - fprintf(stderr,"Writing data section\n"); - - fprintf(out, "# Data Section\n\ndata;\n\n"); - fflush(out); - // Write out the problem data - fprintf(out, "param num_nodes:=%d;\n", G->get_num_nodes()); - fflush(out); - fprintf(out, "param w:=\n"); - fflush(out); - vector nodes = G->get_nodes(); - vector weight = G->get_weight(); - - for (i = 0; i < G->get_num_nodes(); i++) - { - fprintf(out, "%d %d\n",nodes[i].get_label(), weight[i]); - } - fprintf(out, ";\n"); - fprintf(out, "set E:=\n"); - Graph::GraphProperties properties; - - vector adj_vec; - for (i = 0; i < G->get_num_nodes(); i++) - { - // This assumes 1-based labeling! - int current_key = properties.fill_adj_vec(G, i); - //int current_key=G->fill_adj_vec(i); - adj_vec = G->get_adj_vec(); - for (j = i + 1; j < G->get_num_nodes(); j++) - { - if (adj_vec[j] == current_key) - fprintf(out, "(%d,%d)\n", i + 1, j + 1); - } - fprintf(out, "\n"); - } - fprintf(out, ";\nend;\n"); - fclose(out); + Graph::VertexWeightedGraph *G){ + int i, j; + + FILE *out = fopen(model_file, "w"); + if(!out){ + fatal_error("Can't open %s for writing\n", model_file); + } + + // Write out the model + fprintf(out, + "# Automatically generated model file for max independent set\n" + "# Assumes 1-based node names with no holes!!\n" + "# Original graph file is %s\n" + "# Model section\n\n" + "param num_nodes ;\n" + "set Nodes := 1..num_nodes ;\n" + "set E within Nodes cross Nodes ;\n" + "param w{Nodes};\n" + "var x{i in Nodes} binary;\n\n" + // Change to minimization for archaic MPS reasons + "minimize Cost: sum{i in Nodes} -x[i]*w[i];\n\n" + "subject to Independent{i in Nodes, j in Nodes: (i,j) in E}:\n" + "x[i]+x[j]<=1;\n\n" + "solve;\n\n", DIMACS_file); + /* + fprintf( + out, + "printf \" \\nMaximum Independent Set: %%d\\n\", sum{i in Nodes} x[i]*w[i] > \"%s\";\n", + sol_file); + fprintf(out, "for { i in Nodes }\n" + "{\n" + " printf{0..0: x[i]!=0} \"%%d (%%3.1f)\\n\", i, w[i] >> \"%s\";\n", + sol_file); + fprintf(out, "}\n\n");*/ + fflush(out); + fprintf(stderr,"Writing data section\n"); + + fprintf(out, "# Data Section\n\ndata;\n\n"); + fflush(out); + // Write out the problem data + fprintf(out, "param num_nodes:=%d;\n", G->get_num_nodes()); + fflush(out); + fprintf(out, "param w:=\n"); + fflush(out); + vector nodes = G->get_nodes(); + vector weight = G->get_weight(); + + for(i = 0; i < G->get_num_nodes(); i++){ + fprintf(out, "%d %d\n",nodes[i].get_label(), weight[i]); + } + fprintf(out, ";\n"); + fprintf(out, "set E:=\n"); + Graph::GraphProperties properties; + + vector adj_vec; + for(i = 0; i < G->get_num_nodes(); i++){ + // This assumes 1-based labeling! + int current_key = properties.fill_adj_vec(G, i); + //int current_key=G->fill_adj_vec(i); + adj_vec = G->get_adj_vec(); + for(j = i + 1; j < G->get_num_nodes(); j++){ + if(adj_vec[j] == current_key){ + fprintf(out, "(%d,%d)\n", i + 1, j + 1); + } + } + fprintf(out, "\n"); + } + fprintf(out, ";\nend;\n"); + fclose(out); }; -void read_DIMACS(const char *DIMACS_file, Graph::VertexWeightedGraph *G) -{ - int i; - Graph::GraphCreatorFile creator; - creator.set_file_name(DIMACS_file); - creator.set_graph_type("DIMACS"); - - G = creator.create_weighted_mutable_graph(); - if (!G) - { - fprintf(stderr,"Could not create graph for DIMACS file %s\n",DIMACS_file); - exit(-1); - } - - // Add weights of 1 to all vertices if we didn't load any from the file - bool has_weights = false; - vector weight = (G)->get_weight(); - for (i = 0; i < (G)->get_capacity(); i++) - { - if (weight[i] != 0) - { - has_weights = true; - break; - } - } - - if (!has_weights) - for (i = 0; i < (G)->get_capacity(); i++) - weight[i] = 1; - - fprintf(stderr,"Graph loaded with %d nodes, %d edges\n",G->get_num_nodes(), - G->get_num_edges()); +void read_DIMACS(const char *DIMACS_file, Graph::VertexWeightedGraph *G){ + int i; + Graph::GraphCreatorFile creator; + creator.set_file_name(DIMACS_file); + creator.set_graph_type("DIMACS"); + + G = creator.create_weighted_mutable_graph(); + if(!G){ + fprintf(stderr,"Could not create graph for DIMACS file %s\n",DIMACS_file); + exit(-1); + } + + // Add weights of 1 to all vertices if we didn't load any from the file + bool has_weights = false; + vector weight = (G)->get_weight(); + for(i = 0; i < (G)->get_capacity(); i++){ + if(weight[i] != 0){ + has_weights = true; + break; + } + } + + if(!has_weights){ + for(i = 0; i < (G)->get_capacity(); i++){ + weight[i] = 1; + } + } + + fprintf(stderr,"Graph loaded with %d nodes, %d edges\n",G->get_num_nodes(), + G->get_num_edges()); }; -void create_mps_file(char *gmpl_file, char *mps_file, bool verbose) -{ - // Read in the model - glp_prob *lp; - glp_tran *tran; - if(!verbose) - glp_term_out(GLP_OFF); - lp = glp_create_prob(); - tran = glp_mpl_alloc_wksp(); - fprintf(stderr,"reading model\n"); - int ret = glp_mpl_read_model(tran, gmpl_file , 0); - if (ret) - { - fprintf(stderr, "Error translating model\n"); - exit(-1); - } - ret = glp_mpl_generate(tran, NULL); - if (ret) - { - fprintf(stderr, "Error generating model\n"); - exit(-1); - } - - glp_mpl_build_prob(tran, lp); - ret = glp_write_mps(lp, GLP_MPS_FILE, NULL, mps_file); - if (ret) - { - fprintf(stderr, "Error on writing MPS file\n"); - exit(-1); - } - glp_mpl_free_wksp(tran); - glp_delete_prob(lp); - fprintf(stderr,"GLPK created MPS file %s\n",mps_file); +void create_mps_file(char *gmpl_file, char *mps_file, bool verbose){ + // Read in the model + glp_prob *lp; + glp_tran *tran; + if(!verbose){ + glp_term_out(GLP_OFF); + } + lp = glp_create_prob(); + tran = glp_mpl_alloc_wksp(); + fprintf(stderr,"reading model\n"); + int ret = glp_mpl_read_model(tran, gmpl_file, 0); + if(ret){ + fprintf(stderr, "Error translating model\n"); + exit(-1); + } + ret = glp_mpl_generate(tran, NULL); + if(ret){ + fprintf(stderr, "Error generating model\n"); + exit(-1); + } + + glp_mpl_build_prob(tran, lp); + ret = glp_write_mps(lp, GLP_MPS_FILE, NULL, mps_file); + if(ret){ + fprintf(stderr, "Error on writing MPS file\n"); + exit(-1); + } + glp_mpl_free_wksp(tran); + glp_delete_prob(lp); + fprintf(stderr,"GLPK created MPS file %s\n",mps_file); +} // create_mps_file + +void usage(char *str){ + fprintf(stderr,"%s [-n num_threads]\n" + "\t Uses CPLEX with num_threads to solve WIS with max_seconds time limit\n",str); + exit(-1); } -void usage(char *str) -{ - fprintf(stderr,"%s [-n num_threads]\n" - "\t Uses CPLEX with num_threads to solve WIS with max_seconds time limit\n",str); - exit(-1); -} - -int main(int argc,char *argv[]) -{ - if(argc<3) - usage(argv[0]); - char *DIMACS_file=argv[1]; - // set time limit - int max_secs=atoi(argv[2]); - int num_threads=-1; - if(argc>=4) - { - for(int i=3;iget_num_nodes(), - G->get_num_edges()); - - // Write a GMPL model - sprintf(mod_file,"%s.mod",DIMACS_file); - write_ind_set_model(DIMACS_file, mod_file, G); - // Write mps file - sprintf(mps_file,"%s.mps",DIMACS_file); - create_mps_file(mod_file,mps_file,false); - - CPXENVptr env = NULL; - env = CPXopenCPLEX (&status); - check_CPX_status("CPXopenCPLEX",status); - - CPXsetintparam (env, CPX_PARAM_SCRIND, CPX_OFF); - - clock_t start=clock(),stop; - CPXLPptr mip; - mip=CPXcreateprob(env,&status,mps_file); - status = CPXreadcopyprob (env, mip, mps_file, NULL); - check_CPX_status("CPXreadcopyprob",status); - CPXsetdblparam(env, CPX_PARAM_TILIM, max_secs); - - if(num_threads!=-1) - // Set # of threads - CPXsetintparam(env,CPX_PARAM_THREADS,num_threads); - - int num_cols=CPXgetnumcols(env,mip); - int num_rows=CPXgetnumrows(env,mip); - - int mip_status=CPXmipopt(env,mip); - double obj; - CPXgetobjval(env,mip,&obj); - int objval=(int)obj; - stop=clock(); - fprintf(stdout,"%s %d %d %d %d %d %3.3f\n",DIMACS_file,num_cols, num_rows,mip_status, - -objval,getHWmem(),(double)(stop-start)/CLOCKS_PER_SEC); - fflush(stdout); - exit(-1); -} - - - +int main(int argc,char *argv[]){ + if(argc < 3){ + usage(argv[0]); + } + char *DIMACS_file = argv[1]; + // set time limit + int max_secs = atoi(argv[2]); + int num_threads = -1; + if(argc >= 4){ + for(int i = 3; i < argc; i++){ + if(strcmp(argv[i],"-n") == 0){ + num_threads = atoi(argv[i + 1]); + } + } + } + + // Load the graph from DIMACS_file + Graph::VertexWeightedGraph *G; + Graph::GraphCreatorFile creator; + creator.set_file_name(DIMACS_file); + creator.set_graph_type("DIMACS"); + G = creator.create_weighted_mutable_graph(); + + char mps_file[100], mod_file[100]; + + int status; + fprintf(stderr,"G has %d nodes, %d edges\n",G->get_num_nodes(), + G->get_num_edges()); + + // Write a GMPL model + sprintf(mod_file,"%s.mod",DIMACS_file); + write_ind_set_model(DIMACS_file, mod_file, G); + // Write mps file + sprintf(mps_file,"%s.mps",DIMACS_file); + create_mps_file(mod_file,mps_file,false); + + CPXENVptr env = NULL; + env = CPXopenCPLEX (&status); + check_CPX_status("CPXopenCPLEX",status); + + CPXsetintparam (env, CPX_PARAM_SCRIND, CPX_OFF); + + clock_t start = clock(),stop; + CPXLPptr mip; + mip = CPXcreateprob(env,&status,mps_file); + status = CPXreadcopyprob (env, mip, mps_file, NULL); + check_CPX_status("CPXreadcopyprob",status); + CPXsetdblparam(env, CPX_PARAM_TILIM, max_secs); + + if(num_threads != -1){ + // Set # of threads + CPXsetintparam(env,CPX_PARAM_THREADS,num_threads); + } + + int num_cols = CPXgetnumcols(env,mip); + int num_rows = CPXgetnumrows(env,mip); + + int mip_status = CPXmipopt(env,mip); + double obj; + CPXgetobjval(env,mip,&obj); + int objval = (int)obj; + stop = clock(); + fprintf(stdout,"%s %d %d %d %d %d %3.3f\n",DIMACS_file,num_cols, num_rows,mip_status, + -objval,getHWmem(),(double)(stop - start) / CLOCKS_PER_SEC); + fflush(stdout); + exit(-1); +} // main diff --git a/util/src/complement.cpp b/util/src/complement.cpp old mode 100755 new mode 100644 index d63b6b5..843f731 --- a/util/src/complement.cpp +++ b/util/src/complement.cpp @@ -1,23 +1,23 @@ /* -This file is part of INDDGO. + This file is part of INDDGO. -Copyright (C) 2012, Oak Ridge National Laboratory + Copyright (C) 2012, Oak Ridge National Laboratory -This product includes software produced by UT-Battelle, LLC under Contract No. -DE-AC05-00OR22725 with the Department of Energy. + This product includes software produced by UT-Battelle, LLC under Contract No. + DE-AC05-00OR22725 with the Department of Energy. -This program is free software; you can redistribute it and/or modify -it under the terms of the New BSD 3-clause software license (LICENSE). + This program is free software; you can redistribute it and/or modify + it under the terms of the New BSD 3-clause software license (LICENSE). -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -LICENSE for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + LICENSE for more details. -For more information please contact the INDDGO developers at: -inddgo-info@googlegroups.com + For more information please contact the INDDGO developers at: + inddgo-info@googlegroups.com -*/ + */ #include "GraphDecomposition.h" #include "TreeDecomposition.h" @@ -28,39 +28,38 @@ inddgo-info@googlegroups.com #include "VertexWeightedGraph.h" -void usage(char *str) -{ - fprintf(stderr,"%s \n\tWrites the complement graph of the provided\n" - "\tDIMACS file to .comp.norm\n" - "\tin normalized DIMACS form\n", str); - exit(-1); +void usage(char *str){ + fprintf(stderr,"%s \n\tWrites the complement graph of the provided\n" + "\tDIMACS file to .comp.norm\n" + "\tin normalized DIMACS form\n", str); + exit(-1); }; -int main(int argc, char **argv) -{ - if(argc!=2 || strcmp(argv[1],"-h")==0 || strcmp(argv[1],"--help")==0) - usage(argv[0]); +int main(int argc, char **argv){ + if((argc != 2) || (strcmp(argv[1],"-h") == 0) || (strcmp(argv[1],"--help") == 0) ){ + usage(argv[0]); + } - Graph::VertexWeightedGraph *G; - - Graph::GraphCreatorFile creator; - creator.set_file_name(argv[1]); - creator.set_graph_type("DIMACS"); - G = creator.create_weighted_mutable_graph(); - G->complement(); - Graph::GraphWriter writer; - - char comp_DIMACS_file[200]; - char normalized_comp_DIMACS_file[200]; - sprintf(comp_DIMACS_file,"%s.comp",argv[1]); - writer.write_graph(G,comp_DIMACS_file,"DIMACS",true,false); - // Now normalize it - sprintf(normalized_comp_DIMACS_file,"%s.norm",comp_DIMACS_file); - normalize_DIMACS_file(comp_DIMACS_file,normalized_comp_DIMACS_file); - fprintf(stderr,"Complement graph of %s written to %s in normalized DIMACS form\n", - argv[1],normalized_comp_DIMACS_file); + Graph::VertexWeightedGraph *G; - delete G; - return 1; -} + Graph::GraphCreatorFile creator; + creator.set_file_name(argv[1]); + creator.set_graph_type("DIMACS"); + G = creator.create_weighted_mutable_graph(); + G->complement(); + Graph::GraphWriter writer; + + char comp_DIMACS_file[200]; + char normalized_comp_DIMACS_file[200]; + sprintf(comp_DIMACS_file,"%s.comp",argv[1]); + writer.write_graph(G,comp_DIMACS_file,"DIMACS",true,false); + // Now normalize it + sprintf(normalized_comp_DIMACS_file,"%s.norm",comp_DIMACS_file); + normalize_DIMACS_file(comp_DIMACS_file,normalized_comp_DIMACS_file); + fprintf(stderr,"Complement graph of %s written to %s in normalized DIMACS form\n", + argv[1],normalized_comp_DIMACS_file); + + delete G; + return 1; +} // main diff --git a/util/src/count-tri.cpp b/util/src/count-tri.cpp index e0bb0bf..20419a6 100644 --- a/util/src/count-tri.cpp +++ b/util/src/count-tri.cpp @@ -21,21 +21,21 @@ #if !WIN32 && !CYGWIN -#include "GraphDecomposition.h" -#include "GraphProperties.h" -#include "Log.h" -#include "VertexWeightedGraph.h" -#include "GraphException.h" -#include "GraphReader.h" -#include "GraphWriter.h" -#include -#include -#include -#include -#include -#include -#include "orbconfig.h" -#include "orbtimer.h" + #include "GraphDecomposition.h" + #include "GraphProperties.h" + #include "Log.h" + #include "VertexWeightedGraph.h" + #include "GraphException.h" + #include "GraphReader.h" + #include "GraphWriter.h" + #include + #include + #include + #include + #include + #include + #include "orbconfig.h" + #include "orbtimer.h" using namespace std; @@ -136,13 +136,12 @@ int main(int argc, char **argv){ return 0; } // main - -#else -#include -int main() -{ - fprintf(stderr,"Can't build under windows or cygwin\n"); - return 0; +#else // if !WIN32 && !CYGWIN + #include +int main(){ + fprintf(stderr,"Can't build under windows or cygwin\n"); + return 0; } -#endif + +#endif // if !WIN32 && !CYGWIN diff --git a/util/src/gconvert.cpp b/util/src/gconvert.cpp index dc5b14a..65a1ef7 100644 --- a/util/src/gconvert.cpp +++ b/util/src/gconvert.cpp @@ -28,13 +28,14 @@ #include "GraphWriter.h" #if !WIN32 && !CYGWIN -#include "orbconfig.h" -#include "orbtimer.h" + #include "orbconfig.h" + #include "orbtimer.h" using namespace std; void print_time(string prefix, ORB_t start, ORB_t end){ cout << prefix + ": " << ORB_seconds(end, start) << "\n"; } + #endif void usage(const char *s){ @@ -42,7 +43,7 @@ void usage(const char *s){ } int main(int argc, char **argv){ -#if !WIN32 & !CYGWIN + #if !WIN32 & !CYGWIN ORB_t t1, t2; char *intype, *outtype, *infile, *outfile; @@ -108,9 +109,9 @@ int main(int argc, char **argv){ print_time("Time(write_graph)", t1, t2); return 0; -#else - fprintf(stderr,"Can't build under Cygwin or Windows\n"); - return 1; -#endif + #else // if !WIN32 & !CYGWIN + fprintf(stderr,"Can't build under Cygwin or Windows\n"); + return 1; + #endif // if !WIN32 & !CYGWIN } // main diff --git a/util/src/gen_pkt.cpp b/util/src/gen_pkt.cpp index 1e1bd71..7b0b3f6 100644 --- a/util/src/gen_pkt.cpp +++ b/util/src/gen_pkt.cpp @@ -26,16 +26,15 @@ #include "GraphWriter.h" #if !WIN32 && !CYGWIN -#include "orbconfig.h" -#include "orbtimer.h" + #include "orbconfig.h" + #include "orbtimer.h" #else -#define ORB_t clock_t -#define ORB_seconds(x,y) "lame" -#define ORB_calibrate() -#define ORB_read(x) + #define ORB_t clock_t + #define ORB_seconds(x,y) "lame" + #define ORB_calibrate() + #define ORB_read(x) #endif - using namespace std; void usage(const char *s){ @@ -69,7 +68,7 @@ int main(int argc, char **argv){ exit(-1); } - ORB_t t1=0, t2=0, t3=0; + ORB_t t1 = 0, t2 = 0, t3 = 0; int i; int t = 1; int ktree_n = -1, ktree_k = -1, ktree_p = -1; diff --git a/util/src/graph_stats.cpp b/util/src/graph_stats.cpp index 9ebc35a..81b128c 100644 --- a/util/src/graph_stats.cpp +++ b/util/src/graph_stats.cpp @@ -33,12 +33,12 @@ #include "GraphException.h" #if !WIN32 && !CYGWIN -#include "orbconfig.h" -#include "orbtimer.h" + #include "orbconfig.h" + #include "orbtimer.h" -#ifdef HAS_SLEPC - #include -#endif + #ifdef HAS_SLEPC + #include + #endif using namespace std; @@ -387,9 +387,10 @@ int main(int argc, char **argv){ create_map(allowed_methods, val_methods); parse_options(argc, argv, infile, intype, outfilename, outprefix, req_methods, record_timings, file_append, &spectrum_spread, apspinputfilename); if(outfilename.length() == 0){ - if(outprefix.length() != 0) { - outfilename = outprefix+".stats"; - } else { + if(outprefix.length() != 0){ + outfilename = outprefix + ".stats"; + } + else { outfilename = "graph-stats.txt"; } } @@ -436,7 +437,6 @@ int main(int argc, char **argv){ exit(1); } - // Read in the graph and start recording things to output streams cout << "Reading graph" << endl; ORB_read(t1); @@ -455,7 +455,8 @@ int main(int argc, char **argv){ string of = outfilename + ".timings"; if(file_append == false){ timing_file.open(of.c_str()); - } else { + } + else { timing_file.open(of.c_str(), ios_base::out | ios_base::app); } if(!timing_file.is_open()){ @@ -477,8 +478,6 @@ int main(int argc, char **argv){ g->set_shortest_path_dist(apsp_dists); } - - outfile.precision(16); vector components; cout << "Graph is connected?: " << std::boolalpha << gp.is_connected(g) << endl; @@ -498,7 +497,7 @@ int main(int argc, char **argv){ // some algorithms only make sense to run on a connected graph/component if(not is_connected){ // run everything against the other algorithms cout << "Graph is not connected, re-running stats on largest connected component" << endl; - outfilename = outprefix+".largest_component.stats"; + outfilename = outprefix + ".largest_component.stats"; if(file_append == false){ outfile.open(outfilename.c_str()); } @@ -523,7 +522,8 @@ int main(int argc, char **argv){ string of = outfilename + ".timings"; if(file_append == false){ timing_file.open(of.c_str()); - } else { + } + else { timing_file.open(of.c_str(), ios_base::out | ios_base::app); } @@ -545,10 +545,10 @@ int main(int argc, char **argv){ exit(0); } // main -#else -int main() -{ - fprintf(stderr,"Can't run under windows or cygwin\n"); - return 0; +#else // if !WIN32 && !CYGWIN +int main(){ + fprintf(stderr,"Can't run under windows or cygwin\n"); + return 0; } -#endif + +#endif // if !WIN32 && !CYGWIN diff --git a/util/src/orbtimer.cpp b/util/src/orbtimer.cpp index d53302a..0f6e1a8 100644 --- a/util/src/orbtimer.cpp +++ b/util/src/orbtimer.cpp @@ -28,26 +28,26 @@ * **************************************************************************/ #if !WIN32 -#if !CYGWIN + #if !CYGWIN -#include -#include -#include "orbconfig.h" + #include + #include + #include "orbconfig.h" -#define ORBTIMER_LIBRARY -#include "orbtimer.h" + #define ORBTIMER_LIBRARY + #include "orbtimer.h" static ORB_tick_t Csum = 0; static ORB_tick_t Gsum = 0; static ORB_tick_t nsamples = 0; static ORB_tick_t ndummy = 0; -#endif + #endif #endif void ORB_calibrate(){ -#if WIN32 || CYGWIN || _CYGWIN - return; -#else + #if WIN32 || CYGWIN || _CYGWIN + return; + #else int i, j; double seconds; struct timeval tv1, tv2; @@ -111,8 +111,6 @@ void ORB_calibrate(){ ORB_min_lat_sec = ORB_min_lat_cyc / ORB_ref_freq; GTD_avg_lat_sec = GTD_avg_lat_cyc / ORB_ref_freq; GTD_min_lat_sec = GTD_min_lat_cyc / ORB_ref_freq; -#endif + #endif // if WIN32 || CYGWIN || _CYGWIN } // ORB_calibrate - - From ee4e5720a6cd3d9ecf112b3d7a3bd67cf4dd47fc Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Thu, 26 Sep 2013 13:45:15 -0400 Subject: [PATCH 71/73] add correct output of data we calculate (eccentricity, expansion) Fix average shortest paths calculations on large graphs --- lib_graphd/inc/Util.h | 15 +++++++ lib_graphd/src/Graph.cpp | 9 ++-- lib_graphd/src/GraphProperties.cpp | 41 ++++++++---------- lib_graphd/src/Util.cpp | 69 ++++++++++++++++++++++++++++++ util/src/graph_stats.cpp | 14 ++++-- 5 files changed, 119 insertions(+), 29 deletions(-) diff --git a/lib_graphd/inc/Util.h b/lib_graphd/inc/Util.h index 89dd8f5..398b70c 100644 --- a/lib_graphd/inc/Util.h +++ b/lib_graphd/inc/Util.h @@ -97,11 +97,21 @@ void split(const std::string& s, char sep, vector& v); // used in meti */ void write_degree_distribution(string filename, const vector &dist); +/** + * \brief write an eccentricity distribution out to a file + */ +void write_eccentricity_distribution(string filename, const vector &dist); + /** * \brief write a k_core list out to a file */ void write_kcores(string filename, const vector &kcores); +/** + * \brief write an eccentricity list out to a file + */ +void write_eccentricity(string filename, const vector &ecc); + /** * \brief write a betweenness centrality list out to a file */ @@ -112,6 +122,11 @@ void write_betweenness(string filename, const vector &bc); */ void write_delta_hyperbolicity(string filename, const vector< vector > &delta); +/** + * \brief write an expansion list out to a file + */ +void write_expansion(string filename, const vector &expansion); + /** * \brief Write an all pairs shortest path matrix out to file. */ diff --git a/lib_graphd/src/Graph.cpp b/lib_graphd/src/Graph.cpp index e21633a..c100b61 100644 --- a/lib_graphd/src/Graph.cpp +++ b/lib_graphd/src/Graph.cpp @@ -101,6 +101,7 @@ namespace Graph { nodes[i].set_label(i + 1); } this->next_label = n + 1; + this->apsp_dist = NULL; #ifdef HAS_BOOST this->boost_graph = NULL; #endif @@ -778,10 +779,10 @@ namespace Graph { **/ const vector< vector > &Graph::get_shortest_path_dist_ref(){ if(this->apsp_dist == NULL){ - this->apsp_dist = new(vector< vector >); + this->apsp_dist = new vector< vector >; } if(this->apsp_dist->empty()){ - cout << "Empty -- calling function to compute shortest paths" << endl; + cout << "APSP matrix is empty -- calling function to compute shortest paths" << endl; GraphProperties properties; properties.paths_dijkstra_all(this,*(this->apsp_dist)); //sets this>apsp_dist with values } @@ -790,10 +791,10 @@ namespace Graph { const vector &Graph::get_u_shortest_path_dist(int u){ if(this->apsp_dist == NULL){ - this->apsp_dist = new(vector< vector >); + this->apsp_dist = new vector< vector >; } if(this->apsp_dist[u].empty()){ - cout << "u Empty -- calling function to compute shortest paths" << endl; + cout << "SSSP vector is empty -- calling function to compute shortest paths" << endl; GraphProperties properties; properties.paths_dijkstra_single(this,(*(this->apsp_dist))[u], u); //sets this>apsp_dist[u] with values } diff --git a/lib_graphd/src/GraphProperties.cpp b/lib_graphd/src/GraphProperties.cpp index 514e1ca..734417d 100644 --- a/lib_graphd/src/GraphProperties.cpp +++ b/lib_graphd/src/GraphProperties.cpp @@ -883,7 +883,7 @@ namespace Graph { #pragma omp parallel for default(none) shared(norm_hops, hops) for(int h = 1; h < n; h++){ - norm_hops[h] = (double)hops[h] / (n * (n - 1)); + norm_hops[h] = (double)hops[h] / ((double)n * (n - 1)); //printf("h = %d and number is %d; norm value is %f\n",h,hops[h],norm_hops[h]); } } //expansion @@ -976,38 +976,35 @@ namespace Graph { } void GraphProperties::avg_path_length(Graph *g, double &pl){ - const int n = g->get_num_nodes(); + const uint64_t n = g->get_num_nodes(); const vector< vector > &short_paths = g->get_shortest_path_dist_ref(); double sum = 0; - int intermediate = 0; + uint64_t intermediate = 0; int i, j; int inf_path = 0; - #pragma omp parallel default(none) private(j, intermediate) reduction(+:sum) shared(short_paths, inf_path) - { - #pragma omp for reduction(+:inf_path) - for(i=0; i &dist){ outfile.close(); } // write_degree_distribution +/** + * Write an eccentricity distribution out to file. + * \param[in] filename filename to write output to + * \param[in] dist a vector, indexed on degree + */ +void write_eccentricity_distribution(string filename, const vector &dist){ + ofstream outfile; + + outfile.open(filename.c_str()); + + if(!outfile.is_open()){ + cerr << "Error opening " << filename << "for writing\n"; + } + else { + int i; + for(i = 0; i < dist.size(); i++){ + outfile << i << " " << dist[i] << "\n"; + } + } + + outfile.close(); +} // write_eccentricity_distribution + +/** + * Write a expansion out to file. + * \param[in] filename filename to write output to + * \param[in] dist a vector, indexed on degree + */ +void write_expansion(string filename, const vector &expansion){ + ofstream outfile; + + outfile.open(filename.c_str()); + + if(!outfile.is_open()){ + cerr << "Error opening " << filename << "for writing\n"; + } + else { + int i; + for(i = 0; i < expansion.size(); i++){ + outfile << i << " " << expansion[i] << "\n"; + } + } + + outfile.close(); +} // write_expansion + /** * Write a kcore list out to file. * \param[in] filename filename to write output to @@ -892,6 +938,29 @@ void write_kcores(string filename, const vector &kcores){ outfile.close(); } // write_k_cores +/** + * Write an eccentricity list out to file. + * \param[in] filename filename to write output to + * \param[in] ecc a vector, indexed on vertex number + */ +void write_eccentricity(string filename, const vector &ecc){ + ofstream outfile; + + outfile.open(filename.c_str()); + + if(!outfile.is_open()){ + cerr << "Error opening " << filename << "for writing\n"; + } + else { + int i; + for(i = 0; i < ecc.size(); i++){ + outfile << i << " " << ecc[i] << "\n"; + } + } + + outfile.close(); +} // write_k_cores + /** * Write a betweenness centrality vecotr out to file. * diff --git a/util/src/graph_stats.cpp b/util/src/graph_stats.cpp index 81b128c..d003553 100644 --- a/util/src/graph_stats.cpp +++ b/util/src/graph_stats.cpp @@ -261,6 +261,9 @@ void run_all_methods(Graph::Graph *g, ofstream &outfile, ofstream &timing_file, gp.eccentricity(g, ecc); ORB_read(t2); print_time(timing_file, "Time(eccentricity)",t1,t2); + string of = outprefix + ".eccentricity"; + outfile << "eccentricity_file " << of << endl; + write_eccentricity(of, ecc); } if(req_methods["eccentricity_dist"] == true){ cout << "Calculating distribution of eccentricities" << endl; @@ -268,6 +271,9 @@ void run_all_methods(Graph::Graph *g, ofstream &outfile, ofstream &timing_file, gp.eccentricity_dist(g, ecc, freq_ecc); ORB_read(t2); print_time(timing_file, "Time(eccentricity distribution)",t1,t2); + string of = outprefix + ".eccentricity_dist"; + outfile << "eccentricity_dist_file " << of << endl; + write_eccentricity_distribution(of, freq_ecc); } } else { @@ -280,6 +286,9 @@ void run_all_methods(Graph::Graph *g, ofstream &outfile, ofstream &timing_file, gp.expansion(g, norm_hops); ORB_read(t2); print_time(timing_file, "Time(expansion)",t1,t2); + string of = outprefix + ".expansion"; + outfile << "expansion_file " << of << endl; + write_expansion(of, norm_hops); } if(req_methods["avg_shortest_path"] == true){ cout << "Calculating average shortest path length" << endl; @@ -480,16 +489,14 @@ int main(int argc, char **argv){ outfile.precision(16); vector components; - cout << "Graph is connected?: " << std::boolalpha << gp.is_connected(g) << endl; ORB_read(t1); cout << "GU.label_all_components says: " << gu.label_all_components(g, &components) << endl; ORB_read(t2); print_time(timing_file, "Time(label_all_components)", t1, t2); bool is_connected = gp.is_connected(g); cout << "Connected components: " << g->get_num_connected_components() << endl; - cout << "Graph is connected?: " << std::boolalpha << is_connected << endl; + cout << "Graph is connected: " << std::boolalpha << is_connected << endl; - cout << "Creating largest connected component graph" << endl; run_all_methods(g, outfile, timing_file, outprefix, req_methods, file_append, spectrum_spread); outfile.close(); timing_file.close(); @@ -510,6 +517,7 @@ int main(int argc, char **argv){ } // get the largest component + cout << "Creating largest connected component graph" << endl; Graph::Graph *largest_component = gu.get_largest_component_graph(g); delete(g); // delete g here to save on memory From 389849a79871a385f4d5788bec6389e04a747fb1 Mon Sep 17 00:00:00 2001 From: Josh Lothian Date: Fri, 27 Sep 2013 10:58:41 -0400 Subject: [PATCH 72/73] Fix compilation erros when using uint64_t and boost isn't enabled --- lib_graphd/inc/GraphDecomposition.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib_graphd/inc/GraphDecomposition.h b/lib_graphd/inc/GraphDecomposition.h index eda7509..c7f7f12 100644 --- a/lib_graphd/inc/GraphDecomposition.h +++ b/lib_graphd/inc/GraphDecomposition.h @@ -54,6 +54,11 @@ #include #endif +#ifndef HAS_BOOST + #include +#endif + + #include #include #include From 5188957b72da77f32ab8e63f7c5eef8bcfd27b1f Mon Sep 17 00:00:00 2001 From: "Blair D. Sullivan" Date: Fri, 27 Sep 2013 15:20:48 -0400 Subject: [PATCH 73/73] Adding example for running graph_stats --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 6b93f80..5b073c0 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,11 @@ will be identified through a message to standard out. (sample graphviz command: neato -Tpdf -o tree.pdf tree.dot). * ./bin/td_viz -f ./sample_graphs/1dc.64.dimacs -t ./sample_graphs/1dc.64.tree -e +###Calculate graph statistics +Generates a set of output files containing the results of your selection of a broad spectrum of graph statistics (run with -h to see all options) when +calculated on the specified input graph. The single value statistics are stored in sample_graphs/pkt-stats.stats, and that file lists where to find any features that create a vector (or more) of data. Note that without BOOST, distance-based features may not be available. +* ./bin/graph_stats -i ./sample_graphs/1dc.64.dimacs -t dimacs -p ./sample_graphs/pkt-stats -m edge_density,degree_dist,global_cc,avg_cc,assortativity,eccentricity,expansion,avg_shortest_path -r + More information on the output formats for the weighted independent set executables is in the README in max_wis. ##Getting Help