Spaces:
Sleeping
Sleeping
Upload 2 files
Browse files- app.py +119 -0
- requirements.txt +9 -0
app.py
ADDED
@@ -0,0 +1,119 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import pandas as pd
|
3 |
+
from gradio import Interface, components
|
4 |
+
import matplotlib.cm as cm
|
5 |
+
import numpy as np
|
6 |
+
from scipy.integrate import odeint
|
7 |
+
import matplotlib.pyplot as plt
|
8 |
+
from PIL import Image, ImageSequence
|
9 |
+
from math import factorial
|
10 |
+
from tqdm import tqdm
|
11 |
+
from sklearn.cluster import DBSCAN
|
12 |
+
|
13 |
+
def create_trajectory_gif(k1=3, k2=20, p=0.1, u1=1, u2=2, u3=2.3, timesteps=6, grid_interval=0.1):
|
14 |
+
k1 = int(round(k1))
|
15 |
+
k2 = int(round(k2))
|
16 |
+
timesteps = int(round(timesteps))
|
17 |
+
|
18 |
+
# Computes the probability of a strategy being best response to a given sample of k
|
19 |
+
def xtp1(x1, x2, k):
|
20 |
+
probs = np.zeros(3)
|
21 |
+
for i in range(k):
|
22 |
+
for j in range(k-i):
|
23 |
+
if 1.* i/k *u1 > 1.*j/k *u2 and 1.* i/k*u1 > 1.*(k-i-j)/k *u3:
|
24 |
+
probs[0] += factorial(k)/(factorial(j)* factorial(i) * factorial(k-i-j) ) *(x1)**i * (x2)**j * (1-x1-x2)**(k-i-j)
|
25 |
+
elif 1.* j/k *u2 > 1.*i/k *u1 and 1.* j/k*u2 > 1.*(k-i-j)/k *u3:
|
26 |
+
probs[1] += factorial(k)/(factorial(j)* factorial(i) * factorial(k-i-j) ) *(x1)**i * (x2)**j * (1-x1-x2)**(k-i-j)
|
27 |
+
else:
|
28 |
+
probs[2] += factorial(k)/(factorial(j)* factorial(i) * factorial(k-i-j) ) *(x1)**i * (x2)**j * (1-x1-x2)**(k-i-j)
|
29 |
+
return probs
|
30 |
+
|
31 |
+
def W(x1, x2):
|
32 |
+
return p*xtp1(x1, x2, k1) + (1-p)* xtp1(x1, x2, k2)
|
33 |
+
|
34 |
+
# Define the system of differential equations
|
35 |
+
def system(Y, t=0):
|
36 |
+
x1, x2 = Y
|
37 |
+
w = W(x1, x2)
|
38 |
+
dx1dt = w[0] - x1
|
39 |
+
dx2dt = w[1] - x2
|
40 |
+
return [dx1dt, dx2dt]
|
41 |
+
|
42 |
+
# time space
|
43 |
+
t = np.linspace(0, timesteps, int(timesteps*5))
|
44 |
+
grid_points = [(x, y) for x in np.arange(0, 1.1, grid_interval) for y in np.arange(0, 1.1, grid_interval) if x + y <= 1]
|
45 |
+
|
46 |
+
# Generating a color map
|
47 |
+
colors = cm.rainbow(np.linspace(0, 1, len(grid_points)))
|
48 |
+
|
49 |
+
final_points = []
|
50 |
+
frames = []
|
51 |
+
for t_val in tqdm(t):
|
52 |
+
plt.figure(figsize=(12, 8))
|
53 |
+
for ic, color in zip(grid_points, colors):
|
54 |
+
t_segment = np.linspace(0, t_val, 100) # 100 points for each trajectory segment
|
55 |
+
sol = odeint(system, ic, t_segment)
|
56 |
+
plt.plot(sol[:, 0], sol[:, 1], color=color, alpha=0.5)
|
57 |
+
if t_val == t[-1]: # If it's the last timestep, collect the final point
|
58 |
+
final_points.append(sol[-1])
|
59 |
+
|
60 |
+
plt.title(f"Attractor plot at time = {t_val:.2f}")
|
61 |
+
plt.xlabel("x1")
|
62 |
+
plt.ylabel("x2")
|
63 |
+
plt.grid(True)
|
64 |
+
plt.tight_layout()
|
65 |
+
|
66 |
+
# Save the current frame to a file and add to the list of frames
|
67 |
+
filename = f"./temp/temp_frame_{int(t_val*10):04d}.png"
|
68 |
+
plt.savefig(filename)
|
69 |
+
frames.append(Image.open(filename))
|
70 |
+
plt.close()
|
71 |
+
|
72 |
+
# Save frames as a GIF
|
73 |
+
gif_filename = './trajectory_animation2.gif'
|
74 |
+
frames[0].save(gif_filename, save_all=True, append_images=frames[1:], loop=0, duration=100)
|
75 |
+
|
76 |
+
# Cleanup temporary frame files
|
77 |
+
for frame in frames:
|
78 |
+
frame.close()
|
79 |
+
|
80 |
+
# Cluster the final points using DBSCAN
|
81 |
+
clustering = DBSCAN(eps=0.1, min_samples=1).fit(final_points)
|
82 |
+
cluster_labels = clustering.labels_
|
83 |
+
|
84 |
+
# Determine the stable points by averaging the points in each cluster
|
85 |
+
stable_points = []
|
86 |
+
for label in set(cluster_labels):
|
87 |
+
points_in_cluster = np.array(final_points)[cluster_labels == label]
|
88 |
+
stable_point = np.around(np.mean(points_in_cluster, axis=0), decimals = 2)
|
89 |
+
stable_points.append(stable_point)
|
90 |
+
|
91 |
+
list_of_lists = [list(arr) + [1 - sum(arr)] for arr in stable_points]
|
92 |
+
df = pd.DataFrame(list_of_lists, columns=['x1', 'x2', 'x3'])
|
93 |
+
|
94 |
+
return gif_filename, df
|
95 |
+
|
96 |
+
|
97 |
+
|
98 |
+
iface = gr.Interface(
|
99 |
+
fn= create_trajectory_gif,
|
100 |
+
inputs=[
|
101 |
+
gr.Number( label="Sample Size 1"),
|
102 |
+
gr.Number( label="Sample Size 2"),
|
103 |
+
gr.Slider(minimum=0, maximum=1, step=0.01, label="Proportion of Cohort 1 (with sample size 1)"),
|
104 |
+
gr.Number(label="Payoff u1"),
|
105 |
+
gr.Number(label="Payoff u2"),
|
106 |
+
gr.Number(label="Payoff u3"),
|
107 |
+
gr.Number(label="Timesteps"),
|
108 |
+
gr.Number(label="Grid resolution"),
|
109 |
+
],
|
110 |
+
outputs=[
|
111 |
+
gr.Image(label="Simulation GIF"),
|
112 |
+
gr.Dataframe(type="pandas", label="Stable equilibria")
|
113 |
+
],
|
114 |
+
examples=[
|
115 |
+
[3, 20, 0.1, 1, 2, 2.3, 6, 0.1]
|
116 |
+
]
|
117 |
+
)
|
118 |
+
|
119 |
+
iface.launch()
|
requirements.txt
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Pillow
|
2 |
+
scipy
|
3 |
+
tqdm
|
4 |
+
gradio
|
5 |
+
matplotlib
|
6 |
+
numpy
|
7 |
+
pandas
|
8 |
+
gradio
|
9 |
+
scikit-learn
|