euler314 commited on
Commit
e14afd8
·
verified ·
1 Parent(s): 73bcec5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +107 -20
app.py CHANGED
@@ -70,6 +70,72 @@ def find_z_at_discriminant_zero(z_a, y, beta, z_min, z_max, steps):
70
  roots_found.append(0.5 * (zl + zr))
71
  return np.array(roots_found)
72
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  @st.cache_data
74
  def sweep_beta_and_find_z_bounds(z_a, y, z_min, z_max, beta_steps, z_steps):
75
  """
@@ -248,14 +314,20 @@ def compute_custom_expression(betas, z_a, y, s_num_expr, s_denom_expr, is_s_base
248
  def generate_z_vs_beta_plot(z_a, y, z_min, z_max, beta_steps, z_steps,
249
  s_num_expr=None, s_denom_expr=None,
250
  z_num_expr=None, z_denom_expr=None,
251
- show_derivatives=False):
252
  if z_a <= 0 or y <= 0 or z_min >= z_max:
253
  st.error("Invalid input parameters.")
254
  return None
255
 
256
- betas = np.linspace(0, 1, beta_steps)
257
- betas, z_mins, z_maxs = sweep_beta_and_find_z_bounds(z_a, y, z_min, z_max, beta_steps, z_steps)
258
- # Removed low_y_curve computation
 
 
 
 
 
 
259
  high_y_curve = compute_high_y_curve(betas, z_a, y)
260
  alt_low_expr = compute_alternate_low_expr(betas, z_a, y)
261
 
@@ -282,10 +354,11 @@ def generate_z_vs_beta_plot(z_a, y, z_min, z_max, beta_steps, z_steps,
282
  fig = go.Figure()
283
 
284
  # Original curves
 
285
  fig.add_trace(go.Scatter(x=betas, y=z_maxs, mode="markers+lines",
286
- name="Upper z*(β)", line=dict(color='blue')))
287
  fig.add_trace(go.Scatter(x=betas, y=z_mins, mode="markers+lines",
288
- name="Lower z*(β)", line=dict(color='blue')))
289
  # Removed the Low y Expression trace
290
  fig.add_trace(go.Scatter(x=betas, y=high_y_curve, mode="markers+lines",
291
  name="High y Expression", line=dict(color='green')))
@@ -296,7 +369,7 @@ def generate_z_vs_beta_plot(z_a, y, z_min, z_max, beta_steps, z_steps,
296
  fig.add_trace(go.Scatter(x=betas, y=max_k_curve, mode="lines",
297
  name="Max k Expression", line=dict(color='red', width=2)))
298
  fig.add_trace(go.Scatter(x=betas, y=min_t_curve, mode="lines",
299
- name="Min t Expression", line=dict(color='red', width=2)))
300
 
301
  if custom_curve1 is not None:
302
  fig.add_trace(go.Scatter(x=betas, y=custom_curve1, mode="markers+lines",
@@ -336,8 +409,9 @@ def generate_z_vs_beta_plot(z_a, y, z_min, z_max, beta_steps, z_steps,
336
  fig.add_trace(go.Scatter(x=betas, y=min_t_derivatives[1], mode="lines",
337
  name="Min t d²/dβ²", line=dict(color='orange', dash='dot')))
338
 
 
339
  fig.update_layout(
340
- title="Curves vs β: z*(β) Boundaries and Asymptotic Expressions",
341
  xaxis_title="β",
342
  yaxis_title="Value",
343
  hovermode="x unified",
@@ -481,6 +555,9 @@ with tab1:
481
  beta_steps = st.slider("β steps", min_value=51, max_value=501, value=201, step=50, key="beta_steps")
482
  z_steps = st.slider("z grid steps", min_value=1000, max_value=100000, value=50000, step=1000, key="z_steps")
483
 
 
 
 
484
  st.subheader("Custom Expression 1 (s-based)")
485
  st.markdown("""Enter expressions for s = numerator/denominator
486
  (using variables `y`, `beta`, `z_a`, and `sqrt()`)""")
@@ -500,17 +577,18 @@ with tab1:
500
  if st.button("Compute z vs. β Curves", key="tab1_button"):
501
  with col2:
502
  fig = generate_z_vs_beta_plot(z_a_1, y_1, z_min_1, z_max_1, beta_steps, z_steps,
503
- s_num, s_denom, z_num, z_denom, show_derivatives)
504
  if fig is not None:
505
  st.plotly_chart(fig, use_container_width=True)
506
- st.markdown("### Curve Explanations")
507
- st.markdown("""
508
- - **Upper z*(β)** (Blue): Maximum z value where discriminant is zero
509
- - **Lower z*(β)** (Light Blue): Minimum z value where discriminant is zero
 
