File size: 3,955 Bytes
74e96d7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c104270
74e96d7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c104270
74e96d7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import gradio as gr
import numpy as np
import matplotlib.pyplot as plt
import time
from scipy.ndimage import label


def create_initial_plot(grid_size):
    grid = np.zeros((grid_size, grid_size))
    fig = plt.figure(figsize=(15, 6))
    grid_ax = fig.add_subplot(121)
    graph_ax = fig.add_subplot(122)

    grid_ax.imshow(grid, cmap='Greys', alpha=0.3)
    grid_ax.set_title(
        f'Site Occupation Probability p = 0.00\n'
        f'Largest Cluster Ratio = 0.000'
    )

    graph_ax.plot([0], [0], '-b', label='Largest Cluster Size')
    graph_ax.set_xlabel('Occupation Probability p')
    graph_ax.set_ylabel('Largest Cluster Size Ratio')
    graph_ax.set_title('Phase Transition in 2D Percolation')
    graph_ax.grid(True)
    graph_ax.legend()
    graph_ax.set_xlim(0, 1)
    graph_ax.set_ylim(0, 1)

    # plt.tight_layout()
    return fig

def get_largest_cluster(grid):
    labeled_array, num_features = label(grid)
    if num_features == 0:
        return np.zeros_like(grid), 0

    sizes = [np.sum(labeled_array == i) for i in range(1, num_features + 1)]
    if not sizes:
        return np.zeros_like(grid), 0

    max_cluster_index = np.argmax(sizes) + 1
    max_cluster_mask = labeled_array == max_cluster_index
    max_cluster_size = sizes[max_cluster_index - 1]

    return max_cluster_mask, max_cluster_size

def run_percolation_simulation(grid_size):
    p_step = 0.02
    fine_step = 0.01

    p1 = np.arange(0, 0.56, p_step)
    p2 = np.arange(0.56, 0.60 + fine_step, fine_step)
    p3 = np.arange(0.60 + p_step, 1.0 + p_step, p_step)
    steps = np.concatenate((p1, p2, p3))

    p_values = []
    largest_clusters = []

    fig = plt.figure(figsize=(15, 6))
    grid_ax = fig.add_subplot(121)
    graph_ax = fig.add_subplot(122)

    np.random.seed(3407)
    for p in steps:
        grid = np.random.random((grid_size, grid_size)) < p
        largest_cluster_mask, largest_cluster_size = get_largest_cluster(grid)
        largest_cluster_ratio = largest_cluster_size / (grid_size * grid_size)

        p_values.append(p)
        largest_clusters.append(largest_cluster_ratio)

        grid_ax.clear()
        graph_ax.clear()

        grid_ax.imshow(grid, cmap='Greys', alpha=0.3)
        grid_ax.imshow(largest_cluster_mask, cmap='Blues', alpha=0.7)

        grid_ax.set_title(
            f'Site Occupation Probability p = {p:.2f}\n'
            f'Largest Cluster Ratio = {largest_cluster_ratio:.3f}'
        )

        graph_ax.plot(p_values, largest_clusters, '-b', label='Largest Cluster Size')
        graph_ax.set_xlabel('Occupation Probability p')
        graph_ax.set_ylabel('Largest Cluster Size Ratio')
        graph_ax.set_title('Phase Transition in 2D Percolation')
        graph_ax.grid(True)
        graph_ax.legend()
        graph_ax.set_xlim(0, 1)
        graph_ax.set_ylim(0, 1)

        # plt.tight_layout()

        yield fig

        time.sleep(0.25)

with gr.Blocks() as demo:
    gr.Markdown("# 2D Site Percolation Simulation")
    gr.Markdown("""
    This simulation shows the formation of clusters in a 2D percolation system as the occupation probability increases.
    Watch how the system undergoes a phase transition around p ≈ 0.593 (critical point).

    - Gray dots: Occupied sites
    - Blue region: Largest connected cluster
    """)

    with gr.Row():
        plot = gr.Plot(value=create_initial_plot(50))
    with gr.Row():
        grid_size = gr.Slider(
            minimum=20, maximum=200, step=10, value=150,
            label="Grid Size", info="Size of the simulation grid"
        )
    with gr.Row():
        start_btn = gr.Button("Start Simulation")

    start_btn.click(
        fn=run_percolation_simulation,
        inputs=[grid_size],
        outputs=plot,
        show_progress=False
    )
    grid_size.change(
        fn=create_initial_plot,
        inputs=[grid_size],
        outputs=plot
    )

if __name__ == "__main__":
    demo.queue().launch(
        debug=True
    )