1 /* Generate a random graph, given the number of nodes, the number of
4 dump graph if "tofile" is true
5 Output form: directory graphN/ containing files graph0 ... graphN-1
6 file graphK has C, the number of connections, followed by
7 a list of C vertices that K is connected to
9 Modified from the original: changed output format, and converted main to a parametered function
14 /* comment this out to test and change CmiPrintf to printf */
16 #include "graphdefs.h"
18 int addEdge(VerticesListType
*graph
, EdgeListType
*l
,int fm
,int to
);
19 void addspEdge(VerticesListType
*graph
, EdgeListType
*, int, int);
20 int edgeExists(VerticesListType
*graph
, int fm
, int to
);
21 static Q
* makeQueue();
22 static int isEmpty(Q
*);
23 static int dequeue(Q
*);
26 int V
; /* no. of vertices */
27 int E
; /* no. of edges */
28 int C
; /* no. of connections per vertex */
30 VerticesListType
* InitVertices();
34 main(int argc, char **argv)
36 gengraph(atoi(argv[1]), atoi(argv[2]), atoi(argv[3]));
40 static void printOut(VerticesListType
*vertices
);
41 static void copyOut(VerticesListType
*vertices
, int *npe
, int *pes
);
42 static void initGraph(VerticesListType
*graph
);
43 static void diameter(VerticesListType
*graph
);
44 static void AddEdges(VerticesListType
*graph
, EdgeListType
*EdgeList
, int V
, int n
);
46 void gengraph(int pV
, int pC
, int pseed
, int *pes
, int *npe
, int tofile
)
48 VerticesListType graph
;
50 EdgeListType
* EdgeList
;
51 /* VerticesListType * vertices; */
52 extern EdgeListType
* InitEdgeList();
53 char dircmd
[20], dirname
[10];
60 CmiPrintf("for %d PEs, connectivity %d... \n", V
, C
);
62 /* make a directory */
63 if (tofile
&& CmiMyPe() == 0) {
64 sprintf(dirname
, "graph%d", V
);
65 sprintf(dircmd
, "mkdir %s", dirname
);
69 /* for (i=0; i<seed; i++) rand(); */
70 for (i
=0; i
<seed
; i
++) CrnRand();
71 if ((V
*C
%2) != 0) printf("V*C must be even\n");
74 EdgeList
= InitEdgeList(E
);
75 AddEdges(&graph
, EdgeList
, V
, E
);
76 /* vertices = (VerticesListType *) InitVertices(EdgeList, V,E); */
79 if (CmiMyPe()==0) printOut(&graph
);
81 else copyOut(&graph
, npe
, pes
);
83 if (CmiMyPe()==0) diameter(&graph
);
87 static void AddEdges(EdgeListType
*EdgeList
, int V
, int n
)
88 /* Add more edges to make up a total of E edges */
90 /* first add edges for a C-way spanning tree.*/
94 for (i
=0; i
< V
/c1
; i
++)
95 for (j
=0; j
<c1
; j
++) {
97 /* printf("considering (%d, %d)\n", i, w); */
99 addEdge(EdgeList
,i
,w
);
100 /* printf(" --- added.\n"); */
102 else /*printf(" not added.\n")*/;
111 } while (connections(x
) >= C
);
114 } while ((y
== x
) || connections(y
) >= C
);
115 } while (edgeExists(x
,y
));
116 addEdge(EdgeList
, x
, y
);
121 static void AddEdges(VerticesListType
*graph
, EdgeListType
*EdgeList
, int V
, int n
)
122 /* Add more edges to make up a total of E edges */
129 /* first add edges for a C-way spanning tree.*/
130 varr
=(int **)calloc(V
, sizeof(int*));
132 varr
[i
]=calloc(2, sizeof(int));
137 for (i
=0; i
<= V
/c1
; i
++)
138 for (j
=0; j
<c1
; j
++) {
141 addEdge(graph
, EdgeList
,i
,w
);
146 /*varr is array of vertices and free connection for each vertex*/
149 if(connections(graph
, i
)<C
)
152 varr
[j
][1]=C
-connections(graph
,i
);
156 CmiAssert(varrlen
>0);
158 /*for all edges except last 10 , edge is formed by randomly selecting vertices from varr*/
163 for (j=0; j<n-10; j++)
167 x = rand() % varrlen;
169 y = rand() % varrlen;
171 }while (edgeExists(varr[x][0],varr[y][0]));
172 addEdge(EdgeList, varr[x][0], varr[y][0]);
174 varr[x][1]=varr[x][1]-1;
175 varr[y][1]=varr[y][1]-1;
177 //If no free connections left for a vertex remove it from varr
181 for (i=x;i<varrlen-1;i++)
183 varr[i][0]=varr[i+1][0];
184 varr[i][1]=varr[i+1][1];
192 for (i=y-1;i<varrlen-1;i++)
194 varr[i][0]=varr[i+1][0];
195 varr[i][1]=varr[i+1][1];
200 else if (varr[y][1]==0) {
201 for (i=y;i<varrlen-1;i++)
203 varr[i][0]=varr[i+1][0];
204 varr[i][1]=varr[i+1][1];
210 //for last 10 edges, first vertex is one with max free connections and other vertex is randomly chosen
212 if (n>10) k=10; else k = n;*/
220 for (i
=0;i
<varrlen
;i
++)
221 if (varr
[i
][1]>max
) { max
=varr
[i
][1];maxi
=i
;}
224 y
= rand() % varrlen
;
227 /*if (edgeExists(varr[x][0],varr[y][0]))
228 if (j==k-1) addspEdge(EdgeList,varr[x][0],varr[y][0]);
230 y = rand() % varrlen;
232 else addEdge(EdgeList,varr[x][0],varr[y][0]); */
234 if (edgeExists(graph
, varr
[x
][0],varr
[y
][0])&&(j
==k
-1))
235 addspEdge(graph
, EdgeList
,varr
[x
][0],varr
[y
][0]);
238 while((y
==x
)||(edgeExists(graph
,varr
[x
][0],varr
[y
][0])))
239 y
= rand() % varrlen
;
240 addEdge(graph
,EdgeList
,varr
[x
][0],varr
[y
][0]);
243 varr
[x
][1]=varr
[x
][1]-1;
244 varr
[y
][1]=varr
[y
][1]-1;
249 for (i
=x
;i
<varrlen
-1;i
++)
251 varr
[i
][0]=varr
[i
+1][0];
252 varr
[i
][1]=varr
[i
+1][1];
260 for (i
=y
-1;i
<varrlen
-1;i
++)
262 varr
[i
][0]=varr
[i
+1][0];
263 varr
[i
][1]=varr
[i
+1][1];
268 else if (varr
[y
][1]==0)
270 for (i
=y
;i
<varrlen
-1;i
++)
272 varr
[i
][0]=varr
[i
+1][0];
273 varr
[i
][1]=varr
[i
+1][1];
278 for (i
=0;i
<V
;i
++) free(varr
[i
]);
283 void fillAdjArray(Edge
*edges
, VerticesListType
*vlist
, int V
, int E
);
284 void sortAdjArrays(VerticesListType
*vlist
);
285 static void sort(int *adj
, int fromIndex
, int toIndex
);
286 void countDegrees(Edge
*edges
, Vertex
*vertRecs
, int V
, int E
);
289 InitVertices(EdgeList
, V
,E
)
290 EdgeListType
* EdgeList
;
293 { /* returns a structure of type VerticesListType, which contains an arry of
294 vertex records, and an array of adjacency information. See typedef. */
295 /* First allocate the adjacency subarray of size E, and vertex subarray size V.
296 Then count the occurences of each vertex in the Edgelist in vertex.degree.
297 Then compute the real adjListInd = sum from 0 to i-1 of the previous degrees.
298 Then, traverse edge list, and enter each edge in two adj lists.
299 Then sort individual adj-lists, separately. */
300 VerticesListType
* vlist
;
302 vlist
= (VerticesListType
*) malloc(sizeof(VerticesListType
));
304 vlist
->numVertices
= V
;
305 vlist
->vertexArray
= (Vertex
*) malloc(V
*sizeof(Vertex
));
306 _MEMCHECK(vlist
->vertexArray
);
307 vlist
->adjArray
= (int *) malloc(2*E
*sizeof(int));
308 /* as each edge is entered twice */
309 _MEMCHECK(vlist
->adjArray
);
310 countDegrees(EdgeList
->edges
, vlist
->vertexArray
, V
, E
);
311 fillAdjArray(EdgeList
->edges
, vlist
, V
, E
);
312 sortAdjArrays(vlist
);
316 void countDegrees(Edge
*edges
, Vertex
*vertRecs
, int V
, int E
)
317 { /* initialize the degrees of all vertices to 0.
318 Traverse the edge list, incrementing the degree of the 2 nodes for each edge.
323 { vertRecs
[i
].degree
= 0;
324 vertRecs
[i
].next
= 0;}
326 {vertRecs
[ edges
[i
].node1
].degree
++;
327 vertRecs
[ edges
[i
].node2
].degree
++;}
329 /* now fill adjListInd, by starting a counter at 0, and adding degrees of visited
333 { vertRecs
[i
].adjListInd
= count
;
334 count
+= vertRecs
[i
].degree
;
338 void fillAdjArray(Edge
*edges
, VerticesListType
*vlist
, int V
, int E
)
339 { /* Insert each edge <x,y> as an entry y in x's adj list, and vice versa. */
344 adj
= vlist
->adjArray
;
345 vertexRecs
= vlist
->vertexArray
;
348 { x
= edges
[i
].node1
; y
= edges
[i
].node2
;
349 adj
[ vertexRecs
[x
].adjListInd
+ vertexRecs
[x
].next
] = y
;
350 vertexRecs
[x
].next
++;
351 adj
[ vertexRecs
[y
].adjListInd
+ vertexRecs
[y
].next
] = x
;
352 vertexRecs
[y
].next
++;
356 void sortAdjArrays(VerticesListType
*vlist
)
357 { /* sort each section of the array corresponding to each vertex. */
361 V
= vlist
->numVertices
;
363 { sort(vlist
->adjArray
,
364 vlist
->vertexArray
[i
].adjListInd
,
365 vlist
->vertexArray
[i
].adjListInd
+ vlist
->vertexArray
[i
].degree
-1);
367 /* eliminate duplicates. May be should be merged with above? */
373 m
= vlist
->vertexArray
[i
].adjListInd
;
375 limit
= m
+ vlist
->vertexArray
[i
].degree
; /* this is the first index
376 not belonging to this vertex.*/
377 adj
= vlist
->adjArray
;
378 /* do this in 2 phases. First phase: m and n are exactly one away.
379 goes on until the first duplicate is found. In this phase, there
380 is no need to assign values (no shifting is going on.) */
381 while ((adj
[m
] != adj
[n
]) && (n
< limit
)) {m
++; n
++;}
384 while ((adj
[m
] == adj
[n
]) && (n
<limit
))
385 { n
++; dupcount
++; vlist
->vertexArray
[i
].degree
--;}
386 adj
[m
+1] = adj
[n
]; /*move the non duplicate back to its new position*/
390 /* printf("number of duplicate edges removed = %d\n", dupcount/2);*/
391 /* Here is an assignment to a global variable.... */
392 if ((dupcount
% 2) != 0) {printf("error. duplicates not even.\n"); }
396 static void sort(int *adj
, int fromIndex
, int toIndex
)
400 for (i
=toIndex
; ((i
>fromIndex
) && changed
); i
--)
402 for (j
=fromIndex
; j
<i
; j
++)
403 { if (adj
[j
] > adj
[j
+1])
414 static void copyOut(VerticesListType
*vertices
, int *npe
, int *pes
)
420 adj
= vertices
->adjArray
;
421 vertexRecs
= vertices
->vertexArray
;
423 #if CMK_NODE_QUEUE_AVAILABLE
424 *npe
= vertexRecs
[CmiMyNode()].degree
;
425 for (i
=0; i
<vertexRecs
[CmiMyNode()].degree
; i
++)
426 pes
[i
] = adj
[ vertexRecs
[CmiMyNode()].adjListInd
+ i
];
428 *npe
= vertexRecs
[CmiMyPe()].degree
;
429 for (i
=0; i
<vertexRecs
[CmiMyPe()].degree
; i
++)
430 pes
[i
] = adj
[ vertexRecs
[CmiMyPe()].adjListInd
+ i
];
434 static void printOut(VerticesListType
*vertices
)
441 adj
= vertices
->adjArray
;
442 vertexRecs
= vertices
->vertexArray
;
444 for (i
=0; i
<vertices
->numVertices
; i
++)
446 /* Open graphN/graphi */
447 sprintf(filename
, "graph%d/graph%d", vertices
->numVertices
, i
);
448 fp
= fopen(filename
, "w");
449 fprintf(fp
, "%d ", vertexRecs
[i
].degree
);
450 for (j
=0; j
<vertexRecs
[i
].degree
; j
++)
451 fprintf(fp
, "%d ", adj
[ vertexRecs
[i
].adjListInd
+ j
]);
457 static void initGraph(VerticesListType
*graph
)
459 graph
->numVertices
= V
;
460 graph
->vertexArray
= (Vertex
*) malloc(V
*sizeof(Vertex
));
461 _MEMCHECK(graph
->vertexArray
);
462 graph
->adjArray
= (int *) malloc(2*E
*sizeof(int));
463 _MEMCHECK(graph
->adjArray
);
465 for (i
=0; i
< V
; i
++) {
466 graph
->vertexArray
[i
].degree
= 0;
467 graph
->vertexArray
[i
].next
= i
*C
;
468 graph
->vertexArray
[i
].adjListInd
= i
*C
;
472 static void enqueue(Q
*q
, int i
);
474 static void diameter(VerticesListType
*graph
)
477 int i
,j
, k
, v
, w
, start
;
484 distance
= (int *)calloc(V
, sizeof(int));
485 histogram
= (int *)calloc(V
, sizeof(int));
487 for (i
=0; i
<V
; i
++) {
494 for (i
=0; i
<V
; i
++) {
495 /* run non-weighted shortes distance algorithm for each vertex i */
496 for (j
=0; j
<V
; j
++) distance
[j
] = -1;
499 while (! (isEmpty(q
))) {
502 start
=graph
->vertexArray
[v
].adjListInd
;
503 for (k
=0; k
< graph
->vertexArray
[i
].degree
; k
++) {
504 w
= graph
->adjArray
[k
+start
];
505 if (distance
[w
] == -1) {
506 distance
[w
] = distance
[v
] + 1;
511 for (j
=0; j
<V
; j
++) {
512 if (distance
[j
] > dia
) dia
= distance
[j
];
513 average
+= distance
[j
];
514 histogram
[ distance
[j
]]++;
517 average
= average
/ (V
*V
);
518 printf("the diameter is: %d, average internode distance = %f\n",
520 /*for (i = 0; i< 6; i++) printf("histo[%d] = %d\n", i, histogram[i]);*/
525 /* ------------------------------------------------- */
528 static Q
* makeQueue()
530 Q
*q
= (Q
*) malloc(sizeof(Q
));
536 q
->buf
= (int *) malloc(VMAX
*sizeof(int));
541 static void enqueue(Q
* q
, int i
) {
543 if (q
->tail
== q
->size
) q
->tail
= 0; /* no overflows possible */
548 static int dequeue(Q
*q
) {
550 r
= q
->buf
[q
->head
++];
551 if (q
->head
== q
->size
) q
->head
= 0;
556 static int isEmpty(Q
* q
) {
557 return (q
->numElements
== 0) ;