annotate src/find_connected.c @ 1:7eab80f86779 draft

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