510
  - **High y Expression** (Green): Asymptotic approximation for high y values
511
- - **Low Expression** (Green): Alternative asymptotic expression
512
  - **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)}$
513
- - **Min t Expression** (Red): $\\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)}$
514
  - **Custom Expression 1** (Purple): Result from user-defined s substituted into the main formula
515
  - **Custom Expression 2** (Magenta): Direct z(β) expression
516
  """)
@@ -577,6 +655,9 @@ with tab3:
577
  beta_steps_diff = st.slider("β steps", min_value=51, max_value=501, value=201, step=50, key="beta_steps_diff")
578
  z_steps_diff = st.slider("z grid steps", min_value=1000, max_value=100000, value=50000, step=1000, key="z_steps_diff")
579
 
 
 
 
580
  # Add options for curve selection
581
  st.subheader("Curves to Analyze")
582
  analyze_upper_lower = st.checkbox("Upper-Lower Difference", value=True)
@@ -585,7 +666,11 @@ with tab3:
585
 
586
  if st.button("Compute Differentials", key="tab3_button"):
587
  with col2:
588
- betas_diff, lower_vals, upper_vals = sweep_beta_and_find_z_bounds(z_a_diff, y_diff, z_min_diff, z_max_diff, beta_steps_diff, z_steps_diff)
 
 
 
 
589
 
590
  # Create figure
591
  fig_diff = go.Figure()
@@ -595,12 +680,13 @@ with tab3:
595
  d1 = np.gradient(diff_curve, betas_diff)
596
  d2 = np.gradient(d1, betas_diff)
597
 
 
598
  fig_diff.add_trace(go.Scatter(x=betas_diff, y=diff_curve, mode="lines",
599
- name="Upper-Lower Difference", line=dict(color="magenta", width=2)))
600
  fig_diff.add_trace(go.Scatter(x=betas_diff, y=d1, mode="lines",
601
- name="Upper-Lower d/dβ", line=dict(color="magenta", dash='dash')))
602
  fig_diff.add_trace(go.Scatter(x=betas_diff, y=d2, mode="lines",
603
- name="Upper-Lower d²/dβ²", line=dict(color="magenta", dash='dot')))
604
 
605
  if analyze_high_y:
606
  high_y_curve = compute_high_y_curve(betas_diff, z_a_diff, y_diff)
@@ -626,8 +712,9 @@ with tab3:
626
  fig_diff.add_trace(go.Scatter(x=betas_diff, y=d2, mode="lines",
627
  name="Alt Low d²/dβ²", line=dict(color="orange", dash='dot')))
628
 
 
629
  fig_diff.update_layout(
630
- title="Differential Analysis vs. β",
631
  xaxis_title="β",
632
  yaxis_title="Value",
633
  hovermode="x unified",
 
70
  roots_found.append(0.5 * (zl + zr))
71
  return np.array(roots_found)
72
 
73
+ @st.cache_data
74
+ def compute_eigenvalue_support_boundaries(z_a, y, beta_steps, n_samples=1000, seeds=5):
75
+ """
76
+ Compute the support boundaries of the eigenvalue distribution by directly
77
+ finding the minimum and maximum eigenvalues of B_n = S_n T_n for different beta values.
78
+
79
+ Parameters:
80
+ -----------
81
+ z_a : float
82
+ Value for the delta mass at z_a
83
+ y : float
84
+ Aspect ratio p/n
85
+ beta_steps : int
86
+ Number of beta values to compute
87
+ n_samples : int
88
+ Sample size for each matrix
89
+ seeds : int
90
+ Number of different random seeds to average over
91
+
92
+ Returns:
93
+ --------
94
+ betas, min_eigenvalues, max_eigenvalues - arrays representing the support boundaries
95
+ """
96
+ betas = np.linspace(0, 1, beta_steps)
97
+ min_eigenvalues = np.zeros_like(betas)
98
+ max_eigenvalues = np.zeros_like(betas)
99
+
100
+ for i, beta in enumerate(betas):
101
+ min_vals = []
102
+ max_vals = []
103
+
104
+ # Run multiple trials with different seeds for more stable results
105
+ for seed in range(seeds):
106
+ # Set random seed
107
+ np.random.seed(seed)
108
+
109
+ # Compute dimension p based on aspect ratio y
110
+ n = n_samples
111
+ p = int(y * n)
112
+
113
+ # Constructing T_n (Population / Shape Matrix)
114
+ T_diag = np.where(np.random.rand(p) < beta, z_a, 1.0)
115
+ T_n = np.diag(T_diag)
116
+
117
+ # Generate the data matrix X with i.i.d. standard normal entries
118
+ X = np.random.randn(p, n)
119
+
120
+ # Compute the sample covariance matrix S_n = (1/n) * XX^T
121
+ S_n = (1 / n) * (X @ X.T)
122
+
123
+ # Compute B_n = S_n T_n
124
+ B_n = S_n @ T_n
125
+
126
+ # Compute eigenvalues of B_n
127
+ eigenvalues = np.linalg.eigvalsh(B_n)
128
+
129
+ # Find minimum and maximum eigenvalues
130
+ min_vals.append(np.min(eigenvalues))
131
+ max_vals.append(np.max(eigenvalues))
132
+
133
+ # Average over seeds for stability
134
+ min_eigenvalues[i] = np.mean(min_vals)
135
+ max_eigenvalues[i] = np.mean(max_vals)
136
+
137
+ return betas, min_eigenvalues, max_eigenvalues
138
+
139
  @st.cache_data
140
  def sweep_beta_and_find_z_bounds(z_a, y, z_min, z_max, beta_steps, z_steps):
141
  """
 
