Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -196,7 +196,6 @@ def generate_z_vs_beta_plot(z_a, y, z_min, z_max):
|
|
196 |
def compute_cubic_roots(z, beta, z_a, y):
|
197 |
"""
|
198 |
Compute the roots of the cubic equation for given parameters.
|
199 |
-
Returns array of complex roots.
|
200 |
"""
|
201 |
a = z * z_a
|
202 |
b = z * z_a + z + z_a - z_a*y
|
@@ -252,45 +251,70 @@ def curve2(s, y, beta, a):
|
|
252 |
return y*beta*((a-1)*s)/(a*s+1)
|
253 |
|
254 |
def find_intersections(z, y, beta, a, s_range):
|
255 |
-
"""Find intersections between the two curves"""
|
256 |
def equation(s):
|
257 |
return curve1(s, z, y) - curve2(s, y, beta, a)
|
258 |
|
259 |
-
# Create grid of initial guesses
|
260 |
-
s_guesses = np.linspace(s_range[0], s_range[1],
|
261 |
intersections = []
|
262 |
|
|
|
|
|
|
|
|
|
263 |
for s_guess in s_guesses:
|
264 |
try:
|
265 |
-
s_sol = fsolve(equation, s_guess)
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
|
|
|
|
270 |
except:
|
271 |
continue
|
272 |
-
|
273 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
274 |
|
275 |
def generate_curves_plot(z, y, beta, a, s_range):
|
276 |
-
s = np.linspace(s_range[0], s_range[1],
|
277 |
|
278 |
# Compute curves
|
279 |
y1 = curve1(s, z, y)
|
280 |
y2 = curve2(s, y, beta, a)
|
281 |
|
282 |
-
# Find intersections
|
283 |
intersections = find_intersections(z, y, beta, a, s_range)
|
284 |
|
285 |
fig = go.Figure()
|
286 |
|
287 |
-
# Plot curves
|
288 |
fig.add_trace(
|
289 |
go.Scatter(
|
290 |
x=s, y=y1,
|
291 |
mode='lines',
|
292 |
name='z*s² + (z-y+1)*s + 1',
|
293 |
-
line=dict(color='blue')
|
294 |
)
|
295 |
)
|
296 |
|
@@ -299,11 +323,10 @@ def generate_curves_plot(z, y, beta, a, s_range):
|
|
299 |
x=s, y=y2,
|
300 |
mode='lines',
|
301 |
name='y*β*((a-1)*s)/(a*s+1)',
|
302 |
-
line=dict(color='red')
|
303 |
)
|
304 |
)
|
305 |
|
306 |
-
# Plot intersections
|
307 |
if len(intersections) > 0:
|
308 |
fig.add_trace(
|
309 |
go.Scatter(
|
@@ -312,18 +335,26 @@ def generate_curves_plot(z, y, beta, a, s_range):
|
|
312 |
mode='markers',
|
313 |
name='Intersections',
|
314 |
marker=dict(
|
315 |
-
size=
|
316 |
color='green',
|
317 |
-
symbol='x'
|
|
|
318 |
)
|
319 |
)
|
320 |
)
|
321 |
|
322 |
fig.update_layout(
|
323 |
-
title=f"Curve Intersection Analysis (y={y:.
|
324 |
xaxis_title="s",
|
325 |
yaxis_title="Value",
|
326 |
-
hovermode="closest"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
327 |
)
|
328 |
|
329 |
return fig, intersections
|
@@ -343,27 +374,27 @@ with tab1:
|
|
343 |
y_1 = st.number_input("y", value=1.0, key="y_1")
|
344 |
z_min_1 = st.number_input("z_min", value=-10.0, key="z_min_1")
|
345 |
z_max_1 = st.number_input("z_max", value=10.0, key="z_max_1")
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
|
368 |
with tab2:
|
369 |
st.header("Plot Imaginary Parts of Roots vs. z")
|
@@ -389,7 +420,6 @@ with tab3:
|
|
389 |
col1, col2 = st.columns([1, 2])
|
390 |
|
391 |
with col1:
|
392 |
-
# Add sliders for parameters
|
393 |
z = st.slider("z", min_value=-10.0, max_value=10.0, value=1.0, step=0.1)
|
394 |
y_3 = st.slider("y", min_value=0.1, max_value=10.0, value=1.0, step=0.1, key="y_3")
|
395 |
beta_3 = st.slider("β", min_value=0.0, max_value=1.0, value=0.5, step=0.01, key="beta_3")
|
@@ -410,6 +440,6 @@ with tab3:
|
|
410 |
st.subheader("Intersection Points")
|
411 |
for i, s_val in enumerate(intersections):
|
412 |
y_val = curve1(s_val, z, y_3)
|
413 |
-
st.write(f"Point {i+1}: s = {s_val:.
|
414 |
else:
|
415 |
st.write("No intersections found in the given range.")
|
|
|
196 |
def compute_cubic_roots(z, beta, z_a, y):
|
197 |
"""
|
198 |
Compute the roots of the cubic equation for given parameters.
|
|
|
199 |
"""
|
200 |
a = z * z_a
|
201 |
b = z * z_a + z + z_a - z_a*y
|
|
|
251 |
return y*beta*((a-1)*s)/(a*s+1)
|
252 |
|
253 |
def find_intersections(z, y, beta, a, s_range):
|
254 |
+
"""Find intersections between the two curves with improved accuracy"""
|
255 |
def equation(s):
|
256 |
return curve1(s, z, y) - curve2(s, y, beta, a)
|
257 |
|
258 |
+
# Create a finer grid of initial guesses
|
259 |
+
s_guesses = np.linspace(s_range[0], s_range[1], 200)
|
260 |
intersections = []
|
261 |
|
262 |
+
# Parameters for accuracy
|
263 |
+
tolerance = 1e-10
|
264 |
+
|
265 |
+
# First pass: find all potential intersections
|
266 |
for s_guess in s_guesses:
|
267 |
try:
|
268 |
+
s_sol = fsolve(equation, s_guess, full_output=True, xtol=tolerance)
|
269 |
+
if s_sol[2] == 1: # Check if convergence was achieved
|
270 |
+
s_val = s_sol[0][0]
|
271 |
+
if (s_range[0] <= s_val <= s_range[1] and
|
272 |
+
not any(abs(s_val - s_prev) < tolerance for s_prev in intersections)):
|
273 |
+
if abs(equation(s_val)) < tolerance:
|
274 |
+
intersections.append(s_val)
|
275 |
except:
|
276 |
continue
|
277 |
+
|
278 |
+
# Sort intersections
|
279 |
+
intersections = np.sort(np.array(intersections))
|
280 |
+
|
281 |
+
# Ensure even number of intersections by checking for missed ones
|
282 |
+
if len(intersections) % 2 != 0:
|
283 |
+
refined_intersections = []
|
284 |
+
for i in range(len(intersections)-1):
|
285 |
+
mid_point = (intersections[i] + intersections[i+1])/2
|
286 |
+
try:
|
287 |
+
s_sol = fsolve(equation, mid_point, full_output=True, xtol=tolerance)
|
288 |
+
if s_sol[2] == 1:
|
289 |
+
s_val = s_sol[0][0]
|
290 |
+
if (intersections[i] < s_val < intersections[i+1] and
|
291 |
+
abs(equation(s_val)) < tolerance):
|
292 |
+
refined_intersections.append(s_val)
|
293 |
+
except:
|
294 |
+
continue
|
295 |
+
|
296 |
+
intersections = np.sort(np.append(intersections, refined_intersections))
|
297 |
+
|
298 |
+
return intersections
|
299 |
|
300 |
def generate_curves_plot(z, y, beta, a, s_range):
|
301 |
+
s = np.linspace(s_range[0], s_range[1], 2000)
|
302 |
|
303 |
# Compute curves
|
304 |
y1 = curve1(s, z, y)
|
305 |
y2 = curve2(s, y, beta, a)
|
306 |
|
307 |
+
# Find intersections with improved accuracy
|
308 |
intersections = find_intersections(z, y, beta, a, s_range)
|
309 |
|
310 |
fig = go.Figure()
|
311 |
|
|
|
312 |
fig.add_trace(
|
313 |
go.Scatter(
|
314 |
x=s, y=y1,
|
315 |
mode='lines',
|
316 |
name='z*s² + (z-y+1)*s + 1',
|
317 |
+
line=dict(color='blue', width=2)
|
318 |
)
|
319 |
)
|
320 |
|
|
|
323 |
x=s, y=y2,
|
324 |
mode='lines',
|
325 |
name='y*β*((a-1)*s)/(a*s+1)',
|
326 |
+
line=dict(color='red', width=2)
|
327 |
)
|
328 |
)
|
329 |
|
|
|
330 |
if len(intersections) > 0:
|
331 |
fig.add_trace(
|
332 |
go.Scatter(
|
|
|
335 |
mode='markers',
|
336 |
name='Intersections',
|
337 |
marker=dict(
|
338 |
+
size=12,
|
339 |
color='green',
|
340 |
+
symbol='x',
|
341 |
+
line=dict(width=2)
|
342 |
)
|
343 |
)
|
344 |
)
|
345 |
|
346 |
fig.update_layout(
|
347 |
+
title=f"Curve Intersection Analysis (y={y:.4f}, β={beta:.4f}, a={a:.4f})",
|
348 |
xaxis_title="s",
|
349 |
yaxis_title="Value",
|
350 |
+
hovermode="closest",
|
351 |
+
showlegend=True,
|
352 |
+
legend=dict(
|
353 |
+
yanchor="top",
|
354 |
+
y=0.99,
|
355 |
+
xanchor="left",
|
356 |
+
x=0.01
|
357 |
+
)
|
358 |
)
|
359 |
|
360 |
return fig, intersections
|
|
|
374 |
y_1 = st.number_input("y", value=1.0, key="y_1")
|
375 |
z_min_1 = st.number_input("z_min", value=-10.0, key="z_min_1")
|
376 |
z_max_1 = st.number_input("z_max", value=10.0, key="z_max_1")
|
377 |
+
|
378 |
+
if st.button("Compute z vs. β Curves"):
|
379 |
+
with col2:
|
380 |
+
fig = generate_z_vs_beta_plot(z_a_1, y_1, z_min_1, z_max_1)
|
381 |
+
if fig is not None:
|
382 |
+
st.plotly_chart(fig, use_container_width=True)
|
383 |
+
|
384 |
+
st.markdown("### Additional Expressions")
|
385 |
+
st.markdown("""
|
386 |
+
**Low y Expression (Red):**
|
387 |
+
```
|
388 |
+
((y - 2)*(-1 + sqrt(y*β*(a-1)))/a + y*β*((a-1)/a) - 1/a - 1) /
|
389 |
+
((-1 + sqrt(y*β*(a-1)))/a)^2 + (-1 + sqrt(y*β*(a-1)))/a)
|
390 |
+
```
|
391 |
+
|
392 |
+
**High y Expression (Green):**
|
393 |
+
```
|
394 |
+
((4y + 12)(4 - a) + 16y*β*(a - 1))/(3(4 - a))
|
395 |
+
```
|
396 |
+
where a = z_a
|
397 |
+
""")
|
398 |
|
399 |
with tab2:
|
400 |
st.header("Plot Imaginary Parts of Roots vs. z")
|
|
|
420 |
col1, col2 = st.columns([1, 2])
|
421 |
|
422 |
with col1:
|
|
|
423 |
z = st.slider("z", min_value=-10.0, max_value=10.0, value=1.0, step=0.1)
|
424 |
y_3 = st.slider("y", min_value=0.1, max_value=10.0, value=1.0, step=0.1, key="y_3")
|
425 |
beta_3 = st.slider("β", min_value=0.0, max_value=1.0, value=0.5, step=0.01, key="beta_3")
|
|
|
440 |
st.subheader("Intersection Points")
|
441 |
for i, s_val in enumerate(intersections):
|
442 |
y_val = curve1(s_val, z, y_3)
|
443 |
+
st.write(f"Point {i+1}: s = {s_val:.6f}, y = {y_val:.6f}")
|
444 |
else:
|
445 |
st.write("No intersections found in the given range.")
|