File size: 10,437 Bytes
dd5ca7d
1126f78
 
3940b3d
 
 
1126f78
 
13b3948
1aa7fa4
1126f78
80ed07e
1126f78
 
 
80ed07e
1aa7fa4
1126f78
 
 
 
 
 
 
 
a2a65af
 
 
 
1126f78
cb0df60
 
 
 
 
 
 
 
 
3940b3d
cb0df60
3940b3d
 
 
 
 
 
cb0df60
3940b3d
 
cb0df60
3940b3d
cb0df60
 
 
 
 
3940b3d
 
 
 
 
 
 
cb0df60
 
 
 
 
 
 
 
 
1126f78
 
 
 
3940b3d
 
 
1126f78
3940b3d
 
 
 
 
 
 
 
 
 
 
 
 
1126f78
 
 
 
3940b3d
 
 
 
 
 
1126f78
 
3940b3d
 
1126f78
 
3940b3d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1126f78
3940b3d
 
359367f
3940b3d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
359367f
a2a65af
 
3940b3d
1126f78
 
a2a65af
1126f78
3940b3d
 
359367f
1126f78
 
 
 
359367f
1126f78
359367f
1126f78
359367f
1126f78
 
359367f
1126f78
359367f
1126f78
 
 
3940b3d
 
359367f
1126f78
359367f
1126f78
 
359367f
1126f78
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
import streamlit as st
import subprocess
import os
import json
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
import time
import io

# Set page config
st.set_page_config(
    page_title="Eigenvalue Analysis",
    page_icon="📊",
    layout="wide"
)

# Title and description
st.title("Eigenvalue Analysis Visualization")
st.markdown("""
This application visualizes eigenvalue analysis for matrices with specific properties.
Adjust the parameters below to generate a plot showing the relationship between empirical
and theoretical eigenvalues.
""")

# Create output directory in the current working directory
current_dir = os.getcwd()
output_dir = os.path.join(current_dir, "output")
os.makedirs(output_dir, exist_ok=True)

# Compile the C++ code at runtime
cpp_file = os.path.join(current_dir, "app.cpp")
executable = os.path.join(current_dir, "eigen_analysis")

# Check if cpp file exists
if not os.path.exists(cpp_file):
    st.error(f"C++ source file not found at: {cpp_file}")
    st.stop()

# Compile the C++ code with the right OpenCV libraries
try:
    st.info("Compiling C++ code...")
    compile_commands = [
        f"g++ -o {executable} {cpp_file} `pkg-config --cflags --libs opencv4` -std=c++11",
        f"g++ -o {executable} {cpp_file} `pkg-config --cflags --libs opencv` -std=c++11",
        f"g++ -o {executable} {cpp_file} -I/usr/include/opencv4 -lopencv_core -lopencv_imgproc -std=c++11"
    ]
    
    compiled = False
    for cmd in compile_commands:
        compile_result = subprocess.run(
            cmd, 
            shell=True,
            capture_output=True,
            text=True
        )
        
        if compile_result.returncode == 0:
            compiled = True
            break
    
    if not compiled:
        st.error("All compilation attempts failed. Please check the system requirements.")
        st.stop()
    
    # Make sure the executable is executable
    os.chmod(executable, 0o755)
    st.success("C++ code compiled successfully")
    
except Exception as e:
    st.error(f"Error during compilation: {str(e)}")
    st.stop()

# Input parameters sidebar
st.sidebar.header("Parameters")

# Parameter inputs with defaults and validation
n = st.sidebar.number_input("Sample size (n)", min_value=5, max_value=1000, value=100, step=5, help="Number of samples")
p = st.sidebar.number_input("Dimension (p)", min_value=5, max_value=1000, value=50, step=5, help="Dimensionality")
a = st.sidebar.number_input("Value for a", min_value=1.1, max_value=10.0, value=2.0, step=0.1, help="Parameter a > 1")

# Automatically calculate y = p/n (as requested)
y = p/n
st.sidebar.text(f"Value for y = p/n: {y:.4f}")

# Add fineness control
fineness = st.sidebar.slider(
    "Calculation fineness", 
    min_value=20, 
    max_value=500, 
    value=100, 
    step=10,
    help="Higher values give smoother curves but take longer to calculate"
)