314
  def generate_z_vs_beta_plot(z_a, y, z_min, z_max, beta_steps, z_steps,
315
  s_num_expr=None, s_denom_expr=None,
316
  z_num_expr=None, z_denom_expr=None,
317
+ show_derivatives=False, use_eigenvalue_method=False):
318
  if z_a <= 0 or y <= 0 or z_min >= z_max:
319
  st.error("Invalid input parameters.")
320
  return None
321
 
322
+ # Get beta values and curves based on method
323
+ if use_eigenvalue_method:
324
+ # Use direct eigenvalue computation method to find support boundaries
325
+ betas, z_mins, z_maxs = compute_eigenvalue_support_boundaries(z_a, y, beta_steps)
326
+ else:
327
+ # Use discriminant method
328
+ betas, z_mins, z_maxs = sweep_beta_and_find_z_bounds(z_a, y, z_min, z_max, beta_steps, z_steps)
329
+
330
+ # Compute other curves
331
  high_y_curve = compute_high_y_curve(betas, z_a, y)
332
  alt_low_expr = compute_alternate_low_expr(betas, z_a, y)
333
 
 
354
  fig = go.Figure()
355
 
356
  # Original curves
357
+ line_name_suffix = " (Eigenvalue Method)" if use_eigenvalue_method else ""
358
  fig.add_trace(go.Scatter(x=betas, y=z_maxs, mode="markers+lines",
359
+ name="Upper z*(β)" + line_name_suffix, line=dict(color='blue')))
360
  fig.add_trace(go.Scatter(x=betas, y=z_mins, mode="markers+lines",
361
+ name="Lower z*(β)" + line_name_suffix, line=dict(color='blue')))
362
  # Removed the Low y Expression trace
363
  fig.add_trace(go.Scatter(x=betas, y=high_y_curve, mode="markers+lines",
364
  name="High y Expression", line=dict(color='green')))
 
369
  fig.add_trace(go.Scatter(x=betas, y=max_k_curve, mode="lines",
370
  name="Max k Expression", line=dict(color='red', width=2)))
371
  fig.add_trace(go.Scatter(x=betas, y=min_t_curve, mode="lines",
372
+ name="Min t Expression", line=dict(color='orange', width=2)))
373
 
374
  if custom_curve1 is not None:
