-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
cac3027
commit 7afb007
Showing
6 changed files
with
319 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
#include <igraph.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include "BoundaryBetweennessCast.h" | ||
#include "Util.h" | ||
|
||
#include <chrono> | ||
|
||
#if IGRAPH_INTEGER_SIZE==64 | ||
typedef int64_t IG_LONG; | ||
#elif IGRAPH_INTEGER_SIZE==32 | ||
typedef int32_t IG_LONG; | ||
#endif | ||
|
||
namespace interface { | ||
|
||
// Default constructor | ||
BoundaryBetweennessCast::BoundaryBetweennessCast () {} | ||
|
||
BoundaryBetweennessCast::~BoundaryBetweennessCast () {} | ||
|
||
void BoundaryBetweennessCast::boundary_betweenness_compute () { | ||
//printf("Begin\n"); | ||
igraph_t* g = (igraph_t*)this->G_ptr; | ||
|
||
num_edges = igraph_ecount(g); | ||
|
||
igraph_vector_int_t sources_vec, targets_vec; | ||
igraph_vector_t res, weights_vec; | ||
igraph_vector_init(&res, num_edges); | ||
igraph_vs_t ig_sources, ig_targets; | ||
|
||
igraph_integer_t* sources_arr = (IG_LONG*)sources_ptr; | ||
igraph_integer_t* targets_arr = (IG_LONG*)targets_ptr; | ||
igraph_vector_int_init_array(&sources_vec, sources_arr, sources_len); | ||
igraph_vector_int_init_array(&targets_vec, targets_arr, targets_len); | ||
igraph_vs_vector(&ig_sources, &sources_vec); | ||
igraph_vs_vector(&ig_targets, &targets_vec); | ||
|
||
igraph_real_t* weights_arr = (double *)weights_ptr; | ||
igraph_vector_init_array(&weights_vec, weights_arr, num_edges); | ||
|
||
//printf("Running\n"); | ||
std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now(); | ||
igraph_edge_betweenness_subset(g, | ||
&res, /*igraph_vector_t *res*/ | ||
igraph_ess_all(IGRAPH_EDGEORDER_ID), /*igraph_es_t eids*/ | ||
false, /*igraph_bool_t directed*/ | ||
ig_sources, /*igraph_vs_t sources*/ | ||
ig_targets, /*igraph_vs_t targets*/ | ||
&weights_vec); /*igraph_vector_t *weights*/ | ||
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now(); | ||
// printf("Complete in %lld\n", std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count()); | ||
|
||
betweennesses <<= res; | ||
|
||
igraph_vector_int_destroy(&sources_vec); | ||
igraph_vector_int_destroy(&targets_vec); | ||
igraph_vs_destroy(&ig_sources); | ||
igraph_vs_destroy(&ig_targets); | ||
igraph_destroy(g); | ||
} | ||
|
||
|
||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
#include <vector> | ||
|
||
#ifndef BOUNDARYBETWEENNESSCAST_H | ||
#define BOUNDARYBETWEENNESSCAST_H | ||
|
||
namespace interface { | ||
class BoundaryBetweennessCast { | ||
public: | ||
void* G_ptr; | ||
long long* sources_ptr; | ||
long long* targets_ptr; | ||
//std::vector<long long> sources; | ||
//std::vector<long long> targets; | ||
double* weights_ptr; | ||
int sources_len; | ||
int targets_len; | ||
BoundaryBetweennessCast(); | ||
~BoundaryBetweennessCast(); | ||
void boundary_betweenness_compute(); | ||
int num_edges; | ||
std::vector<float> betweennesses; | ||
}; | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
from libcpp.vector cimport vector | ||
|
||
cdef extern from "BoundaryBetweennessCast.cpp": | ||
pass | ||
|
||
# Declare the class with cdef | ||
cdef extern from "BoundaryBetweennessCast.h" namespace "interface": | ||
cdef cppclass BoundaryBetweennessCast: | ||
void* G_ptr | ||
long long* sources_ptr | ||
long long* targets_ptr | ||
#vector[long long] sources | ||
#vector[long long] targets | ||
double* weights_ptr | ||
int sources_len | ||
int targets_len | ||
vector[float] betweennesses | ||
int num_edges | ||
BoundaryBetweennessCast() except + | ||
void boundary_betweenness_compute() except + | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
#include <igraph.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include "Util.h" | ||
#include <Eigen/Dense> | ||
#include "RandomBoundaryBetweennessCast.h" | ||
|
||
#include <iostream> | ||
namespace interface { | ||
|
||
// Default constructor | ||
RandomBoundaryBetweennessCast::RandomBoundaryBetweennessCast () {} | ||
|
||
RandomBoundaryBetweennessCast::~RandomBoundaryBetweennessCast () {} | ||
|
||
|
||
void RandomBoundaryBetweennessCast::random_boundary_betweenness_compute () { | ||
igraph_t* g = (igraph_t*)this->G_ptr; | ||
int num_verts = igraph_vcount(g); | ||
num_edges = igraph_ecount(g); | ||
|
||
igraph_vector_t weights_vec; | ||
igraph_real_t* weights_arr = (double *)weights_ptr; | ||
igraph_vector_init_array(&weights_vec, weights_arr, num_edges); | ||
|
||
/*Prepare Laplacian as Eigen Array*/ | ||
igraph_sparsemat_t A, compA; | ||
igraph_sparsemat_t L, compL; | ||
igraph_sparsemat_init(&L, num_verts, num_verts, num_verts*2*6); | ||
igraph_sparsemat_init(&A, num_verts, num_verts, num_verts*2*6); | ||
igraph_get_laplacian_sparse(g, &L, IGRAPH_ALL, | ||
IGRAPH_LAPLACIAN_UNNORMALIZED, &weights_vec); | ||
igraph_get_adjacency_sparse(g, &A, IGRAPH_GET_ADJACENCY_BOTH, | ||
&weights_vec, IGRAPH_NO_LOOPS); | ||
igraph_sparsemat_compress(&L, &compL); | ||
igraph_sparsemat_compress(&A, &compA); | ||
igraph_sparsemat_iterator_t mit; | ||
Eigen::MatrixXf eigL = Eigen::MatrixXf::Zero(num_verts, num_verts); | ||
|
||
int row, col; | ||
float val; | ||
igraph_sparsemat_iterator_init(&mit, &compL); | ||
for (int i=0; i<(num_edges*2+num_verts); i++) { | ||
|
||
row = igraph_sparsemat_iterator_row(&mit); | ||
col = igraph_sparsemat_iterator_col(&mit); | ||
val = igraph_sparsemat_iterator_get(&mit); | ||
|
||
eigL(row, col) = val; | ||
igraph_sparsemat_iterator_next(&mit); | ||
} | ||
|
||
/*Invert Laplacian*/ | ||
std::chrono::steady_clock::time_point begin, end; | ||
begin = std::chrono::steady_clock::now(); | ||
Eigen::MatrixXf pinv(num_verts, num_verts); | ||
pinv = eigL.completeOrthogonalDecomposition().pseudoInverse(); | ||
end = std::chrono::steady_clock::now(); | ||
printf("Inversion complete in %lld\n", std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count()); | ||
//std::cout << pinv << "\n"; | ||
|
||
/*LINEAR RANDOM BOUNDARY BETWEENNESS*/ | ||
begin = std::chrono::steady_clock::now(); | ||
std::vector<float> V(num_verts, 0); | ||
linear_betweennesses.resize(num_edges); | ||
igraph_integer_t from, to; | ||
//Old method | ||
/* | ||
for (int s=0; s<sources_len; s++) { | ||
for (int t=0; t<targets_len; t++) { | ||
for (int i=0; i< num_verts; i++) { | ||
V[i] = pinv(i, sources[s]) - pinv(i, targets[t]); | ||
} | ||
for (int i=0; i<num_edges; i++) { | ||
igraph_edge(g, i, &from, &to); | ||
linear_betweennesses[i] += abs(V[int(from)] - V[int(to)])*igraph_sparsemat_get(&A, from, to); | ||
} | ||
} | ||
} | ||
end = std::chrono::steady_clock::now(); | ||
printf("Linear Complete in %lld\n", std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count()); | ||
*/ | ||
//New method | ||
float V_from, V_to; | ||
for (int e=0; e<num_edges; e++) { | ||
igraph_edge(g, e, &from, &to); | ||
for (int s=0; s<sources_len; s++) { | ||
for (int t=0; t<targets_len; t++) { | ||
V_from = pinv(from, sources[s]) - pinv(from, targets[t]); | ||
V_to = pinv(to, sources[s]) - pinv(to, targets[t]); | ||
linear_betweennesses[e] += abs(V_from-V_to)*igraph_sparsemat_get(&A, from, to); | ||
} | ||
} | ||
} | ||
|
||
/*NONLINEAR RANDOM BOUNDARY BETWEENNESS*/ | ||
/*Generate voltage vector*/ | ||
/*(Faster than matrix vector multiplication because we know the | ||
* location of non-zero elements a priori) | ||
* Note that, for nonlinear random betweenness, the target vertex has | ||
* changed to the ghost vertex*/ | ||
begin = std::chrono::steady_clock::now(); | ||
float sum = 0; | ||
std::fill(V.begin(), V.end(), 0); | ||
for (int i=0; i<num_verts; i++) { | ||
for (int s=0; s<sources_len; s++) { | ||
V[i] += pinv(i, sources[s])*incoming[s]; | ||
sum += incoming[s]; | ||
} | ||
V[i] -= pinv(i, num_verts-1)*sum; | ||
} | ||
/*Here, from/to refer to the edge endpoints; not the source/targets used | ||
* to calculate the betweenness subset. | ||
*/ | ||
nonlinear_betweennesses.resize(num_edges); | ||
bool skip = false; | ||
for (int i=0; i<num_edges; i++) { | ||
igraph_edge(g, i, &from, &to); | ||
//Skip edges connecting sources | ||
/* | ||
for (int s1=0; s1<sources_len; s1++) { | ||
for (int s2=0; s2<sources_len; s2++) { | ||
//printf("%i,%i,%i,%i\n",s1,s2,int(from),int(to)); | ||
if (((int(from) == sources[s1] && int(to) == sources[s2]) || | ||
(int(from) == sources[s2] && int(to) == sources[s1])) && | ||
!skip) { | ||
skip = true; | ||
break; | ||
} | ||
} | ||
} | ||
//Skip edges connecting targets | ||
for (int t1=0; t1<targets_len; t1++) { | ||
for (int t2=0; t2<targets_len; t2++) { | ||
//printf("%i,%i,%i,%i\n",s1,s2,int(from),int(to)); | ||
if (((int(from) == targets[t1] && int(to) == targets[t2]) || | ||
(int(from) == targets[t2] && int(to) == targets[t1])) && | ||
!skip) { | ||
skip = true; | ||
break; | ||
} | ||
} | ||
} | ||
//Reset the skip flag | ||
if (skip) { | ||
skip = false; | ||
continue; | ||
} | ||
*/ | ||
/*So if edge neither connects two sources nor two targets, do this...*/ | ||
nonlinear_betweennesses[i] = abs(V[int(from)] - V[int(to)])*igraph_sparsemat_get( | ||
&A, from, to); | ||
} | ||
end = std::chrono::steady_clock::now(); | ||
printf("NL Complete in %lld\n", std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count()); | ||
igraph_destroy(g); | ||
} | ||
|
||
|
||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
#include <vector> | ||
|
||
#ifndef RANDOMBOUNDARYBETWEENNESSCAST_H | ||
#define RANDOMBOUNDARYBETWEENNESSCAST_H | ||
|
||
namespace interface { | ||
class RandomBoundaryBetweennessCast { | ||
public: | ||
void* G_ptr; | ||
double* weights_ptr; | ||
std::vector<int> sources; | ||
std::vector<int> targets; | ||
std::vector<float> incoming; | ||
int sources_len; | ||
int targets_len; | ||
RandomBoundaryBetweennessCast(); | ||
~RandomBoundaryBetweennessCast(); | ||
void random_boundary_betweenness_compute(); | ||
int num_edges; | ||
std::vector<float> linear_betweennesses; | ||
std::vector<float> nonlinear_betweennesses; | ||
}; | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
from libcpp.vector cimport vector | ||
|
||
cdef extern from "RandomBoundaryBetweennessCast.cpp": | ||
pass | ||
|
||
# Declare the class with cdef | ||
cdef extern from "RandomBoundaryBetweennessCast.h" namespace "interface": | ||
cdef cppclass RandomBoundaryBetweennessCast: | ||
void* G_ptr | ||
double* weights_ptr | ||
vector[int] sources | ||
vector[int] targets | ||
vector[float] incoming | ||
int sources_len | ||
int targets_len | ||
vector[float] linear_betweennesses | ||
vector[float] nonlinear_betweennesses | ||
int num_edges | ||
RandomBoundaryBetweennessCast() except + | ||
void random_boundary_betweenness_compute() except + | ||
|