annotate cross_sample/src/find_connected.c @ 3:5f670146a9af draft

Uploaded
author immport-devteam
date Mon, 27 Feb 2017 13:29:54 -0500
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
3
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
1 #include <stdlib.h>
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
2 #include <stdio.h>
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
3 #include <string.h>
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
4 #include <assert.h>
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
5
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
6 //static const char *rcsid = "$Id: find_connected.c,v 1.1 2008/09/05 21:54:40 rpl Exp $";
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
7
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
8 int find_connected(int **G, int num_dense_grids, int ndim, int *grid_clusterID);
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
9 void depth_first(int startnode);
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
10
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
11 void bail(const char *); /* exits via abort */
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
12 static void check_clusters(int *gcID, int ndense);
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
13 static void merge_cluster(int from, int into);
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
14
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
15
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
16 /* Vars that will not change througout the depth-first recursion. We
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
17 store them here to avoid endless replication on the stack. */
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
18 static int **Gr=0;
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
19 static int *gcID = 0; /* grid cluster IDs */
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
20 static int *cluster_count=0; /* count of nodes per cluster */
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
21 static int ndense=0;
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
22 static int ndim=0;
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
23 /* cid changes between depth-first searches, but is constant within a
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
24 single search, so it goes here. */
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
25 static int cid=0;
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
26
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
27 /* Find connected components in the graph of neighboring grids defined in G.
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
28 *
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
29 * Output:
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
30 *
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
31 * grid_clusterID[] -- cluster to which each dense grid was assigned
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
32 * return value -- number of clusters assigned.
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
33 */
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
34 int find_connected(int **G, int n_dense_grids, int num_dm, int *grid_clusterID)
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
35 {
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
36 int nclust=0; /* number of clusters found */
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
37 int i;
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
38 int *subfac;
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
39 int subval=0,nempty=0;
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
40 int clustid=0;
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
41
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
42 size_t sz = n_dense_grids*sizeof(int);
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
43 cluster_count = malloc(sz);
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
44 if(!cluster_count)
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
45 bail("find_connected: Unable to allocate %zd bytes.\n");
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
46 memset(cluster_count,0,sz);
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
47
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
48 /* set up the statics that will be used in the DFS */
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
49 Gr=G;
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
50 gcID = grid_clusterID;
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
51 ndense = n_dense_grids;
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
52 ndim = num_dm;
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
53
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
54
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
55 for(i=0;i<ndense;++i)
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
56 grid_clusterID[i] = -1;
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
57
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
58 for(i=0;i<ndense;++i) {
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
59 if(grid_clusterID[i] < 0) { /* grid hasn't been assigned yet */
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
60 cid = nclust++;
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
61 depth_first(i);
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
62 }
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
63 }
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
64
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
65 #ifndef NDEBUG
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
66 check_clusters(gcID,ndense);
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
67 #endif
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
68
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
69 /* At this point we probably have some clusters that are empty due to merging.
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
70 We want to compact the cluster numbering to eliminate the empty clusters. */
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
71
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
72 subfac = malloc(sz);
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
73 if(!subfac)
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
74 bail("find_connected: Unable to allocate %zd bytes.\n");
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
75 subval=0;
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
76 nempty=0;
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
77
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
78 /* cluster #i needs to have its ID decremented by 1 for each empty cluster with
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
79 ID < i. Precaclulate the decrements in this loop: */
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
80 for(i=0;i<nclust;++i) {
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
81 //clustid = grid_clusterID[i];
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
82 if(cluster_count[i] == 0) {
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
83 subval++;
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
84 nempty++;
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
85 }
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
86 subfac[i] = subval;
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
87 }
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
88
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
89 /* Now apply the decrements to all of the dense grids */
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
90 for(i=0;i<ndense;++i) {
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
91 clustid = grid_clusterID[i];
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
92 grid_clusterID[i] -= subfac[clustid];
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
93 }
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
94
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
95 #ifndef NDEBUG
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
96 // check_clusters(gcID,ndense);
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
97 #endif
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
98
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
99 /* correct the number of clusters found */
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
100 nclust -= nempty;
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
101
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
102 return nclust;
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
103 }
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
104
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
105
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
106 /* Do a depth-first search for a single connected component in graph
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
107 * G. Start from node, tag the nodes found with cid, and record
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
108 * the tags in grid_clusterID. Also, record the node count in
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
109 * cluster_count. If we find a node that has already been assigned to
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
110 * a cluster, that means we're merging two clusters, so zero out the
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
111 * old cid's node count.
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
112 *
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
113 * Note that our graph is constructed as a DAG, so we can be
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
114 * guaranteed to terminate without checking for cycles.
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
115 *
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
116 * Note2: this function can potentially recurse to depth = ndense.
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
117 * Plan stack size accordingly.
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
118 *
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
119 * Output:
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
120 *
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
121 * grid_clusterID[] -- array where we tag the nodes.
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
122 * cluster_count[] -- count of the number of nodes per cluster.
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
123 */
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
124
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
125 void depth_first(int node)
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
126 {
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
127 int i;
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
128
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
129 if(gcID[node] == cid) // we're guaranteed no cycles, but it is possible to reach a node
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
130 return; // through two different paths in the same cluster. This early
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
131 // return saves us some unneeded work.
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
132
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
133 /* Check to see if we are merging a cluster */
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
134 if(gcID[node] >= 0) {
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
135 /* We are, so zero the count for the old cluster. */
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
136 cluster_count[ gcID[node] ] = 0;
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
137 merge_cluster(gcID[node], cid);
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
138 return;
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
139 }
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
140
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
141 /* Update for this node */
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
142 gcID[node] = cid;
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
143 cluster_count[cid]++;
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
144
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
145 /* Recursively search the child nodes */
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
146 for(i=0; i<ndim; ++i)
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
147 if(Gr[node][i] >= 0) /* This is a child node */
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
148 depth_first(Gr[node][i]);
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
149 }
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
150
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
151 void bail(const char *msg)
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
152 {
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
153 fprintf(stderr,"%s",msg);
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
154 abort();
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
155 }
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
156
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
157
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
158 static void check_clusters(int *gcID, int ndense)
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
159 {
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
160 int i;
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
161
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
162 for(i=0; i<ndense; ++i)
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
163 if(gcID[i] < 0) {
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
164 fprintf(stderr,"faulty cluster id at i= %d\n",i);
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
165 abort();
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
166 }
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
167 }
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
168
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
169 static void merge_cluster(int from, int into)
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
170 {
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
171 int i;
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
172
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
173 for(i=0; i<ndense; ++i)
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
174 if(gcID[i] == from)
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
175 gcID[i] = into;
5f670146a9af Uploaded
immport-devteam
parents:
diff changeset
176 }