-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPercolationSimulation.java
226 lines (123 loc) · 4.95 KB
/
PercolationSimulation.java
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
package union_find;
/***Given a system of size N*N with random open sites with respect to a given probability, find whether the system percolates.
*
*/
public class PercolationSimulation{
/***
* The probability determines whether a site is open or not. if the site is open, we check its neighbours on top,left,right and bottom
* if any of the neighbour sites is open, we connect them. This will happen for each site on the system.
*
* we then iterate through the first and bottom row to check whether their is a site connection, if ther is then the system percolates if not
* it doesn't percolate.
*
* to accomplish this we need a 2D array for the grid, a parent array to track connections between sites, and the quick union algorithm for
* connecting open sites and finding whether sites are connected.
*/
private int [][] grid; //for the grid
private int[] parent; // for tracking the connected id's
private int gridSize; //size of the grid
// constructor
PercolationSimulation(int size) {
gridSize = size;
grid = new int[size][size];
parent = new int[size*size];
for(int i= 0; i<size*size; i++) {
parent[i] = i; // each site has its unique id that corresponds to its index on the array
}
}
//method 1 - opening a site
public void openSite(double probability) {
/**iterate over the rows and columns, set the probability and assign value 1 to mark an open site.
* Note this is random, so if the probability is low, then the site is likely to remain closed and viceversa
*/
for (int i = 0; i < gridSize * gridSize; i++) {
int currentSiteRow = i / gridSize; // Calculate row index
int currentSiteCol = i % gridSize; // Calculate column index
if((double)Math.random()<probability) {
grid[currentSiteRow][currentSiteCol] = 1;
connectNeighbours(currentSiteRow,currentSiteCol);
}
}
}
//method 2 - checks if the site is open
public boolean isOpen(int row, int column) {
/**logic is if the site is open then its value is 1 */
return grid[row][column]==1;
}
//method 3 - checks whether a row and column are valid
public boolean isValid(int row, int column) {
return row>=0 && row<gridSize && column>=0 && column<gridSize;
}
//method 4 - connect the neighbours
public void connectNeighbours(int row, int column) {
//check left neighbor
connectIfOpen(row,column,row,column-1);
//check right neighbor
connectIfOpen(row,column,row,column+1);
//check top
connectIfOpen(row,column,row+1,column);
//check bottom
connectIfOpen(row,column,row-1,column);
}
//method 5 - connects only open sites
private void connectIfOpen(int currentrow, int currentcolumn, int neighbourRow, int neighbourColumn) {
//connection happens if isValid and isOpen
if(isValid(neighbourRow, neighbourColumn) && isOpen(neighbourRow, neighbourColumn)) {
//convert sites to 1D array coordinates
int currentSite = currentrow * grid.length + currentcolumn;
int neighboursite = neighbourRow * grid.length + neighbourColumn;
union(currentSite,neighboursite); //quick union method
}
}
//method 6 - quick find
private int find(int site) {
/***connected sites will have the same value for site == 1 */
while(site != parent[site]) {
parent[site] = parent[parent[site]];
site = parent[site];
}
return site;
}
//method 7 - does the system percolate?
private boolean percolates() {
/***logic - if it does then atleast one of the points on the top row should connect with one of the points on the bottom row
* iterate both top and bottom at the same time while comparing each point
*/
for (int i = 0; i<gridSize; i++) {
int top = i;
int bottom = (gridSize*gridSize) - i - 1;
if(isConnected(top,bottom)) {
return true;
}
}
return false;
}
//method 8 - given two sites are they connected?
private boolean isConnected(int i, int j) {
/**logic if they are the find method should return same value for both */
return find(i) == find(j);
}
//method 9 - quick union algorithm
private void union(int currentSite, int neighboursite) {
int root_current_site = find(currentSite);
int root_neighbour_site = find(neighboursite);
parent[root_neighbour_site] = root_current_site;
}
//method 10 - Test
public static void main(String[] args) {
PercolationSimulation sm = new PercolationSimulation(20);
sm.openSite(0.6);
if(sm.percolates()) {
System.out.println("System percolates");
}
else {
System.out.println("System does not percolate");
}
for (int i = 0; i<sm.grid.length;i++) {
for (int j = 0; j<sm.grid.length;j++) {
System.out.print(sm.grid[i][j] + " ");
}
System.out.println();
}
}
}