Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -7,6 +7,7 @@ from scipy.stats import gaussian_kde
|
|
| 7 |
import sys
|
| 8 |
import os
|
| 9 |
import importlib.util
|
|
|
|
| 10 |
|
| 11 |
# Configure Streamlit for Hugging Face Spaces - THIS MUST COME FIRST
|
| 12 |
st.set_page_config(
|
|
@@ -15,28 +16,15 @@ st.set_page_config(
|
|
| 15 |
initial_sidebar_state="collapsed"
|
| 16 |
)
|
| 17 |
|
| 18 |
-
#
|
| 19 |
-
|
| 20 |
-
import cubic_cpp
|
| 21 |
-
cpp_available = True
|
| 22 |
-
# Print the location of the imported module to verify
|
| 23 |
-
print(f"Loaded C++ module from: {cubic_cpp.__file__}")
|
| 24 |
-
except ImportError as e:
|
| 25 |
-
print(f"C++ acceleration unavailable: {e}")
|
| 26 |
-
print(f"Python path: {sys.path}")
|
| 27 |
-
print(f"Current directory: {os.getcwd()}")
|
| 28 |
-
|
| 29 |
-
# Try to compile the module on the fly
|
| 30 |
try:
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
print("Attempting to compile C++ module at runtime...")
|
| 34 |
-
|
| 35 |
-
# Get the extension suffix for this Python version
|
| 36 |
ext_suffix = subprocess.check_output("python3-config --extension-suffix", shell=True).decode().strip()
|
| 37 |
print(f"Extension suffix: {ext_suffix}")
|
| 38 |
|
| 39 |
-
# Compile command
|
| 40 |
compile_cmd = f"""g++ -O3 -shared -std=c++17 -fPIC \
|
| 41 |
$(python3-config --includes) \
|
| 42 |
-I$(python3 -c "import pybind11; print(pybind11.get_include())") \
|
|
@@ -49,23 +37,39 @@ except ImportError as e:
|
|
| 49 |
|
| 50 |
if result.returncode == 0:
|
| 51 |
print("Compilation successful")
|
| 52 |
-
# Try to import
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
|
|
|
| 56 |
if spec:
|
| 57 |
cubic_cpp = importlib.util.module_from_spec(spec)
|
| 58 |
spec.loader.exec_module(cubic_cpp)
|
| 59 |
-
cpp_available = True
|
| 60 |
print(f"Successfully imported compiled module")
|
| 61 |
-
|
| 62 |
-
raise ImportError(f"Failed to load module spec for cubic_cpp")
|
| 63 |
else:
|
| 64 |
print(f"Compilation failed: {result.stderr}")
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 69 |
|
| 70 |
def add_sqrt_support(expr_str):
|
| 71 |
"""Replace 'sqrt(' with 'sp.sqrt(' for sympy compatibility"""
|
|
@@ -90,8 +94,7 @@ Delta_expr = (
|
|
| 90 |
+ (c_sym/(3*a_sym) - (b_sym**2)/(9*a_sym**2))**3
|
| 91 |
)
|
| 92 |
|
| 93 |
-
# Define
|
| 94 |
-
# These will be used if C++ module is unavailable
|
| 95 |
|
| 96 |
def discriminant_func_py(z, beta, z_a, y):
|
| 97 |
"""Fast numeric function for the discriminant"""
|
|
@@ -411,20 +414,30 @@ def generate_eigenvalue_distribution_py(beta, y, z_a, n=1000, seed=42):
|
|
| 411 |
eigenvalues = np.linalg.eigvalsh(B_n)
|
| 412 |
return eigenvalues
|
| 413 |
|
| 414 |
-
#
|
| 415 |
if cpp_available:
|
| 416 |
-
|
| 417 |
-
|
| 418 |
-
|
| 419 |
-
|
| 420 |
-
|
| 421 |
-
|
| 422 |
-
|
| 423 |
-
|
| 424 |
-
|
| 425 |
-
|
| 426 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 427 |
else:
|
|
|
|
| 428 |
discriminant_func = discriminant_func_py
|
| 429 |
find_z_at_discriminant_zero = find_z_at_discriminant_zero_py
|
| 430 |
sweep_beta_and_find_z_bounds = sweep_beta_and_find_z_bounds_py
|
|
@@ -1057,84 +1070,7 @@ def generate_eigenvalue_distribution_plot(beta, y, z_a, n=1000, seed=42):
|
|
| 1057 |
)
|
| 1058 |
|
| 1059 |
return fig, eigenvalues
|
| 1060 |
-
|
| 1061 |
-
if cpp_available:
|
| 1062 |
-
# First check which functions actually exist in the C++ module
|
| 1063 |
-
available_cpp_functions = []
|
| 1064 |
-
for func_name in dir(cubic_cpp):
|
| 1065 |
-
if not func_name.startswith('_'):
|
| 1066 |
-
available_cpp_functions.append(func_name)
|
| 1067 |
-
|
| 1068 |
-
print(f"Available C++ functions: {available_cpp_functions}")
|
| 1069 |
-
|
| 1070 |
-
# Now assign functions based on what's available
|
| 1071 |
-
if "discriminant_func" in available_cpp_functions:
|
| 1072 |
-
discriminant_func = cubic_cpp.discriminant_func
|
| 1073 |
-
else:
|
| 1074 |
-
discriminant_func = discriminant_func_py
|
| 1075 |
-
|
| 1076 |
-
if "find_z_at_discriminant_zero" in available_cpp_functions:
|
| 1077 |
-
find_z_at_discriminant_zero = cubic_cpp.find_z_at_discriminant_zero
|
| 1078 |
-
else:
|
| 1079 |
-
find_z_at_discriminant_zero = find_z_at_discriminant_zero_py
|
| 1080 |
-
|
| 1081 |
-
if "sweep_beta_and_find_z_bounds" in available_cpp_functions:
|
| 1082 |
-
sweep_beta_and_find_z_bounds = cubic_cpp.sweep_beta_and_find_z_bounds
|
| 1083 |
-
else:
|
| 1084 |
-
sweep_beta_and_find_z_bounds = sweep_beta_and_find_z_bounds_py
|
| 1085 |
-
|
| 1086 |
-
if "compute_eigenvalue_support_boundaries" in available_cpp_functions:
|
| 1087 |
-
compute_eigenvalue_support_boundaries = cubic_cpp.compute_eigenvalue_support_boundaries
|
| 1088 |
-
else:
|
| 1089 |
-
compute_eigenvalue_support_boundaries = compute_eigenvalue_support_boundaries_py
|
| 1090 |
-
|
| 1091 |
-
if "compute_cubic_roots" in available_cpp_functions:
|
| 1092 |
-
compute_cubic_roots = cubic_cpp.compute_cubic_roots
|
| 1093 |
-
else:
|
| 1094 |
-
compute_cubic_roots = compute_cubic_roots_py
|
| 1095 |
-
|
| 1096 |
-
if "compute_high_y_curve" in available_cpp_functions:
|
| 1097 |
-
compute_high_y_curve = cubic_cpp.compute_high_y_curve
|
| 1098 |
-
else:
|
| 1099 |
-
compute_high_y_curve = compute_high_y_curve_py
|
| 1100 |
-
|
| 1101 |
-
if "compute_alternate_low_expr" in available_cpp_functions:
|
| 1102 |
-
compute_alternate_low_expr = cubic_cpp.compute_alternate_low_expr
|
| 1103 |
-
else:
|
| 1104 |
-
compute_alternate_low_expr = compute_alternate_low_expr_py
|
| 1105 |
-
|
| 1106 |
-
if "compute_max_k_expression" in available_cpp_functions:
|
| 1107 |
-
compute_max_k_expression = cubic_cpp.compute_max_k_expression
|
| 1108 |
-
else:
|
| 1109 |
-
compute_max_k_expression = compute_max_k_expression_py
|
| 1110 |
-
|
| 1111 |
-
if "compute_min_t_expression" in available_cpp_functions:
|
| 1112 |
-
compute_min_t_expression = cubic_cpp.compute_min_t_expression
|
| 1113 |
-
else:
|
| 1114 |
-
compute_min_t_expression = compute_min_t_expression_py
|
| 1115 |
-
|
| 1116 |
-
if "compute_derivatives" in available_cpp_functions:
|
| 1117 |
-
compute_derivatives = cubic_cpp.compute_derivatives
|
| 1118 |
-
else:
|
| 1119 |
-
compute_derivatives = compute_derivatives_py
|
| 1120 |
-
|
| 1121 |
-
if "generate_eigenvalue_distribution" in available_cpp_functions:
|
| 1122 |
-
generate_eigenvalue_distribution = lambda beta, y, z_a, n=1000, seed=42: cubic_cpp.generate_eigenvalue_distribution(beta, y, z_a, n, seed)
|
| 1123 |
-
else:
|
| 1124 |
-
generate_eigenvalue_distribution = generate_eigenvalue_distribution_py
|
| 1125 |
-
else:
|
| 1126 |
-
# Use all Python implementations
|
| 1127 |
-
discriminant_func = discriminant_func_py
|
| 1128 |
-
find_z_at_discriminant_zero = find_z_at_discriminant_zero_py
|
| 1129 |
-
sweep_beta_and_find_z_bounds = sweep_beta_and_find_z_bounds_py
|
| 1130 |
-
compute_eigenvalue_support_boundaries = compute_eigenvalue_support_boundaries_py
|
| 1131 |
-
compute_cubic_roots = compute_cubic_roots_py
|
| 1132 |
-
compute_high_y_curve = compute_high_y_curve_py
|
| 1133 |
-
compute_alternate_low_expr = compute_alternate_low_expr_py
|
| 1134 |
-
compute_max_k_expression = compute_max_k_expression_py
|
| 1135 |
-
compute_min_t_expression = compute_min_t_expression_py
|
| 1136 |
-
compute_derivatives = compute_derivatives_py
|
| 1137 |
-
generate_eigenvalue_distribution = generate_eigenvalue_distribution_py
|
| 1138 |
# ----------------- Streamlit UI -----------------
|
| 1139 |
def main():
|
| 1140 |
st.title("Cubic Root Analysis")
|
|
|
|
| 7 |
import sys
|
| 8 |
import os
|
| 9 |
import importlib.util
|
| 10 |
+
import subprocess
|
| 11 |
|
| 12 |
# Configure Streamlit for Hugging Face Spaces - THIS MUST COME FIRST
|
| 13 |
st.set_page_config(
|
|
|
|
| 16 |
initial_sidebar_state="collapsed"
|
| 17 |
)
|
| 18 |
|
| 19 |
+
# Function to dynamically compile the C++ module
|
| 20 |
+
def compile_cpp_module():
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 21 |
try:
|
| 22 |
+
print("Attempting to compile C++ module...")
|
| 23 |
+
# Get extension suffix
|
|
|
|
|
|
|
|
|
|
| 24 |
ext_suffix = subprocess.check_output("python3-config --extension-suffix", shell=True).decode().strip()
|
| 25 |
print(f"Extension suffix: {ext_suffix}")
|
| 26 |
|
| 27 |
+
# Compile command using C++17
|
| 28 |
compile_cmd = f"""g++ -O3 -shared -std=c++17 -fPIC \
|
| 29 |
$(python3-config --includes) \
|
| 30 |
-I$(python3 -c "import pybind11; print(pybind11.get_include())") \
|
|
|
|
| 37 |
|
| 38 |
if result.returncode == 0:
|
| 39 |
print("Compilation successful")
|
| 40 |
+
# Try to import the newly compiled module
|
| 41 |
+
spec = importlib.util.spec_from_file_location(
|
| 42 |
+
"cubic_cpp",
|
| 43 |
+
os.path.join(os.getcwd(), "cubic_cpp" + ext_suffix)
|
| 44 |
+
)
|
| 45 |
if spec:
|
| 46 |
cubic_cpp = importlib.util.module_from_spec(spec)
|
| 47 |
spec.loader.exec_module(cubic_cpp)
|
|
|
|
| 48 |
print(f"Successfully imported compiled module")
|
| 49 |
+
return cubic_cpp
|
|
|
|
| 50 |
else:
|
| 51 |
print(f"Compilation failed: {result.stderr}")
|
| 52 |
+
except Exception as e:
|
| 53 |
+
print(f"Error during compilation: {e}")
|
| 54 |
+
|
| 55 |
+
return None
|
| 56 |
+
|
| 57 |
+
# Try to import or compile the C++ module
|
| 58 |
+
try:
|
| 59 |
+
import cubic_cpp
|
| 60 |
+
print(f"Loaded existing C++ module from: {cubic_cpp.__file__}")
|
| 61 |
+
cpp_available = True
|
| 62 |
+
except ImportError:
|
| 63 |
+
print("C++ acceleration unavailable: No module named 'cubic_cpp'")
|
| 64 |
+
print(f"Python path: {sys.path}")
|
| 65 |
+
print(f"Current directory: {os.getcwd()}")
|
| 66 |
+
|
| 67 |
+
# Try to compile the module
|
| 68 |
+
cubic_cpp = compile_cpp_module()
|
| 69 |
+
cpp_available = cubic_cpp is not None
|
| 70 |
+
|
| 71 |
+
if cpp_available:
|
| 72 |
+
print(f"Loaded C++ module from: {cubic_cpp.__file__}")
|
| 73 |
|
| 74 |
def add_sqrt_support(expr_str):
|
| 75 |
"""Replace 'sqrt(' with 'sp.sqrt(' for sympy compatibility"""
|
|
|
|
| 94 |
+ (c_sym/(3*a_sym) - (b_sym**2)/(9*a_sym**2))**3
|
| 95 |
)
|
| 96 |
|
| 97 |
+
# Define Python implementations for all functions
|
|
|
|
| 98 |
|
| 99 |
def discriminant_func_py(z, beta, z_a, y):
|
| 100 |
"""Fast numeric function for the discriminant"""
|
|
|
|
| 414 |
eigenvalues = np.linalg.eigvalsh(B_n)
|
| 415 |
return eigenvalues
|
| 416 |
|
| 417 |
+
# Now determine which functions to use
|
| 418 |
if cpp_available:
|
| 419 |
+
# Get list of available C++ functions
|
| 420 |
+
cpp_functions = [name for name in dir(cubic_cpp) if not name.startswith('_')]
|
| 421 |
+
print(f"Available C++ functions: {cpp_functions}")
|
| 422 |
+
|
| 423 |
+
# Assign function implementations based on what's available
|
| 424 |
+
discriminant_func = cubic_cpp.discriminant_func if 'discriminant_func' in cpp_functions else discriminant_func_py
|
| 425 |
+
find_z_at_discriminant_zero = cubic_cpp.find_z_at_discriminant_zero if 'find_z_at_discriminant_zero' in cpp_functions else find_z_at_discriminant_zero_py
|
| 426 |
+
sweep_beta_and_find_z_bounds = cubic_cpp.sweep_beta_and_find_z_bounds if 'sweep_beta_and_find_z_bounds' in cpp_functions else sweep_beta_and_find_z_bounds_py
|
| 427 |
+
compute_eigenvalue_support_boundaries = cubic_cpp.compute_eigenvalue_support_boundaries if 'compute_eigenvalue_support_boundaries' in cpp_functions else compute_eigenvalue_support_boundaries_py
|
| 428 |
+
compute_cubic_roots = cubic_cpp.compute_cubic_roots if 'compute_cubic_roots' in cpp_functions else compute_cubic_roots_py
|
| 429 |
+
compute_high_y_curve = cubic_cpp.compute_high_y_curve if 'compute_high_y_curve' in cpp_functions else compute_high_y_curve_py
|
| 430 |
+
compute_alternate_low_expr = cubic_cpp.compute_alternate_low_expr if 'compute_alternate_low_expr' in cpp_functions else compute_alternate_low_expr_py
|
| 431 |
+
compute_max_k_expression = cubic_cpp.compute_max_k_expression if 'compute_max_k_expression' in cpp_functions else compute_max_k_expression_py
|
| 432 |
+
compute_min_t_expression = cubic_cpp.compute_min_t_expression if 'compute_min_t_expression' in cpp_functions else compute_min_t_expression_py
|
| 433 |
+
compute_derivatives = cubic_cpp.compute_derivatives if 'compute_derivatives' in cpp_functions else compute_derivatives_py
|
| 434 |
+
|
| 435 |
+
if 'generate_eigenvalue_distribution' in cpp_functions:
|
| 436 |
+
generate_eigenvalue_distribution = lambda beta, y, z_a, n=1000, seed=42: cubic_cpp.generate_eigenvalue_distribution(beta, y, z_a, n, seed)
|
| 437 |
+
else:
|
| 438 |
+
generate_eigenvalue_distribution = generate_eigenvalue_distribution_py
|
| 439 |
else:
|
| 440 |
+
# Use all Python implementations
|
| 441 |
discriminant_func = discriminant_func_py
|
| 442 |
find_z_at_discriminant_zero = find_z_at_discriminant_zero_py
|
| 443 |
sweep_beta_and_find_z_bounds = sweep_beta_and_find_z_bounds_py
|
|
|
|
| 1070 |
)
|
| 1071 |
|
| 1072 |
return fig, eigenvalues
|
| 1073 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1074 |
# ----------------- Streamlit UI -----------------
|
| 1075 |
def main():
|
| 1076 |
st.title("Cubic Root Analysis")
|