Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -96,6 +96,9 @@ def compute_eigenvalue_support_boundaries(z_a, y, beta_values, n_samples=100, se
|
|
96 |
Compute the support boundaries of the eigenvalue distribution by directly
|
97 |
finding the minimum and maximum eigenvalues of B_n = S_n T_n for different beta values.
|
98 |
"""
|
|
|
|
|
|
|
99 |
min_eigenvalues = np.zeros_like(beta_values)
|
100 |
max_eigenvalues = np.zeros_like(beta_values)
|
101 |
|
@@ -118,11 +121,16 @@ def compute_eigenvalue_support_boundaries(z_a, y, beta_values, n_samples=100, se
|
|
118 |
|
119 |
# Compute dimension p based on aspect ratio y
|
120 |
n = n_samples
|
121 |
-
p = int(
|
122 |
|
123 |
# Constructing T_n (Population / Shape Matrix)
|
124 |
-
|
125 |
-
|
|
|
|
|
|
|
|
|
|
|
126 |
|
127 |
# Generate the data matrix X with i.i.d. standard normal entries
|
128 |
X = np.random.randn(p, n)
|
@@ -155,12 +163,15 @@ def compute_high_y_curve(betas, z_a, y):
|
|
155 |
"""
|
156 |
Compute the "High y Expression" curve.
|
157 |
"""
|
|
|
|
|
|
|
158 |
a = z_a
|
159 |
betas = np.array(betas)
|
160 |
denominator = 1 - 2*a
|
161 |
if denominator == 0:
|
162 |
return np.full_like(betas, np.nan)
|
163 |
-
numerator = -4*a*(a-1)*
|
164 |
return numerator/denominator
|
165 |
|
166 |
def compute_alternate_low_expr(betas, z_a, y):
|
@@ -168,14 +179,20 @@ def compute_alternate_low_expr(betas, z_a, y):
|
|
168 |
Compute the alternate low expression:
|
169 |
(z_a*y*beta*(z_a-1) - 2*z_a*(1-y) - 2*z_a**2) / (2+2*z_a)
|
170 |
"""
|
|
|
|
|
|
|
171 |
betas = np.array(betas)
|
172 |
-
return (z_a *
|
173 |
|
174 |
@st.cache_data
|
175 |
def compute_max_k_expression(betas, z_a, y, k_samples=1000):
|
176 |
"""
|
177 |
Compute max_{k ∈ (0,∞)} (y*beta*(a-1)*k + (a*k+1)*((y-1)*k-1)) / ((a*k+1)*(k^2+k))
|
178 |
"""
|
|
|
|
|
|
|
179 |
a = z_a
|
180 |
# Sample k values on a logarithmic scale
|
181 |
k_values = np.logspace(-3, 3, k_samples)
|
@@ -184,7 +201,7 @@ def compute_max_k_expression(betas, z_a, y, k_samples=1000):
|
|
184 |
for i, beta in enumerate(betas):
|
185 |
values = np.zeros_like(k_values)
|
186 |
for j, k in enumerate(k_values):
|
187 |
-
numerator =
|
188 |
denominator = (a*k+1)*(k**2+k)
|
189 |
if abs(denominator) < 1e-10:
|
190 |
values[j] = np.nan
|
@@ -204,6 +221,9 @@ def compute_min_t_expression(betas, z_a, y, t_samples=1000):
|
|
204 |
"""
|
205 |
Compute min_{t ∈ (-1/a, 0)} (y*beta*(a-1)*t + (a*t+1)*((y-1)*t-1)) / ((a*t+1)*(t^2+t))
|
206 |
"""
|
|
|
|
|
|
|
207 |
a = z_a
|
208 |
if a <= 0:
|
209 |
return np.full_like(betas, np.nan)
|
@@ -215,7 +235,7 @@ def compute_min_t_expression(betas, z_a, y, t_samples=1000):
|
|
215 |
for i, beta in enumerate(betas):
|
216 |
values = np.zeros_like(t_values)
|
217 |
for j, t in enumerate(t_values):
|
218 |
-
numerator =
|
219 |
denominator = (a*t+1)*(t**2+t)
|
220 |
if abs(denominator) < 1e-10:
|
221 |
values[j] = np.nan
|
@@ -272,6 +292,9 @@ def compute_custom_expression(betas, z_a, y, s_num_expr, s_denom_expr, is_s_base
|
|
272 |
Compute custom curve. If is_s_based=True, compute using s substitution.
|
273 |
Otherwise, compute direct z(β) expression.
|
274 |
"""
|
|
|
|
|
|
|
275 |
beta_sym, z_a_sym, y_sym = sp.symbols("beta z_a y", positive=True)
|
276 |
local_dict = {"beta": beta_sym, "z_a": z_a_sym, "y": y_sym, "sp": sp}
|
277 |
|
@@ -300,7 +323,7 @@ def compute_custom_expression(betas, z_a, y, s_num_expr, s_denom_expr, is_s_base
|
|
300 |
|
301 |
final_func = sp.lambdify((beta_sym, z_a_sym, y_sym), final_expr, modules=["numpy"])
|
302 |
with np.errstate(divide='ignore', invalid='ignore'):
|
303 |
-
result = final_func(betas, z_a,
|
304 |
if np.isscalar(result):
|
305 |
result = np.full_like(betas, result)
|
306 |
return result
|
@@ -444,9 +467,12 @@ def compute_cubic_roots(z, beta, z_a, y):
|
|
444 |
"""
|
445 |
Compute the roots of the cubic equation for given parameters.
|
446 |
"""
|
|
|
|
|
|
|
447 |
a = z * z_a
|
448 |
-
b = z * z_a + z + z_a - z_a*
|
449 |
-
c = z + z_a + 1 -
|
450 |
d = 1
|
451 |
coeffs = [a, b, c, d]
|
452 |
roots = np.roots(coeffs)
|
@@ -489,29 +515,24 @@ def generate_root_plots(beta, y, z_a, z_min, z_max, n_points):
|
|
489 |
def generate_eigenvalue_distribution(beta, y, z_a, n=1000, seed=42):
|
490 |
"""
|
491 |
Generate the eigenvalue distribution of B_n = S_n T_n as n→∞
|
492 |
-
|
493 |
-
Parameters:
|
494 |
-
-----------
|
495 |
-
beta : float
|
496 |
-
Fraction of components equal to z_a
|
497 |
-
y : float
|
498 |
-
Aspect ratio p/n
|
499 |
-
z_a : float
|
500 |
-
Value for the delta mass at z_a
|
501 |
-
n : int
|
502 |
-
Number of samples
|
503 |
-
seed : int
|
504 |
-
Random seed for reproducibility
|
505 |
"""
|
|
|
|
|
|
|
506 |
# Set random seed
|
507 |
np.random.seed(seed)
|
508 |
|
509 |
# Compute dimension p based on aspect ratio y
|
510 |
-
p = int(
|
511 |
|
512 |
-
# Constructing T_n (Population / Shape Matrix)
|
513 |
-
|
514 |
-
|
|
|
|
|
|
|
|
|
|
|
515 |
|
516 |
# Generate the data matrix X with i.i.d. standard normal entries
|
517 |
X = np.random.randn(p, n)
|
@@ -559,34 +580,42 @@ tab1, tab2, tab3 = st.tabs(["z*(β) Curves", "Im{s} vs. z", "Differential Analys
|
|
559 |
|
560 |
# ----- Tab 1: z*(β) Curves -----
|
561 |
with tab1:
|
562 |
-
st.header("
|
563 |
-
|
|
|
|
|
|
|
564 |
with col1:
|
565 |
z_a_1 = st.number_input("z_a", value=1.0, key="z_a_1")
|
566 |
y_1 = st.number_input("y", value=1.0, key="y_1")
|
|
|
|
|
567 |
z_min_1 = st.number_input("z_min", value=-10.0, key="z_min_1")
|
568 |
z_max_1 = st.number_input("z_max", value=10.0, key="z_max_1")
|
569 |
-
|
|
|
570 |
method_type = st.radio(
|
571 |
-
"
|
572 |
["Eigenvalue Method", "Discriminant Method"],
|
573 |
index=0 # Default to eigenvalue method
|
574 |
)
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
-
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
|
|
|
|
590 |
st.markdown("""Enter expressions for s = numerator/denominator
|
591 |
(using variables `y`, `beta`, `z_a`, and `sqrt()`)""")
|
592 |
st.latex(r"\text{This s will be inserted into:}")
|
@@ -594,16 +623,19 @@ with tab1:
|
|
594 |
s_num = st.text_input("s numerator", value="", key="s_num")
|
595 |
s_denom = st.text_input("s denominator", value="", key="s_denom")
|
596 |
|
597 |
-
|
598 |
st.markdown("""Enter direct expression for z(β) = numerator/denominator
|
599 |
(using variables `y`, `beta`, `z_a`, and `sqrt()`)""")
|
600 |
z_num = st.text_input("z(β) numerator", value="", key="z_num")
|
601 |
z_denom = st.text_input("z(β) denominator", value="", key="z_denom")
|
602 |
|
|
|
|
|
603 |
show_derivatives = st.checkbox("Show derivatives", value=False)
|
604 |
|
|
|
605 |
if st.button("Compute Curves", key="tab1_button"):
|
606 |
-
with
|
607 |
use_eigenvalue_method = (method_type == "Eigenvalue Method")
|
608 |
if use_eigenvalue_method:
|
609 |
fig = generate_z_vs_beta_plot(z_a_1, y_1, z_min_1, z_max_1, beta_steps, None,
|
@@ -617,35 +649,37 @@ with tab1:
|
|
617 |
|
618 |
if fig is not None:
|
619 |
st.plotly_chart(fig, use_container_width=True)
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
|
646 |
-
|
647 |
-
|
648 |
-
|
|
|
|
|
649 |
|
650 |
# ----- Tab 2: Im{s} vs. z -----
|
651 |
with tab2:
|
@@ -657,7 +691,7 @@ with tab2:
|
|
657 |
z_a_2 = st.number_input("z_a", value=1.0, key="z_a_tab2")
|
658 |
z_min_2 = st.number_input("z_min", value=-10.0, key="z_min_tab2")
|
659 |
z_max_2 = st.number_input("z_max", value=10.0, key="z_max_tab2")
|
660 |
-
with st.expander("Resolution Settings"):
|
661 |
z_points = st.slider("z grid points", min_value=1000, max_value=10000, value=5000, step=500, key="z_points")
|
662 |
if st.button("Compute Complex Roots vs. z", key="tab2_button"):
|
663 |
with col2:
|
@@ -671,12 +705,13 @@ with tab2:
|
|
671 |
|
672 |
# Add eigenvalue distribution section
|
673 |
st.header("Eigenvalue Distribution for B_n = S_n T_n")
|
674 |
-
st.
|
675 |
-
|
676 |
-
|
677 |
-
|
678 |
-
|
679 |
-
|
|
|
680 |
|
681 |
col_eigen1, col_eigen2 = st.columns([1, 2])
|
682 |
with col_eigen1:
|
@@ -692,7 +727,9 @@ with tab2:
|
|
692 |
# ----- Tab 3: Differential Analysis -----
|
693 |
with tab3:
|
694 |
st.header("Differential Analysis vs. β")
|
695 |
-
st.
|
|
|
|
|
696 |
col1, col2 = st.columns([1, 2])
|
697 |
with col1:
|
698 |
z_a_diff = st.number_input("z_a", value=1.0, key="z_a_diff")
|
@@ -707,7 +744,7 @@ with tab3:
|
|
707 |
key="diff_method_type"
|
708 |
)
|
709 |
|
710 |
-
with st.expander("Resolution Settings"):
|
711 |
if diff_method_type == "Eigenvalue Method":
|
712 |
beta_steps_diff = st.slider("β steps", min_value=21, max_value=101, value=51, step=10,
|
713 |
key="beta_steps_diff_eigen")
|
@@ -795,9 +832,9 @@ with tab3:
|
|
795 |
)
|
796 |
st.plotly_chart(fig_diff, use_container_width=True)
|
797 |
|
798 |
-
st.
|
799 |
-
|
800 |
-
|
801 |
-
|
802 |
-
|
803 |
-
|
|
|
96 |
Compute the support boundaries of the eigenvalue distribution by directly
|
97 |
finding the minimum and maximum eigenvalues of B_n = S_n T_n for different beta values.
|
98 |
"""
|
99 |
+
# Apply the condition for y
|
100 |
+
y_effective = y if y > 1 else 1/y
|
101 |
+
|
102 |
min_eigenvalues = np.zeros_like(beta_values)
|
103 |
max_eigenvalues = np.zeros_like(beta_values)
|
104 |
|
|
|
121 |
|
122 |
# Compute dimension p based on aspect ratio y
|
123 |
n = n_samples
|
124 |
+
p = int(y_effective * n)
|
125 |
|
126 |
# Constructing T_n (Population / Shape Matrix)
|
127 |
+
k = int(np.floor(beta * p))
|
128 |
+
diag_entries = np.concatenate([
|
129 |
+
np.full(k, z_a),
|
130 |
+
np.full(p - k, 1.0)
|
131 |
+
])
|
132 |
+
np.random.shuffle(diag_entries)
|
133 |
+
T_n = np.diag(diag_entries)
|
134 |
|
135 |
# Generate the data matrix X with i.i.d. standard normal entries
|
136 |
X = np.random.randn(p, n)
|
|
|
163 |
"""
|
164 |
Compute the "High y Expression" curve.
|
165 |
"""
|
166 |
+
# Apply the condition for y
|
167 |
+
y_effective = y if y > 1 else 1/y
|
168 |
+
|
169 |
a = z_a
|
170 |
betas = np.array(betas)
|
171 |
denominator = 1 - 2*a
|
172 |
if denominator == 0:
|
173 |
return np.full_like(betas, np.nan)
|
174 |
+
numerator = -4*a*(a-1)*y_effective*betas - 2*a*y_effective - 2*a*(2*a-1)
|
175 |
return numerator/denominator
|
176 |
|
177 |
def compute_alternate_low_expr(betas, z_a, y):
|
|
|
179 |
Compute the alternate low expression:
|
180 |
(z_a*y*beta*(z_a-1) - 2*z_a*(1-y) - 2*z_a**2) / (2+2*z_a)
|
181 |
"""
|
182 |
+
# Apply the condition for y
|
183 |
+
y_effective = y if y > 1 else 1/y
|
184 |
+
|
185 |
betas = np.array(betas)
|
186 |
+
return (z_a * y_effective * betas * (z_a - 1) - 2*z_a*(1 - y_effective) - 2*z_a**2) / (2 + 2*z_a)
|
187 |
|
188 |
@st.cache_data
|
189 |
def compute_max_k_expression(betas, z_a, y, k_samples=1000):
|
190 |
"""
|
191 |
Compute max_{k ∈ (0,∞)} (y*beta*(a-1)*k + (a*k+1)*((y-1)*k-1)) / ((a*k+1)*(k^2+k))
|
192 |
"""
|
193 |
+
# Apply the condition for y
|
194 |
+
y_effective = y if y > 1 else 1/y
|
195 |
+
|
196 |
a = z_a
|
197 |
# Sample k values on a logarithmic scale
|
198 |
k_values = np.logspace(-3, 3, k_samples)
|
|
|
201 |
for i, beta in enumerate(betas):
|
202 |
values = np.zeros_like(k_values)
|
203 |
for j, k in enumerate(k_values):
|
204 |
+
numerator = y_effective*beta*(a-1)*k + (a*k+1)*((y_effective-1)*k-1)
|
205 |
denominator = (a*k+1)*(k**2+k)
|
206 |
if abs(denominator) < 1e-10:
|
207 |
values[j] = np.nan
|
|
|
221 |
"""
|
222 |
Compute min_{t ∈ (-1/a, 0)} (y*beta*(a-1)*t + (a*t+1)*((y-1)*t-1)) / ((a*t+1)*(t^2+t))
|
223 |
"""
|
224 |
+
# Apply the condition for y
|
225 |
+
y_effective = y if y > 1 else 1/y
|
226 |
+
|
227 |
a = z_a
|
228 |
if a <= 0:
|
229 |
return np.full_like(betas, np.nan)
|
|
|
235 |
for i, beta in enumerate(betas):
|
236 |
values = np.zeros_like(t_values)
|
237 |
for j, t in enumerate(t_values):
|
238 |
+
numerator = y_effective*beta*(a-1)*t + (a*t+1)*((y_effective-1)*t-1)
|
239 |
denominator = (a*t+1)*(t**2+t)
|
240 |
if abs(denominator) < 1e-10:
|
241 |
values[j] = np.nan
|
|
|
292 |
Compute custom curve. If is_s_based=True, compute using s substitution.
|
293 |
Otherwise, compute direct z(β) expression.
|
294 |
"""
|
295 |
+
# Apply the condition for y
|
296 |
+
y_effective = y if y > 1 else 1/y
|
297 |
+
|
298 |
beta_sym, z_a_sym, y_sym = sp.symbols("beta z_a y", positive=True)
|
299 |
local_dict = {"beta": beta_sym, "z_a": z_a_sym, "y": y_sym, "sp": sp}
|
300 |
|
|
|
323 |
|
324 |
final_func = sp.lambdify((beta_sym, z_a_sym, y_sym), final_expr, modules=["numpy"])
|
325 |
with np.errstate(divide='ignore', invalid='ignore'):
|
326 |
+
result = final_func(betas, z_a, y_effective)
|
327 |
if np.isscalar(result):
|
328 |
result = np.full_like(betas, result)
|
329 |
return result
|
|
|
467 |
"""
|
468 |
Compute the roots of the cubic equation for given parameters.
|
469 |
"""
|
470 |
+
# Apply the condition for y
|
471 |
+
y_effective = y if y > 1 else 1/y
|
472 |
+
|
473 |
a = z * z_a
|
474 |
+
b = z * z_a + z + z_a - z_a*y_effective
|
475 |
+
c = z + z_a + 1 - y_effective*(beta*z_a + 1 - beta)
|
476 |
d = 1
|
477 |
coeffs = [a, b, c, d]
|
478 |
roots = np.roots(coeffs)
|
|
|
515 |
def generate_eigenvalue_distribution(beta, y, z_a, n=1000, seed=42):
|
516 |
"""
|
517 |
Generate the eigenvalue distribution of B_n = S_n T_n as n→∞
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
518 |
"""
|
519 |
+
# Apply the condition for y
|
520 |
+
y_effective = y if y > 1 else 1/y
|
521 |
+
|
522 |
# Set random seed
|
523 |
np.random.seed(seed)
|
524 |
|
525 |
# Compute dimension p based on aspect ratio y
|
526 |
+
p = int(y_effective * n)
|
527 |
|
528 |
+
# Constructing T_n (Population / Shape Matrix) - using the approach from the second script
|
529 |
+
k = int(np.floor(beta * p))
|
530 |
+
diag_entries = np.concatenate([
|
531 |
+
np.full(k, z_a),
|
532 |
+
np.full(p - k, 1.0)
|
533 |
+
])
|
534 |
+
np.random.shuffle(diag_entries)
|
535 |
+
T_n = np.diag(diag_entries)
|
536 |
|
537 |
# Generate the data matrix X with i.i.d. standard normal entries
|
538 |
X = np.random.randn(p, n)
|
|
|
580 |
|
581 |
# ----- Tab 1: z*(β) Curves -----
|
582 |
with tab1:
|
583 |
+
st.header("Eigenvalue Support Boundaries")
|
584 |
+
|
585 |
+
# Cleaner layout with better column organization
|
586 |
+
col1, col2, col3 = st.columns([1, 1, 2])
|
587 |
+
|
588 |
with col1:
|
589 |
z_a_1 = st.number_input("z_a", value=1.0, key="z_a_1")
|
590 |
y_1 = st.number_input("y", value=1.0, key="y_1")
|
591 |
+
|
592 |
+
with col2:
|
593 |
z_min_1 = st.number_input("z_min", value=-10.0, key="z_min_1")
|
594 |
z_max_1 = st.number_input("z_max", value=10.0, key="z_max_1")
|
595 |
+
|
596 |
+
with col1:
|
597 |
method_type = st.radio(
|
598 |
+
"Calculation Method",
|
599 |
["Eigenvalue Method", "Discriminant Method"],
|
600 |
index=0 # Default to eigenvalue method
|
601 |
)
|
602 |
+
|
603 |
+
# Advanced settings in collapsed expanders
|
604 |
+
with st.expander("Method Settings", expanded=False):
|
605 |
+
if method_type == "Eigenvalue Method":
|
606 |
+
beta_steps = st.slider("β steps", min_value=21, max_value=101, value=51, step=10,
|
607 |
+
key="beta_steps_eigen")
|
608 |
+
n_samples = st.slider("Matrix size (n)", min_value=100, max_value=2000, value=1000,
|
609 |
+
step=100)
|
610 |
+
seeds = st.slider("Number of seeds", min_value=1, max_value=10, value=5, step=1)
|
611 |
+
else:
|
612 |
+
beta_steps = st.slider("β steps", min_value=51, max_value=501, value=201, step=50,
|
613 |
+
key="beta_steps")
|
614 |
+
z_steps = st.slider("z grid steps", min_value=1000, max_value=100000, value=50000,
|
615 |
+
step=1000, key="z_steps")
|
616 |
+
|
617 |
+
# Custom expressions collapsed by default
|
618 |
+
with st.expander("Custom Expression 1 (s-based)", expanded=False):
|
619 |
st.markdown("""Enter expressions for s = numerator/denominator
|
620 |
(using variables `y`, `beta`, `z_a`, and `sqrt()`)""")
|
621 |
st.latex(r"\text{This s will be inserted into:}")
|
|
|
623 |
s_num = st.text_input("s numerator", value="", key="s_num")
|
624 |
s_denom = st.text_input("s denominator", value="", key="s_denom")
|
625 |
|
626 |
+
with st.expander("Custom Expression 2 (direct z(β))", expanded=False):
|
627 |
st.markdown("""Enter direct expression for z(β) = numerator/denominator
|
628 |
(using variables `y`, `beta`, `z_a`, and `sqrt()`)""")
|
629 |
z_num = st.text_input("z(β) numerator", value="", key="z_num")
|
630 |
z_denom = st.text_input("z(β) denominator", value="", key="z_denom")
|
631 |
|
632 |
+
# Move show_derivatives to main UI level for better visibility
|
633 |
+
with col2:
|
634 |
show_derivatives = st.checkbox("Show derivatives", value=False)
|
635 |
|
636 |
+
# Compute button
|
637 |
if st.button("Compute Curves", key="tab1_button"):
|
638 |
+
with col3:
|
639 |
use_eigenvalue_method = (method_type == "Eigenvalue Method")
|
640 |
if use_eigenvalue_method:
|
641 |
fig = generate_z_vs_beta_plot(z_a_1, y_1, z_min_1, z_max_1, beta_steps, None,
|
|
|
649 |
|
650 |
if fig is not None:
|
651 |
st.plotly_chart(fig, use_container_width=True)
|
652 |
+
|
653 |
+
# Curve explanations in collapsed expander
|
654 |
+
with st.expander("Curve Explanations", expanded=False):
|
655 |
+
if use_eigenvalue_method:
|
656 |
+
st.markdown("""
|
657 |
+
- **Upper/Lower Bounds** (Blue): Maximum/minimum eigenvalues of B_n = S_n T_n
|
658 |
+
- **Shaded Region**: Eigenvalue support region
|
659 |
+
- **High y Expression** (Green): Asymptotic approximation for high y values
|
660 |
+
- **Low Expression** (Orange): Alternative asymptotic expression
|
661 |
+
- **Max k Expression** (Red): $\\max_{k \\in (0,\\infty)} \\frac{y\\beta (a-1)k + \\bigl(ak+1\\bigr)\\bigl((y-1)k-1\\bigr)}{(ak+1)(k^2+k)}$
|
662 |
+
- **Min t Expression** (Orange): $\\min_{t \\in \\left(-\\frac{1}{a},\\, 0\\right)} \\frac{y\\beta (a-1)t + \\bigl(at+1\\bigr)\\bigl((y-1)t-1\\bigr)}{(at+1)(t^2+t)}$
|
663 |
+
- **Custom Expression 1** (Purple): Result from user-defined s substituted into the main formula
|
664 |
+
- **Custom Expression 2** (Magenta): Direct z(β) expression
|
665 |
+
""")
|
666 |
+
else:
|
667 |
+
st.markdown("""
|
668 |
+
- **Upper z*(β)** (Blue): Maximum z value where discriminant is zero
|
669 |
+
- **Lower z*(β)** (Light Blue): Minimum z value where discriminant is zero
|
670 |
+
- **High y Expression** (Green): Asymptotic approximation for high y values
|
671 |
+
- **Low Expression** (Orange): Alternative asymptotic expression
|
672 |
+
- **Max k Expression** (Red): $\\max_{k \\in (0,\\infty)} \\frac{y\\beta (a-1)k + \\bigl(ak+1\\bigr)\\bigl((y-1)k-1\\bigr)}{(ak+1)(k^2+k)}$
|
673 |
+
- **Min t Expression** (Orange): $\\min_{t \\in \\left(-\\frac{1}{a},\\, 0\\right)} \\frac{y\\beta (a-1)t + \\bigl(at+1\\bigr)\\bigl((y-1)t-1\\bigr)}{(at+1)(t^2+t)}$
|
674 |
+
- **Custom Expression 1** (Purple): Result from user-defined s substituted into the main formula
|
675 |
+
- **Custom Expression 2** (Magenta): Direct z(β) expression
|
676 |
+
""")
|
677 |
+
if show_derivatives:
|
678 |
+
st.markdown("""
|
679 |
+
Derivatives are shown as:
|
680 |
+
- Dashed lines: First derivatives (d/dβ)
|
681 |
+
- Dotted lines: Second derivatives (d²/dβ²)
|
682 |
+
""")
|
683 |
|
684 |
# ----- Tab 2: Im{s} vs. z -----
|
685 |
with tab2:
|
|
|
691 |
z_a_2 = st.number_input("z_a", value=1.0, key="z_a_tab2")
|
692 |
z_min_2 = st.number_input("z_min", value=-10.0, key="z_min_tab2")
|
693 |
z_max_2 = st.number_input("z_max", value=10.0, key="z_max_tab2")
|
694 |
+
with st.expander("Resolution Settings", expanded=False):
|
695 |
z_points = st.slider("z grid points", min_value=1000, max_value=10000, value=5000, step=500, key="z_points")
|
696 |
if st.button("Compute Complex Roots vs. z", key="tab2_button"):
|
697 |
with col2:
|
|
|
705 |
|
706 |
# Add eigenvalue distribution section
|
707 |
st.header("Eigenvalue Distribution for B_n = S_n T_n")
|
708 |
+
with st.expander("Simulation Information", expanded=False):
|
709 |
+
st.markdown("""
|
710 |
+
This simulation generates the eigenvalue distribution of B_n as n→∞, where:
|
711 |
+
- B_n = (1/n)XX* with X being a p×n matrix
|
712 |
+
- p/n → y as n→∞
|
713 |
+
- All elements of X are i.i.d with distribution β·δ(z_a) + (1-β)·δ(1)
|
714 |
+
""")
|
715 |
|
716 |
col_eigen1, col_eigen2 = st.columns([1, 2])
|
717 |
with col_eigen1:
|
|
|
727 |
# ----- Tab 3: Differential Analysis -----
|
728 |
with tab3:
|
729 |
st.header("Differential Analysis vs. β")
|
730 |
+
with st.expander("Description", expanded=False):
|
731 |
+
st.markdown("This page shows the difference between the Upper (blue) and Lower (lightblue) z*(β) curves, along with their first and second derivatives with respect to β.")
|
732 |
+
|
733 |
col1, col2 = st.columns([1, 2])
|
734 |
with col1:
|
735 |
z_a_diff = st.number_input("z_a", value=1.0, key="z_a_diff")
|
|
|
744 |
key="diff_method_type"
|
745 |
)
|
746 |
|
747 |
+
with st.expander("Resolution Settings", expanded=False):
|
748 |
if diff_method_type == "Eigenvalue Method":
|
749 |
beta_steps_diff = st.slider("β steps", min_value=21, max_value=101, value=51, step=10,
|
750 |
key="beta_steps_diff_eigen")
|
|
|
832 |
)
|
833 |
st.plotly_chart(fig_diff, use_container_width=True)
|
834 |
|
835 |
+
with st.expander("Curve Types", expanded=False):
|
836 |
+
st.markdown("""
|
837 |
+
- Solid lines: Original curves
|
838 |
+
- Dashed lines: First derivatives (d/dβ)
|
839 |
+
- Dotted lines: Second derivatives (d²/dβ²)
|
840 |
+
""")
|