Advertisement
Guest User

Untitled

a guest
Dec 3rd, 2016
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.42 KB | None | 0 0
  1. //
  2. // Computes the minimum spanning tree (MST) of a weighted graph
  3. // The graph is provided as an adjacency matrix A
  4. //
  5. // Warning: Return values of calls are not checked for error to keep
  6. // the code simple.
  7. //
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <math.h>
  11. #include <sys/time.h>
  12. #include <time.h> // mod
  13.  
  14. enum { FALSE, TRUE };
  15.  
  16. #define MAX_N 65536
  17.  
  18. //#define INFINITY 1.0e300
  19.  
  20. // mod
  21. struct timespec start, stop;
  22. double total_time;
  23.  
  24. int numthreads = 4;
  25. pthread_t p_threads[4]; // Threads
  26. pthread_attr_t attr; // Thread attributes
  27. // end
  28.  
  29. // MST
  30. typedef struct _mst {
  31. unsigned int n; // number of nodess in the tree
  32. unsigned int * node; // edge (i,node[i]) is in the MST
  33. double * weight; // weight of edge (i,node[i])
  34. double mst_weight; // weight of MST (sum of weights of all edges
  35. } MST_t;
  36. // Adjacency matrix structure
  37. typedef struct _adj_matrix {
  38. double ** weight;
  39. int n;
  40. } ADJ_MATRIX_t;
  41.  
  42. // Variable Declarations
  43. ADJ_MATRIX_t * A; // Adjacency Matrix of graph
  44. MST_t * mst; // MST of graph
  45. MST_t * my_mst; // mod -> my parellel MST of graph
  46.  
  47. // -----------------------------------------------------------------------------
  48. // MST Routines
  49. //
  50. // Create and initialize MST
  51. //
  52. MST_t * init_mst ( ADJ_MATRIX_t * A ) {
  53. unsigned i;
  54. MST_t * mst = calloc(1, sizeof(MST_t));
  55. mst->n = A->n;
  56. mst->node = calloc(mst->n, sizeof(unsigned int));
  57. mst->weight = calloc(mst->n, sizeof(double));
  58. for (i = 0; i < mst->n; i++) {
  59. mst->node[i] = i;
  60. mst->weight[i] = 0.0;
  61. }
  62. mst->mst_weight = 0.0;
  63. return mst;
  64. }
  65. // -----------------------------------------------------------------------------
  66. // Adjacency Matrix Routines
  67. //
  68. // Create and initialize adjacency matrix A with edge weights of the graph
  69. // A->n denotes size of matrix
  70. // A->weight[i][j] denotes weight edge from nodes i and j
  71. //
  72. ADJ_MATRIX_t * init_adj_matrix ( unsigned int num_nodes, unsigned int seed ) {
  73. unsigned int i, j;
  74. ADJ_MATRIX_t * A = calloc(1, sizeof(ADJ_MATRIX_t));
  75. A->n = num_nodes;
  76. // Allocate storage for matrix elements
  77. A->weight = calloc(A->n, sizeof(double *));
  78. for (i = 0; i < A->n; i++) {
  79. A->weight[i] = calloc(A->n, sizeof(double));
  80. }
  81. // Initialize matrix elements
  82. srand(seed);
  83. double randwt;
  84. for (i = 0; i < A->n; i++) {
  85. for (j = i; j < A->n; j++) {
  86. if (i == j) {
  87. A->weight[i][j] = 0.0;
  88. } else {
  89. // Insert random edge weights
  90. A->weight[i][j] = (double)(rand_r(&seed))/(double)(RAND_MAX);
  91. A->weight[j][i] = A->weight[i][j];
  92. }
  93. }
  94. }
  95. return A;
  96. }
  97. // Compute minimum spanning tree of graph A
  98. MST_t * minimum_spanning_tree(ADJ_MATRIX_t * A, unsigned int root) {
  99. unsigned int i, j, u, nodes;
  100. double minwt;
  101.  
  102. // Initialize MST
  103. MST_t * mst = init_mst(A);
  104.  
  105. // Initialize weight vector d with weight of edges connecting node i to root
  106. double * d = calloc(A->n, sizeof(double));
  107. for (i = 0; i < A->n; i++) {
  108. d[i] = A->weight[root][i]; // d[i]= min wt. edge from node i to MST
  109. mst->node[i] = root; // closest MST node to node i
  110. }
  111. // Initialize flag that indicates whether a node has been inserted in the tree
  112. short int * inserted_in_mst = calloc(A->n, sizeof(short int));
  113. for (i = 0; i < A->n; i++)
  114. inserted_in_mst[i] = FALSE;
  115.  
  116. // Prim's MST algorithm
  117.  
  118. // Insert root into MST
  119. inserted_in_mst[root] = TRUE;
  120. mst->node[root] = root;
  121. mst->weight[root] = 0.0;
  122. mst->mst_weight = 0.0;
  123.  
  124. nodes = 1;
  125. while (nodes < A->n) {
  126. // Find node u not belonging to MST with minimum weight edge in d
  127. minwt = INFINITY;
  128. for (i = 0; i < A->n; i++) {
  129. if ((!inserted_in_mst[i]) && (d[i] < minwt)) {
  130. u = i;
  131. minwt = d[i];
  132. }
  133. }
  134. // Add u to MST
  135. inserted_in_mst[u] = TRUE;
  136. mst->weight[u] = d[u];
  137. mst->mst_weight += d[u];
  138. nodes ++;
  139.  
  140. // Update d vector
  141. for (i = 0; i < A->n; i++) {
  142. if ((!inserted_in_mst[i]) && (d[i] > A->weight[u][i])) {
  143. d[i] = A->weight[u][i];
  144. mst->node[i] = u; // set u as closest MST node of i
  145. }
  146. }
  147. }
  148. return mst;
  149. }
  150.  
  151.  
  152. // mod
  153. typedef struct _passme {
  154. ADJ_MATRIX_t * A;
  155. short int * inserted_in_mst;
  156. double * d;
  157. MST_t * mst;
  158. unsigned int u;
  159. int threadid;
  160. } passme;
  161.  
  162.  
  163. void *pprim(void *s) {
  164. passme* data = (passme*)s;
  165. unsigned int i;
  166. MST_t * mst = data->mst;
  167. ADJ_MATRIX_t * A = data->A;
  168. unsigned int u = data->u;
  169. double * d = data->d;
  170. short int * inserted_in_mst = data->inserted_in_mst;
  171. int threadid = data->threadid;
  172.  
  173. int blocksize = A->n / numthreads;
  174. int index = threadid * blocksize;
  175.  
  176. //printf("my threadid is %d\n", threadid);
  177. //for(;;);
  178.  
  179. for(i = index; i < (index + blocksize); i++){
  180. if ((!inserted_in_mst[i]) && (d[i] > A->weight[u][i])) {
  181. d[i] = A->weight[u][i];
  182. mst->node[i] = u; // set u as closest MST node of i
  183. }
  184. }
  185. }
  186.  
  187.  
  188. MST_t * parallel_mst(ADJ_MATRIX_t * A, unsigned int root) {
  189. unsigned int i, j, u, nodes;
  190. double minwt;
  191.  
  192. // Initialize MST
  193. MST_t * mst = init_mst(A);
  194.  
  195. // Initialize weight vector d with weight of edges connecting node i to root
  196. double * d = calloc(A->n, sizeof(double));
  197. for(i = 0; i < A->n; i++) {
  198. d[i] = A->weight[root][i]; // d[i]= min wt. edge from node i to MST
  199. mst->node[i] = root; // closest MST node to node i
  200. }
  201.  
  202. // Initialize flag that indicates whether a node has been inserted in the tree
  203. short int * inserted_in_mst = calloc(A->n, sizeof(short int));
  204. for(i = 0; i < A->n; i++)
  205. inserted_in_mst[i] = FALSE;
  206.  
  207. // Prim's MST algorithm
  208.  
  209. // Insert root into MST
  210. inserted_in_mst[root] = TRUE;
  211. mst->node[root] = root;
  212. mst->weight[root] = 0.0;
  213. mst->mst_weight = 0.0;
  214.  
  215. nodes = 1;
  216. while (nodes < A->n) {
  217. // Find node u not belonging to MST with minimum weight edge in d
  218. minwt = INFINITY;
  219. for(i = 0; i < A->n; i++) {
  220. if((!inserted_in_mst[i]) && (d[i] < minwt)) {
  221. u = i;
  222. minwt = d[i];
  223. }
  224. }
  225. // Add u to MST
  226. inserted_in_mst[u] = TRUE;
  227. mst->weight[u] = d[u];
  228. mst->mst_weight += d[u];
  229. nodes ++;
  230.  
  231. passme data[4];
  232.  
  233. for(i = 0; i < numthreads; i++) {
  234. data[i].A = A;
  235. data[i].inserted_in_mst = inserted_in_mst;
  236. data[i].d = d;
  237. data[i].mst = mst;
  238. data[i].u = u;
  239. data[i].threadid = i;
  240. //printf("creating thread with value %d\n", data.threadid);
  241. pthread_create(&p_threads[i], &attr, pprim, (void *)&data[i]);
  242. }
  243.  
  244. for(i = 0; i < numthreads; i++) {
  245. pthread_join(p_threads[i], NULL);
  246. }
  247. }
  248. return mst;
  249. }
  250. // end
  251.  
  252.  
  253. // Main program
  254. // - Initialize adjacency matrix A of a graph
  255. // - Computes minimum spanning tree with a given starting node
  256. int main(int argc, char *argv[]) {
  257.  
  258. unsigned int num_nodes, root, seed;
  259.  
  260. if (argc != 4) {
  261. printf("Use: <executable_name> <num_nodes> <root_node> <seed>\n");
  262. exit(0);
  263. }
  264. if ((num_nodes = atoi(argv[argc-3])) > MAX_N) {
  265. printf("Maximum number of nodes allowed: %d\n", MAX_N);
  266. exit(0);
  267. };
  268. if ((root = atoi(argv[argc-2])) > num_nodes-1) {
  269. printf("Root node (%d) should be in the range [0,...,%d]\n", root, num_nodes-1);
  270. exit(0);
  271. };
  272. seed = atoi(argv[argc-1]);
  273.  
  274. // Initialize adjacency matrix of graph
  275. A = init_adj_matrix(num_nodes, seed);
  276.  
  277. clock_gettime(CLOCK_REALTIME, &start);
  278.  
  279. // Compute single source shortest path with root node r
  280. mst = minimum_spanning_tree(A, root);
  281.  
  282. // Compute time taken
  283. clock_gettime(CLOCK_REALTIME, &stop);
  284. total_time = (stop.tv_sec-start.tv_sec) + 0.000000001 * (stop.tv_nsec-start.tv_nsec);
  285.  
  286. // Print results
  287. unsigned int i, j;
  288. printf(" MST: Nodes=%d, MST Weight = %e, time (sec) = %8.4f\n", A->n, mst->mst_weight, total_time);
  289.  
  290. // mod
  291. clock_gettime(CLOCK_REALTIME, &start);
  292. my_mst = parallel_mst(A, root);
  293. clock_gettime(CLOCK_REALTIME, &stop);
  294. total_time = (stop.tv_sec-start.tv_sec) + 0.000000001 * (stop.tv_nsec-start.tv_nsec);
  295. printf("parallel MST: Nodes=%d, MST Weight = %e, time (sec) = %8.4f\n", A->n, my_mst->mst_weight, total_time);
  296. // end
  297. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement