00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <stdio.h>
00012 #include <stdlib.h>
00013
00014
00015 #include "converse.h"
00016 #include "graphdefs.h"
00017
00018 void addEdge(VerticesListType *graph, EdgeListType *l,int fm,int to);
00019 void addspEdge(VerticesListType *graph, EdgeListType *, int, int);
00020 int edgeExists(VerticesListType *graph, int fm, int to);
00021 static Q * makeQueue(void);
00022 static int isEmpty(Q*);
00023 static int dequeue(Q*);
00024
00025 #define VMAX 2050
00026 int V;
00027 int E;
00028 int C;
00029
00030 VerticesListType * InitVertices(EdgeListType * EdgeList, int V, int E);
00031
00032
00033 extern "C" void gengraph(int, int, int, int *, int *, int);
00034
00035
00036
00037
00038
00039
00040
00041
00042 static void printOut(VerticesListType *vertices);
00043 static void copyOut(VerticesListType *vertices, int *npe, int *pes);
00044 static void initGraph(VerticesListType *graph);
00045 static void diameter(VerticesListType *graph);
00046 static void AddEdges(VerticesListType *graph, EdgeListType *EdgeList, int V, int n);
00047
00048 void gengraph(int pV, int pC, int pseed, int *pes, int *npe, int tofile)
00049 { int i;
00050 VerticesListType graph;
00051 int seed;
00052 EdgeListType * EdgeList;
00053
00054 extern EdgeListType * InitEdgeList(int);
00055 char dircmd[20], dirname[10];
00056
00057 V = pV;
00058 C = pC;
00059 seed = pseed;
00060
00061 if (CmiMyPe() == 0)
00062 CmiPrintf("for %d PEs, connectivity %d... \n", V, C);
00063
00064
00065 if (tofile && CmiMyPe() == 0) {
00066 sprintf(dirname, "graph%d", V);
00067 sprintf(dircmd, "mkdir %s", dirname);
00068 if (system(dircmd) == -1) {
00069 CmiAbort("CLD> call to system() failed!");
00070 }
00071 }
00072
00073
00074 for (i=0; i<seed; i++) CrnRand();
00075 if ((V*C %2) != 0) printf("V*C must be even\n");
00076 E = V*C/2;
00077 initGraph(&graph);
00078 EdgeList = InitEdgeList(E);
00079 AddEdges(&graph, EdgeList, V, E);
00080
00081
00082 if (tofile) {
00083 if (CmiMyPe()==0) printOut(&graph);
00084 }
00085 else copyOut(&graph, npe, pes);
00086
00087 if (CmiMyPe()==0) diameter(&graph);
00088 }
00089
00090 #if 0
00091 static void AddEdges(EdgeListType *EdgeList, int V, int n)
00092
00093 {int i,j,w,x,y;
00094
00095 int c1;
00096 if (C>1) c1 = C-1;
00097
00098 for (i=0; i< V/c1; i++)
00099 for (j=0; j<c1; j++) {
00100 w = c1*i + j +1;
00101
00102 if (w < V) {
00103 addEdge(EdgeList,i,w);
00104
00105 }
00106 else ;
00107 }
00108 n -= (V-1);
00109
00110 for (i=0; i<n; i++)
00111 {
00112 do {
00113 do {
00114 x = CrnRand() % V;
00115 } while (connections(x) >= C);
00116 do {
00117 y = CrnRand() % V;
00118 } while ((y== x) || connections(y) >= C);
00119 } while (edgeExists(x,y));
00120 addEdge(EdgeList, x, y);
00121 }
00122 }
00123 #endif
00124
00125 static void AddEdges(VerticesListType *graph, EdgeListType *EdgeList, int V, int n)
00126
00127 { int i,j,w,x,y,k;
00128 int c1,max,maxi;
00129 int **varr;
00130 int varrlen,count=0;
00131 int flag=0;
00132
00133
00134 varr=(int **)calloc(V, sizeof(int*));
00135 for (i=0;i<V;i++)
00136 varr[i] = (int *)calloc(2, sizeof(int));
00137
00138 c1 = 1;
00139 if (C>1) c1 = C-1;
00140
00141 for (i=0; i<= V/c1; i++)
00142 for (j=0; j<c1; j++) {
00143 w = c1*i + j +1;
00144 if (w < V) {
00145 addEdge(graph, EdgeList,i,w);
00146 count++;
00147 }
00148 }
00149
00150
00151 j=0;
00152 for (i=0;i<V;i++)
00153 if(connections(graph, i)<C)
00154 {
00155 varr[j][0]=i;
00156 varr[j][1]=C-connections(graph,i);
00157 j++;
00158 }
00159 varrlen=j;
00160 CmiAssert(varrlen>0);
00161
00162
00163
00164 n -= count;
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218 k=n;
00219 for (j=0;j<k;j++)
00220 {
00221 flag=0;
00222 max=0;
00223 maxi=0;
00224 for (i=0;i<varrlen;i++)
00225 if (varr[i][1]>max) { max=varr[i][1];maxi=i;}
00226 x = maxi;
00227 do {
00228 y = rand() % varrlen;
00229 } while (y == x) ;
00230
00231
00232
00233
00234
00235
00236
00237
00238 if (edgeExists(graph, varr[x][0],varr[y][0])&&(j==k-1))
00239 addspEdge(graph, EdgeList,varr[x][0],varr[y][0]);
00240 else
00241 {
00242 while((y==x)||(edgeExists(graph,varr[x][0],varr[y][0])))
00243 y = rand() % varrlen;
00244 addEdge(graph,EdgeList,varr[x][0],varr[y][0]);
00245 }
00246
00247 varr[x][1]=varr[x][1]-1;
00248 varr[y][1]=varr[y][1]-1;
00249
00250 if (varr[x][1]==0)
00251 {
00252 flag=1;
00253 for (i=x;i<varrlen-1;i++)
00254 {
00255 varr[i][0]=varr[i+1][0];
00256 varr[i][1]=varr[i+1][1];
00257 }
00258 varrlen--;
00259 }
00260 if ((y>x)&&(flag))
00261 {
00262 if (varr[y-1][1]==0)
00263 {
00264 for (i=y-1;i<varrlen-1;i++)
00265 {
00266 varr[i][0]=varr[i+1][0];
00267 varr[i][1]=varr[i+1][1];
00268 }
00269 varrlen--;
00270 }
00271 }
00272 else if (varr[y][1]==0)
00273 {
00274 for (i=y;i<varrlen-1;i++)
00275 {
00276 varr[i][0]=varr[i+1][0];
00277 varr[i][1]=varr[i+1][1];
00278 }
00279 varrlen--;
00280 }
00281 }
00282 for (i=0;i<V;i++) free(varr[i]);
00283 free(varr);
00284 }
00285
00286
00287 void fillAdjArray(Edge *edges, VerticesListType *vlist, int V, int E);
00288 void sortAdjArrays(VerticesListType *vlist);
00289 static void sort(int *adj, int fromIndex, int toIndex);
00290 void countDegrees(Edge *edges, Vertex *vertRecs, int V, int E);
00291
00292 VerticesListType *
00293 InitVertices(EdgeListType * EdgeList, int V, int E)
00294 {
00295
00296
00297
00298
00299
00300
00301 VerticesListType * vlist;
00302
00303 vlist = (VerticesListType *) malloc(sizeof(VerticesListType));
00304 _MEMCHECK(vlist);
00305 vlist->numVertices = V;
00306 vlist->vertexArray = (Vertex *) malloc(V*sizeof(Vertex));
00307 _MEMCHECK(vlist->vertexArray);
00308 vlist->adjArray = (int *) malloc(2*E*sizeof(int));
00309
00310 _MEMCHECK(vlist->adjArray);
00311 countDegrees(EdgeList->edges, vlist->vertexArray, V, E);
00312 fillAdjArray(EdgeList->edges, vlist, V, E);
00313 sortAdjArrays(vlist);
00314 return(vlist);
00315 }
00316
00317 void countDegrees(Edge *edges, Vertex *vertRecs, int V, int E)
00318 {
00319
00320
00321 int i, count;
00322
00323 for (i=0; i<V; i++)
00324 { vertRecs[i].degree = 0;
00325 vertRecs[i].next = 0;}
00326 for (i=0; i<E; i++)
00327 {vertRecs[ edges[i].node1 ].degree++;
00328 vertRecs[ edges[i].node2 ].degree++;}
00329
00330
00331
00332 count = 0;
00333 for (i=0; i<V; i++)
00334 { vertRecs[i].adjListInd = count;
00335 count += vertRecs[i].degree;
00336 }
00337 }
00338
00339 void fillAdjArray(Edge *edges, VerticesListType *vlist, int V, int E)
00340 {
00341 int i, x,y;
00342 int * adj;
00343 Vertex * vertexRecs;
00344
00345 adj = vlist->adjArray;
00346 vertexRecs = vlist->vertexArray;
00347
00348 for (i=0; i<E; i++)
00349 { x = edges[i].node1; y = edges[i].node2;
00350 adj[ vertexRecs[x].adjListInd + vertexRecs[x].next ] = y;
00351 vertexRecs[x].next++;
00352 adj[ vertexRecs[y].adjListInd + vertexRecs[y].next ] = x;
00353 vertexRecs[y].next++;
00354 }
00355 }
00356
00357 void sortAdjArrays(VerticesListType *vlist)
00358 {
00359 int V, i;
00360 int dupcount;
00361
00362 V = vlist->numVertices;
00363 for (i=0; i<V; i++)
00364 { sort(vlist->adjArray,
00365 vlist->vertexArray[i].adjListInd,
00366 vlist->vertexArray[i].adjListInd + vlist->vertexArray[i].degree -1);
00367 }
00368
00369 dupcount = 0;
00370 for (i=0; i<V; i++)
00371 { int m,n, limit;
00372 int * adj;
00373
00374 m = vlist->vertexArray[i].adjListInd;
00375 n = m+1;
00376 limit = m + vlist->vertexArray[i].degree;
00377
00378 adj = vlist->adjArray;
00379
00380
00381
00382 while ((adj[m] != adj[n]) && (n < limit)) {m++; n++;}
00383
00384 while (n<limit) {
00385 while ((adj[m] == adj[n]) && (n<limit))
00386 { n++; dupcount++; vlist->vertexArray[i].degree--;}
00387 adj[m+1] = adj[n];
00388 m++; n++;
00389 }
00390 }
00391
00392
00393 if ((dupcount % 2) != 0) {printf("error. duplicates not even.\n"); }
00394 E -= dupcount/2;
00395 }
00396
00397 static void sort(int *adj, int fromIndex, int toIndex)
00398 { int i,j, tmp;
00399 short changed;
00400 changed = 1;
00401 for (i=toIndex; ((i>fromIndex) && changed); i--)
00402 { changed = 0;
00403 for (j=fromIndex; j<i; j++)
00404 { if (adj[j] > adj[j+1])
00405 {
00406 changed = 1;
00407 tmp = adj[j];
00408 adj[j] = adj[j+1];
00409 adj[j+1] = tmp;
00410 }
00411 }
00412 }
00413 }
00414
00415 static void copyOut(VerticesListType *vertices, int *npe, int *pes)
00416 {
00417 int i;
00418 int * adj;
00419 Vertex * vertexRecs;
00420
00421 adj = vertices->adjArray;
00422 vertexRecs = vertices->vertexArray;
00423
00424 #if CMK_NODE_QUEUE_AVAILABLE
00425 *npe = vertexRecs[CmiMyNode()].degree;
00426 for (i=0; i<vertexRecs[CmiMyNode()].degree; i++)
00427 pes[i] = adj[ vertexRecs[CmiMyNode()].adjListInd + i ];
00428 #else
00429 *npe = vertexRecs[CmiMyPe()].degree;
00430 for (i=0; i<vertexRecs[CmiMyPe()].degree; i++)
00431 pes[i] = adj[ vertexRecs[CmiMyPe()].adjListInd + i ];
00432 #endif
00433 }
00434
00435 static void printOut(VerticesListType *vertices)
00436 {int i,j;
00437 int * adj;
00438 Vertex * vertexRecs;
00439 FILE *fp;
00440 char filename[40];
00441
00442 adj = vertices->adjArray;
00443 vertexRecs = vertices->vertexArray;
00444
00445 for (i=0; i<vertices->numVertices; i++)
00446 {
00447
00448 sprintf(filename, "graph%d/graph%d", vertices->numVertices, i);
00449 fp = fopen(filename, "w");
00450 fprintf(fp, "%d ", vertexRecs[i].degree);
00451 for (j=0; j<vertexRecs[i].degree; j++)
00452 fprintf(fp, "%d ", adj[ vertexRecs[i].adjListInd + j ]);
00453 fprintf(fp, "\n");
00454 fclose(fp);
00455 }
00456 }
00457
00458 static void initGraph(VerticesListType *graph)
00459 { int i;
00460 graph->numVertices = V;
00461 graph->vertexArray = (Vertex *) malloc(V*sizeof(Vertex));
00462 _MEMCHECK(graph->vertexArray);
00463 graph->adjArray = (int *) malloc(2*E*sizeof(int));
00464 _MEMCHECK(graph->adjArray);
00465
00466 for (i=0; i< V; i++) {
00467 graph->vertexArray[i].degree = 0;
00468 graph->vertexArray[i].next = i*C;
00469 graph->vertexArray[i].adjListInd = i*C;
00470 }
00471 }
00472
00473 static void enqueue(Q *q, int i);
00474
00475 static void diameter(VerticesListType *graph)
00476 {
00477 extern Q * makeQueue(void);
00478 int i,j, k, v, w, start;
00479 int *distance;
00480 int *histogram;
00481 Q * q;
00482 int dia;
00483 float average;
00484
00485 distance = (int *)calloc(V, sizeof(int));
00486 histogram = (int *)calloc(V, sizeof(int));
00487
00488 for (i=0; i<V; i++) {
00489 histogram[i] = 0;
00490 }
00491
00492 dia = 0;
00493 average = 0.0;
00494 q = makeQueue();
00495 for (i=0; i<V; i++) {
00496
00497 for (j=0; j<V; j++) distance[j] = -1;
00498 distance[i] = 0;
00499 enqueue(q, i);
00500 while (! (isEmpty(q))) {
00501 v = dequeue(q);
00502
00503 start=graph->vertexArray[v].adjListInd;
00504 for (k=0; k< graph->vertexArray[i].degree; k++) {
00505 w = graph->adjArray[k+start];
00506 if (distance[w] == -1) {
00507 distance[w] = distance[v] + 1;
00508 enqueue(q, w);
00509 }
00510 }
00511 }
00512 for (j=0; j<V; j++) {
00513 if (distance[j] > dia) dia = distance[j];
00514 average += distance[j];
00515 histogram[ distance[j]]++;
00516 }
00517 }
00518 average = average / (V*V);
00519 printf("the diameter is: %d, average internode distance = %f\n",
00520 dia, average);
00521
00522 free(distance);
00523 free(histogram);
00524 }
00525
00526
00527
00528
00529 static Q * makeQueue(void)
00530 {
00531 Q *q = (Q *) malloc(sizeof(Q));
00532 _MEMCHECK(q);
00533 q->size = VMAX;
00534 q->numElements = 0;
00535 q->head = 1;
00536 q->tail = 0;
00537 q->buf = (int *) malloc(VMAX*sizeof(int));
00538 _MEMCHECK(q->buf);
00539 return q;
00540 }
00541
00542 static void enqueue(Q * q, int i) {
00543 q->tail++;
00544 if (q->tail == q->size) q->tail = 0;
00545 q->buf[q->tail] = i;
00546 q->numElements++;
00547 }
00548
00549 static int dequeue(Q *q) {
00550 int r;
00551 r = q->buf[q->head++];
00552 if (q->head == q->size) q->head = 0;
00553 q->numElements--;
00554 return r;
00555 }
00556
00557 static int isEmpty(Q * q) {
00558 return (q->numElements == 0) ;
00559 }