-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathpercolation.h
More file actions
337 lines (256 loc) · 10.1 KB
/
percolation.h
File metadata and controls
337 lines (256 loc) · 10.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
#ifndef PERCOLATION_H
#define PERCOLATION_H
// percolation.h: a class that performs percolation measurements given
// 1) The arbitrary list of Neighbors or Nodes
// 2) The "occupation" of the nodes, as 0 or 1
//
// Hoshen-Kopelman algorithm by Grant Watson, see https://github.com/MelkoCollective/extended_hk
// last update August 17, 2013, 5892ff451f1f014b6c6bc76681476a2e84527d51
#include <boost/multi_array.hpp>
#define PRINT_RED(x) std::cout << "\033[1;31m" << x << "\033[0m" << " "
#define PRINT_BLUE(x) std::cout << "\033[1;34m" << x << "\033[0m" << " "
#define PRINT_GREEN(x) std::cout << "\033[1;32m" << x << "\033[0m" << " "
#define PRINT_YELLOW(x) std::cout << "\033[1;33m" << x << "\033[0m" << " "
class Percolation
{
private:
int N_;
boost::multi_array<int, 1> UniqueClusters;
boost::multi_array<int, 1> ClustSize; //the size of each cluster
//all below from Grant's hk.cpp -------------
int n_labels; //the length of the labels array
int *labels;
int uf_find(int x);
int uf_union(int x, int y);
int uf_make_set(void);
void uf_initialize(int max_labels);
void uf_done(void);
//-------------------------------------------
public:
double Avg_Clust_Size;
double Largest_Clust_Size;
int NumberClusters;
Percolation(const int & N);
void zero();
void print();
void DetermineClusters(const boost::multi_array<int, 2>& nbs,
const boost::multi_array<int, 1>& occupancy);
//void record(double & energy, Spins & sigma);
void output(const double & T, const int & MCS);
//Headers from Grant's hk.h file, worked into this class
//-------------------------------------------
void extended_hoshen_kopelman(boost::multi_array<int, 1>& node_labels,
const boost::multi_array<int, 2>& nbs,
const boost::multi_array<int, 1>& occupancy);
void extended_hk_no_boost(int* node_labels, int const* const* nbs,
const int* occupancy, int N, int m);
int hoshen_kopelman(int **matrix, int m, int n);
};
//constructor
Percolation::Percolation(const int & N){
N_ = N; //number of ising variables that can be in a cluster
n_labels = 0; /* length of the labels array */
Avg_Clust_Size= 0;
Largest_Clust_Size = 0;
}
void Percolation::print(){
PRINT_YELLOW("Cluster determination")<<endl;
cout<<"there are "<<NumberClusters<<" labels \n";
for (int i=0; i<N_; i++){
cout<<UniqueClusters[i]<<" ";
}
cout<<endl;
//print each cluster's size
PRINT_GREEN("Each cluster has a size (zero included):")<<endl;
for (int i=0; i<=NumberClusters; i++)
cout<<ClustSize[i]<<endl;
cout<<Avg_Clust_Size<<" ";
cout<<Largest_Clust_Size<<endl;
}//print
void Percolation::zero(){
Avg_Clust_Size = 0.0;
Largest_Clust_Size= 0.0;
}//zero
void Percolation::DetermineClusters(const boost::multi_array<int, 2>& nbs,
const boost::multi_array<int, 1>& occupancy) {
extended_hoshen_kopelman(UniqueClusters,nbs,occupancy);
ClustSize.resize(boost::extents[NumberClusters+1]); //resize
fill(ClustSize.begin(),ClustSize.end(),0); //reinitialize
for (int i=0; i<N_; i++) { //note 0 is not a cluster
ClustSize[UniqueClusters[i]] ++;
}
double Asize=0;
int Lclust =0;
if (NumberClusters !=0 ){
for (int i=1; i<(NumberClusters+1); i++){
Asize += 1.0*ClustSize[i]; //average cluster size
if (ClustSize[i] > Lclust) Lclust = ClustSize[i]; //largest cluster size
}
Asize /= 1.0*NumberClusters;
}
Avg_Clust_Size += Asize;
Largest_Clust_Size += 1.0*Lclust;
}//DetermineClusters
void Percolation::output(const double & T, const int & MCS){
ofstream cfout;
cfout.open("01.data",ios::app);
cfout<<T<<" ";
cfout<<Avg_Clust_Size/(1.0*MCS*N_)<<" ";
cfout<<Largest_Clust_Size/(1.0*MCS*N_)<<" ";
cfout<<endl;
cfout.close();
}//output
/*-------------------------------------------------------------------------------------------
below, the hk.cpp file from
https://github.com/MelkoCollective/extended_hk
-------------------------------------------------------------------------------------------*/
/* Tobin Fricke's original code with an extended version of the HK algorithm
added. The extension borrows some ideas from:
http://gaia.pge.utexas.edu/papers/AFTWPPhysicaA.pdf
Requirements:
-Boost
-compiler ? - ?
Copyright (c) September 9, 2000, by Tobin Fricke <tobin@pas.rochester.edu>
Extended 2013-08-14 Grant Watson
Modified 2002-03-09 Tobin Fricke
Modified substantially 2004-04-21 by Tobin Fricke
Fricke's code available at:
http://www.ocf.berkeley.edu/~fricke/projects/hoshenkopelman/hoshenkopelman.html
*/
//#include <boost/phoenix.hpp>
#include <algorithm>
#include <cassert>
#include <new>
using namespace std;
/* Implementation of Union-Find Algorithm */
/* The 'labels' array has the meaning that labels[x] is an alias for the label x; by
following this chain until x == labels[x], you can find the canonical name of an
equivalence class. The labels start at one; labels[0] is a special value indicating
the highest label already used. */
// SEE PRIVATE CLASS MEMBERS
//int *labels;
//int n_labels = 0; /* length of the labels array */
/* uf_find returns the canonical label for the equivalence class containing x */
int Percolation::uf_find(int x) {
int y = x;
while (labels[y] != y)
y = labels[y];
while (labels[x] != x) {
int z = labels[x];
labels[x] = y;
x = z;
}
return y;
}
/* uf_union joins two equivalence classes and returns the canonical label of the resulting class. */
int Percolation::uf_union(int x, int y) {
return labels[uf_find(x)] = uf_find(y);
}
/* uf_make_set creates a new equivalence class and returns its label */
int Percolation::uf_make_set(void) {
labels[0]++;
assert(labels[0] < n_labels);
labels[labels[0]] = labels[0];
return labels[0];
}
/* uf_intitialize sets up the data structures needed by the union-find implementation. */
void Percolation::uf_initialize(int max_labels) {
n_labels = max_labels;
labels = new int[n_labels];
labels[0] = 0;
}
/* uf_done frees the memory used by the union-find data structures */
void Percolation::uf_done(void) {
n_labels = 0;
delete[] labels;
labels = 0;
}
/* End Union-Find implementation */
/* A generalized version of the HK algorithm for arbitrary networks of nodes.
*
* INPUT:
* -nbs: 2D array. ith row is the neighbours of node i. If a node has
* less neighbours than # of cols, fill the rest of the row with -1.
* -occupancy: 1D array with the occupation number (0 or 1) of the nodes.
* OUTPUT:
* -node_labels: an array of the labels of the nodes.
*/
void Percolation::extended_hoshen_kopelman(boost::multi_array<int, 1>& node_labels,
const boost::multi_array<int, 2>& nbs,
const boost::multi_array<int, 1>& occupancy) {
// Typedefs
typedef boost::multi_array<int, 2> array_2t;
typedef boost::multi_array<int, 1> array_1t;
typedef boost::multi_array_types::index_range range_t;
typedef boost::multi_array<int, 1>::const_iterator c_iter;
// Tools for multi-arrays.
array_1t::extent_gen extents;
array_2t::index_gen indices;
// Number of nodes.
const int N = nbs.shape()[0];
const int m = nbs.shape()[1];
// Initialize node_labels with N+1 since labels live in [1,N].
const int unlabelled = N+1;
node_labels.resize(extents[N]);
fill(node_labels.begin(),node_labels.end(),N+1);
// Initialize memory for binary forest of labels.
uf_initialize(N);
// Iterate over nodes and perform clustering.
for (int i = 0; i < N; ++i) {
if (occupancy[i]) {
// Get neighbours of node i ('i'th row of neighbours)
int n_nbs = m;
while (nbs[i][n_nbs - 1] == -1) // Find last neighbour.
n_nbs--;
array_2t::const_array_view<1>::type node_nbs =
nbs[ indices[i][range_t(0,n_nbs)] ];
// Get subset of labels using node_nbs as indices.
array_1t node_nbs_labels(extents[n_nbs]);
for (unsigned int j = 0; j < n_nbs; ++j) {
node_nbs_labels[j] = node_labels[node_nbs[j]];
}
c_iter begin = node_nbs_labels.begin();
c_iter end = node_nbs_labels.end();
// Check if node has no labelled neighbours.
bool is_alone = 1;
for (c_iter it = begin; is_alone && (it != end); ++it){
is_alone *= (*it == unlabelled);
}
// Labelling + merging
if(is_alone)
node_labels[i] = uf_make_set();
else {
// Find smallest label of the neighbours.
int min_label = *min_element(begin, end);
// Apply the minimum label to all labelled neighbours + current node.
node_labels[i] = min_label;
for (c_iter nb = node_nbs.begin(); nb != node_nbs.end(); ++nb)
if (node_labels[*nb] != unlabelled)
uf_union(min_label, node_labels[*nb]);
}
} //occupancy
} //node
/* This is a little bit sneaky.. we create a mapping from the canonical labels
determined by union/find into a new set of canonical labels, which are
guaranteed to be sequential. */
NumberClusters = 0;
int *new_labels = new int[n_labels]; // allocate array, initialized to zero
for (int i = 0; i < n_labels; i++) new_labels[i] = 0;
for (int i = 0; i < N; i++)
if (occupancy[i]) {
int x = uf_find(node_labels[i]);
if (new_labels[x] == 0) {
new_labels[0]++;
new_labels[x] = new_labels[0];
NumberClusters ++;
}
node_labels[i] = new_labels[x];
}
else {
node_labels[i] = 0; // Replace placeholders with 0.
}
// Cleanup
delete[] new_labels;
uf_done();
}
#endif