# Generate button
if st.sidebar.button("Generate Plot", type="primary"):
    # Show progress
    progress_bar = st.progress(0)
    status_text = st.empty()
    
    try:
        # Run the C++ executable with the parameters in JSON output mode
        data_file = os.path.join(output_dir, "eigenvalue_data.json")
        
        # Delete previous output if exists
        if os.path.exists(data_file):
            os.remove(data_file)
        
        # Execute the C++ program
        cmd = [executable, str(n), str(p), str(a), str(y), str(fineness), data_file]
        
        process = subprocess.Popen(
            cmd, 
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            text=True
        )
        
        # Show output in a status area
        status_text.text("Starting calculations...")
        
        last_progress = 0
        while process.poll() is None:
            output = process.stdout.readline()
            if output:
                if output.startswith("PROGRESS:"):
                    try:
                        # Update progress bar
                        progress_value = float(output.split(":")[1].strip())
                        progress_bar.progress(progress_value)
                        last_progress = progress_value
                        status_text.text(f"Calculating... {int(progress_value * 100)}% complete")
                    except:
                        pass
                else:
                    status_text.text(output.strip())
            time.sleep(0.1)
        
        return_code = process.poll()
        
        if return_code != 0:
            error = process.stderr.read()
            st.error(f"Error executing the analysis: {error}")
        else:
            progress_bar.progress(1.0)
            status_text.text("Calculations complete! Generating plot...")
            
            # Load the results from the JSON file
            with open(data_file, 'r') as f:
                data = json.load(f)
            
            # Create a better plot with matplotlib
            beta_values = np.array(data['beta_values'])
            max_eigenvalues = np.array(data['max_eigenvalues'])
            min_eigenvalues = np.array(data['min_eigenvalues'])
            theoretical_max = np.array(data['theoretical_max'])
            theoretical_min = np.array(data['theoretical_min'])
            
            # Create the plot
            fig, ax = plt.subplots(figsize=(12, 9), dpi=100)
            
            # Set the background color
            fig.patch.set_facecolor('#f5f5f5')
            ax.set_facecolor('#f0f0f0')
            
            # Plot the data
            ax.plot(beta_values, max_eigenvalues, 'r-', linewidth=2, 
                    label='Empirical Max Eigenvalue', marker='o', markevery=len(beta_values)//20)
            ax.plot(beta_values, min_eigenvalues, 'b-', linewidth=2, 
                    label='Empirical Min Eigenvalue', marker='o', markevery=len(beta_values)//20)
            ax.plot(beta_values, theoretical_max, 'g-', linewidth=2, 
                    label='Theoretical Max Function', marker='D', markevery=len(beta_values)//20)
            ax.plot(beta_values, theoretical_min, 'm-', linewidth=2, 
                    label='Theoretical Min Function', marker='D', markevery=len(beta_values)//20)
            
            # Add grid
            ax.grid(True, linestyle='--', alpha=0.7)
            
            # Set labels and title
            ax.set_xlabel('β', fontsize=14)
            ax.set_ylabel('Eigenvalues', fontsize=14)
            ax.set_title(f'Eigenvalue Analysis: n={n}, p={p}, a={a}, y={y:.4f}', fontsize=16)
            
            # Add legend
            ax.legend(loc='best', fontsize=12, framealpha=0.9)
            
            # Add formulas as text
            formula_text1 = r"Max Function: $\max_{k \in (0,\infty)} \frac{y\beta(a-1)k + (ak+1)((y-1)k-1)}{(ak+1)(k^2+k)y}$"
            formula_text2 = r"Min Function: $\min_{t \in (-1/a,0)} \frac{y\beta(a-1)t + (at+1)((y-1)t-1)}{(at+1)(t^2+t)y}$"
            
            plt.figtext(0.02, 0.02, formula_text1, fontsize=10, color='green')
            plt.figtext(0.55, 0.02, formula_text2, fontsize=10, color='purple')
            
            # Adjust layout
            plt.tight_layout(rect=[0, 0.05, 1, 0.95])
            
            # Save the plot to a buffer
            buf = io.BytesIO()
            plt.savefig(buf, format='png', dpi=100)
            buf.seek(0)
            
            # Save to file
            output_file = os.path.join(output_dir, "eigenvalue_analysis.png")
            plt.savefig(output_file, format='png', dpi=100)
            plt.close()
            
            # Display the image in Streamlit
            status_text.success("Analysis completed successfully!")
            st.image(buf, use_column_width=True)
            
            # Provide download button
            with open(output_file, "rb") as file:
                btn = st.download_button(
                    label="Download Plot",
                    data=file,
                    file_name=f"eigenvalue_analysis_n{n}_p{p}_a{a}_y{y:.4f}.png",
                    mime="image/png"
                )
            
            # Add some statistics
            st.subheader("Statistical Summary")
            col1, col2 = st.columns(2)
            
            with col1:
                st.write("### Maximum Eigenvalues")
                st.write(f"Empirical Max: {max(max_eigenvalues):.6f}")
                st.write(f"Theoretical Max: {max(theoretical_max):.6f}")
                st.write(f"Difference: {abs(max(max_eigenvalues) - max(theoretical_max)):.6f}")
            
            with col2:
                st.write("### Minimum Eigenvalues")
                st.write(f"Empirical Min: {min(min_eigenvalues):.6f}")
                st.write(f"Theoretical Min: {min(theoretical_min):.6f}")
                st.write(f"Difference: {abs(min(min_eigenvalues) - min(theoretical_min)):.6f}")
    
    except Exception as e:
        st.error(f"An error occurred: {str(e)}")

# Show example plot on startup or previous results
example_file = os.path.join(output_dir, "eigenvalue_analysis.png")
if os.path.exists(example_file):
    # Show the most recent plot by default
    st.subheader("Current Plot")
    img = Image.open(example_file)
    st.image(img, use_column_width=True)
else:
    st.info("👈 Set parameters and click 'Generate Plot' to create a visualization.")

# Add information about the analysis
with st.expander("About Eigenvalue Analysis"):
    st.markdown("""
    ## Theory
    
    This application visualizes the relationship between empirical and theoretical eigenvalues for matrices with specific properties.
    
    The analysis examines:
    
    - **Empirical Max/Min Eigenvalues**: The maximum and minimum eigenvalues calculated from the generated matrices
    - **Theoretical Max/Min Functions**: The theoretical bounds derived from mathematical analysis
    
    ### Key Parameters
    
    - **n**: Sample size
    - **p**: Dimension
    - **a**: Value > 1 that affects the distribution of eigenvalues
    - **y**: Value calculated as p/n that affects scaling
    - **Fineness**: Controls the number of points calculated along the β range (0 to 1)
    
    ### Mathematical Formulas
    
    Max Function: 
    max{k ∈ (0,∞)} [yβ(a-1)k + (ak+1)((y-1)k-1)]/[(ak+1)(k²+k)y]
    
    Min Function: 
    min{t ∈ (-1/a,0)} [yβ(a-1)t + (at+1)((y-1)t-1)]/[(at+1)(t²+t)y]
    """)