375
  fig.add_trace(go.Scatter(x=betas, y=custom_curve1, mode="markers+lines",
 
409
  fig.add_trace(go.Scatter(x=betas, y=min_t_derivatives[1], mode="lines",
410
  name="Min t d²/dβ²", line=dict(color='orange', dash='dot')))
411
 
412
+ method_name = "Eigenvalue Method" if use_eigenvalue_method else "Discriminant Method"
413
  fig.update_layout(
414
+ title=f"Curves vs β: z*(β) Boundaries and Asymptotic Expressions ({method_name})",
415
  xaxis_title="β",
416
  yaxis_title="Value",
417
  hovermode="x unified",
 
555
  beta_steps = st.slider("β steps", min_value=51, max_value=501, value=201, step=50, key="beta_steps")
556
  z_steps = st.slider("z grid steps", min_value=1000, max_value=100000, value=50000, step=1000, key="z_steps")
557
 
558
+ # Add option to use eigenvalue method
559
+ use_eigenvalue_method = st.checkbox("Use Eigenvalue Method", value=True)
560
+
561
  st.subheader("Custom Expression 1 (s-based)")
562
  st.markdown("""Enter expressions for s = numerator/denominator
563
  (using variables `y`, `beta`, `z_a`, and `sqrt()`)""")
 
577
  if st.button("Compute z vs. β Curves", key="tab1_button"):
578
  with col2:
579
  fig = generate_z_vs_beta_plot(z_a_1, y_1, z_min_1, z_max_1, beta_steps, z_steps,
580
+ s_num, s_denom, z_num, z_denom, show_derivatives, use_eigenvalue_method)
581
  if fig is not None:
582
  st.plotly_chart(fig, use_container_width=True)
583
+ method_used = "Eigenvalue Method" if use_eigenvalue_method else "Discriminant Method"
584
+ st.markdown(f"### Curve Explanations (using {method_used})")
585
+ st.markdown(f"""
586
+ - **Upper z*(β)** (Blue): Maximum z value where roots transition between real and complex ({method_used})
587
+ - **Lower z*(β)** (Light Blue): Minimum z value where roots transition between real and complex ({method_used})
588
  - **High y Expression** (Green): Asymptotic approximation for high y values
589
+ - **Low Expression** (Orange): Alternative asymptotic expression
590
  - **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)}$
591
+ - **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)}$
592
  - **Custom Expression 1** (Purple): Result from user-defined s substituted into the main formula
593
  - **Custom Expression 2** (Magenta): Direct z(β) expression
594
  """)
 
655
  beta_steps_diff = st.slider("β steps", min_value=51, max_value=501, value=201, step=50, key="beta_steps_diff")
656
  z_steps_diff = st.slider("z grid steps", min_value=1000, max_value=100000, value=50000, step=1000, key="z_steps_diff")
657
 
658
+ # Add option for eigenvalue method
659
+ use_eigenvalue_diff = st.checkbox("Use Eigenvalue Method", value=False, key="use_eigenvalue_diff")
660
+
661
  # Add options for curve selection
662
  st.subheader("Curves to Analyze")
663
  analyze_upper_lower = st.checkbox("Upper-Lower Difference", value=True)
 
666
 
667
  if st.button("Compute Differentials", key="tab3_button"):
668
  with col2:
669
+ # Use eigenvalue method if selected
670
+ if use_eigenvalue_diff:
671
+ betas_diff, lower_vals, upper_vals = compute_eigenvalue_support_boundaries(z_a_diff, y_diff, beta_steps_diff)
672
+ else:
673
+ betas_diff, lower_vals, upper_vals = sweep_beta_and_find_z_bounds(z_a_diff, y_diff, z_min_diff, z_max_diff, beta_steps_diff, z_steps_diff)
674
 
675
  # Create figure
676
  fig_diff = go.Figure()
 
680
  d1 = np.gradient(diff_curve, betas_diff)
681
  d2 = np.gradient(d1, betas_diff)
682
 
683
+ method_suffix = " (Eigenvalue)" if use_eigenvalue_diff else ""
684
  fig_diff.add_trace(go.Scatter(x=betas_diff, y=diff_curve, mode="lines",
685
+ name="Upper-Lower Difference" + method_suffix, line=dict(color="magenta", width=2)))
686
  fig_diff.add_trace(go.Scatter(x=betas_diff, y=d1, mode="lines",
687
+ name="Upper-Lower d/dβ" + method_suffix, line=dict(color="magenta", dash='dash')))
688
  fig_diff.add_trace(go.Scatter(x=betas_diff, y=d2, mode="lines",
689
+ name="Upper-Lower d²/dβ²" + method_suffix, line=dict(color="magenta", dash='dot')))
690
 
691
  if analyze_high_y:
692
  high_y_curve = compute_high_y_curve(betas_diff, z_a_diff, y_diff)
 
712
  fig_diff.add_trace(go.Scatter(x=betas_diff, y=d2, mode="lines",
713
  name="Alt Low d²/dβ²", line=dict(color="orange", dash='dot')))
714
 
715
+ method_name = "Eigenvalue Method" if use_eigenvalue_diff else "Discriminant Method"
716
  fig_diff.update_layout(
717
+ title=f"Differential Analysis vs. β ({method_name})",
718
  xaxis_title="β",
719
  yaxis_title="Value",
720
  hovermode="x unified",