euler314 commited on
Commit
7282961
Β·
verified Β·
1 Parent(s): f84f14b

Update app.cpp

Browse files
Files changed (1) hide show
  1. app.cpp +292 -79
app.cpp CHANGED
@@ -1,4 +1,4 @@
1
- // app.cpp - Modified version for Hugging Face Spaces (calculation only)
2
  #include <opencv2/opencv.hpp>
3
  #include <algorithm>
4
  #include <cmath>
@@ -11,6 +11,179 @@
11
  #include <sstream>
12
  #include <string>
13
  #include <fstream>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
  // Function to compute the theoretical max value
16
  double compute_theoretical_max(double a, double y, double beta, int grid_points, double tolerance) {
@@ -174,99 +347,139 @@ void save_as_json(const std::string& filename,
174
  }
175
 
176
  int main(int argc, char* argv[]) {
177
- // ─── Inputs from command line ───────────────────────────────────────────
178
- if (argc != 9) {
179
- std::cerr << "Usage: " << argv[0] << " <n> <p> <a> <y> <fineness> <theory_grid_points> <theory_tolerance> <output_file>" << std::endl;
180
  return 1;
181
  }
182
 
183
- int n = std::stoi(argv[1]);
184
- int p = std::stoi(argv[2]);
185
- double a = std::stod(argv[3]);
186
- double y = std::stod(argv[4]);
187
- int fineness = std::stoi(argv[5]);
188
- int theory_grid_points = std::stoi(argv[6]);
189
- double theory_tolerance = std::stod(argv[7]);
190
- std::string output_file = argv[8];
191
- const double b = 1.0;
192
-
193
- std::cout << "Running with parameters: n = " << n << ", p = " << p
194
- << ", a = " << a << ", y = " << y << ", fineness = " << fineness
195
- << ", theory_grid_points = " << theory_grid_points
196
- << ", theory_tolerance = " << theory_tolerance << std::endl;
197
- std::cout << "Output will be saved to: " << output_file << std::endl;
198
-
199
- // ─── Beta range parameters ────────────────────────────────────────
200
- const int num_beta_points = fineness; // Controlled by fineness parameter
201
- std::vector<double> beta_values(num_beta_points);
202
- for (int i = 0; i < num_beta_points; ++i) {
203
- beta_values[i] = static_cast<double>(i) / (num_beta_points - 1);
204
- }
205
-
206
- // ─── Storage for results ────────────────────────────────────────
207
- std::vector<double> max_eigenvalues(num_beta_points);
208
- std::vector<double> min_eigenvalues(num_beta_points);
209
- std::vector<double> theoretical_max_values(num_beta_points);
210
- std::vector<double> theoretical_min_values(num_beta_points);
211
-
212
- // ─── Random‐Gaussian X and S_n ────────────────────────────────
213
- std::mt19937_64 rng{std::random_device{}()};
214
- std::normal_distribution<double> norm(0.0, 1.0);
215
-
216
- cv::Mat X(p, n, CV_64F);
217
- for(int i = 0; i < p; ++i)
218
- for(int j = 0; j < n; ++j)
219
- X.at<double>(i,j) = norm(rng);
220
 
221
- // ─── Process each beta value ─────────────────────────────────
222
- for (int beta_idx = 0; beta_idx < num_beta_points; ++beta_idx) {
223
- double beta = beta_values[beta_idx];
 
 
 
224
 
225
- // Compute theoretical values with customizable precision
226
- theoretical_max_values[beta_idx] = compute_theoretical_max(a, y, beta, theory_grid_points, theory_tolerance);
227
- theoretical_min_values[beta_idx] = compute_theoretical_min(a, y, beta, theory_grid_points, theory_tolerance);
 
 
 
 
 
 
228
 
229
- // ─── Build T_n matrix ──────────────────────────────────
230
- int k = static_cast<int>(std::floor(beta * p));
231
- std::vector<double> diags(p);
232
- std::fill_n(diags.begin(), k, a);
233
- std::fill_n(diags.begin()+k, p-k, b);
234
- std::shuffle(diags.begin(), diags.end(), rng);
235
 
236
- cv::Mat T_n = cv::Mat::zeros(p, p, CV_64F);
237
- for(int i = 0; i < p; ++i){
238
- T_n.at<double>(i,i) = diags[i];
 
 
239
  }
240
 
241
- // ─── Form B_n = (1/n) * X * T_n * X^T ────────────
242
- cv::Mat B = (X.t() * T_n * X) / static_cast<double>(n);
 
 
 
 
 
 
 
243
 
244
- // ─── Compute eigenvalues of B ────────────────────────────
245
- cv::Mat eigVals;
246
- cv::eigen(B, eigVals);
247
- std::vector<double> eigs(n);
248
- for(int i = 0; i < n; ++i)
249
- eigs[i] = eigVals.at<double>(i, 0);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
250
 
251
- max_eigenvalues[beta_idx] = *std::max_element(eigs.begin(), eigs.end());
252
- min_eigenvalues[beta_idx] = *std::min_element(eigs.begin(), eigs.end());
 
253
 
254
- // Progress indicator for Streamlit
255
- double progress = static_cast<double>(beta_idx + 1) / num_beta_points;
256
- std::cout << "PROGRESS:" << progress << std::endl;
257
 
258
- // Less verbose output for Streamlit
259
- if (beta_idx % 20 == 0 || beta_idx == num_beta_points - 1) {
260
- std::cout << "Processing beta = " << beta
261
- << " (" << beta_idx+1 << "/" << num_beta_points << ")" << std::endl;
 
262
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
263
  }
264
 
265
- // Save data as JSON for Python to read
266
- save_as_json(output_file, beta_values, max_eigenvalues, min_eigenvalues,
267
- theoretical_max_values, theoretical_min_values);
268
-
269
- std::cout << "Data saved to " << output_file << std::endl;
270
-
271
  return 0;
272
  }
 
1
+ // app.cpp - Modified version with cubic equation solver
2
  #include <opencv2/opencv.hpp>
3
  #include <algorithm>
4
  #include <cmath>
 
11
  #include <sstream>
12
  #include <string>
13
  #include <fstream>
14
+ #include <complex>
15
+
16
+ // Struct to hold cubic equation roots
17
+ struct CubicRoots {
18
+ std::complex<double> root1;
19
+ std::complex<double> root2;
20
+ std::complex<double> root3;
21
+ };
22
+
23
+ // Function to solve cubic equation: az^3 + bz^2 + cz + d = 0
24
+ CubicRoots solveCubic(double a, double b, double c, double d) {
25
+ // Handle special case for a == 0 (quadratic)
26
+ if (std::abs(a) < 1e-14) {
27
+ CubicRoots roots;
28
+ // For a quadratic equation: bz^2 + cz + d = 0
29
+ double discriminant = c * c - 4.0 * b * d;
30
+ if (discriminant >= 0) {
31
+ double sqrtDiscriminant = std::sqrt(discriminant);
32
+ roots.root1 = std::complex<double>((-c + sqrtDiscriminant) / (2.0 * b), 0.0);
33
+ roots.root2 = std::complex<double>((-c - sqrtDiscriminant) / (2.0 * b), 0.0);
34
+ roots.root3 = std::complex<double>(1e99, 0.0); // Infinity for third root
35
+ } else {
36
+ double real = -c / (2.0 * b);
37
+ double imag = std::sqrt(-discriminant) / (2.0 * b);
38
+ roots.root1 = std::complex<double>(real, imag);
39
+ roots.root2 = std::complex<double>(real, -imag);
40
+ roots.root3 = std::complex<double>(1e99, 0.0); // Infinity for third root
41
+ }
42
+ return roots;
43
+ }
44
+
45
+ // Normalize equation: z^3 + (b/a)z^2 + (c/a)z + (d/a) = 0
46
+ double p = b / a;
47
+ double q = c / a;
48
+ double r = d / a;
49
+
50
+ // Substitute z = t - p/3 to get t^3 + pt^2 + qt + r = 0
51
+ double p1 = q - p * p / 3.0;
52
+ double q1 = r - p * q / 3.0 + 2.0 * p * p * p / 27.0;
53
+
54
+ // Calculate discriminant
55
+ double D = q1 * q1 / 4.0 + p1 * p1 * p1 / 27.0;
56
+
57
+ // Precompute values
58
+ const double two_pi = 2.0 * M_PI;
59
+ const double third = 1.0 / 3.0;
60
+ const double p_over_3 = p / 3.0;
61
+
62
+ CubicRoots roots;
63
+
64
+ if (D > 1e-10) { // One real root and two complex conjugate roots
65
+ double sqrtD = std::sqrt(D);
66
+ double u = std::cbrt(-q1 / 2.0 + sqrtD);
67
+ double v = std::cbrt(-q1 / 2.0 - sqrtD);
68
+
69
+ // Real root
70
+ roots.root1 = std::complex<double>(u + v - p_over_3, 0.0);
71
+
72
+ // Complex conjugate roots
73
+ double real_part = -(u + v) / 2.0 - p_over_3;
74
+ double imag_part = (u - v) * std::sqrt(3.0) / 2.0;
75
+ roots.root2 = std::complex<double>(real_part, imag_part);
76
+ roots.root3 = std::complex<double>(real_part, -imag_part);
77
+ }
78
+ else if (D < -1e-10) { // Three distinct real roots
79
+ double angle = std::acos(-q1 / 2.0 * std::sqrt(-27.0 / (p1 * p1 * p1)));
80
+ double magnitude = 2.0 * std::sqrt(-p1 / 3.0);
81
+
82
+ roots.root1 = std::complex<double>(magnitude * std::cos(angle / 3.0) - p_over_3, 0.0);
83
+ roots.root2 = std::complex<double>(magnitude * std::cos((angle + two_pi) / 3.0) - p_over_3, 0.0);
84
+ roots.root3 = std::complex<double>(magnitude * std::cos((angle + 2.0 * two_pi) / 3.0) - p_over_3, 0.0);
85
+ }
86
+ else { // D β‰ˆ 0, at least two equal roots
87
+ double u = std::cbrt(-q1 / 2.0);
88
+
89
+ roots.root1 = std::complex<double>(2.0 * u - p_over_3, 0.0);
90
+ roots.root2 = std::complex<double>(-u - p_over_3, 0.0);
91
+ roots.root3 = roots.root2; // Duplicate root
92
+ }
93
+
94
+ return roots;
95
+ }
96
+
97
+ // Function to compute the cubic equation for Im(s) vs z
98
+ std::vector<std::vector<double>> computeImSVsZ(double a, double y, double beta, int num_points) {
99
+ std::vector<double> z_values(num_points);
100
+ std::vector<double> ims_values1(num_points);
101
+ std::vector<double> ims_values2(num_points);
102
+ std::vector<double> ims_values3(num_points);
103
+
104
+ // Generate z values from 0 to 10 (or adjust range as needed)
105
+ double z_start = 0.01; // Avoid z=0 to prevent potential division issues
106
+ double z_end = 10.0;
107
+ double z_step = (z_end - z_start) / (num_points - 1);
108
+
109
+ for (int i = 0; i < num_points; ++i) {
110
+ double z = z_start + i * z_step;
111
+ z_values[i] = z;
112
+
113
+ // Coefficients for the cubic equation:
114
+ // zas^3 + [z(a+1)+a(1-y)]s^2 + [z+(a+1)-y-yΞ²(a-1)]s + 1 = 0
115
+ double coef_a = z * a;
116
+ double coef_b = z * (a + 1) + a * (1 - y);
117
+ double coef_c = z + (a + 1) - y - y * beta * (a - 1);
118
+ double coef_d = 1.0;
119
+
120
+ // Solve the cubic equation
121
+ CubicRoots roots = solveCubic(coef_a, coef_b, coef_c, coef_d);
122
+
123
+ // Extract imaginary parts
124
+ ims_values1[i] = std::abs(roots.root1.imag());
125
+ ims_values2[i] = std::abs(roots.root2.imag());
126
+ ims_values3[i] = std::abs(roots.root3.imag());
127
+ }
128
+
129
+ // Create output vector
130
+ std::vector<std::vector<double>> result = {
131
+ z_values, ims_values1, ims_values2, ims_values3
132
+ };
133
+
134
+ return result;
135
+ }
136
+
137
+ // Function to save Im(s) vs z data as JSON
138
+ void saveImSDataAsJSON(const std::string& filename,
139
+ const std::vector<std::vector<double>>& data) {
140
+ std::ofstream outfile(filename);
141
+
142
+ if (!outfile.is_open()) {
143
+ std::cerr << "Error: Could not open file " << filename << " for writing." << std::endl;
144
+ return;
145
+ }
146
+
147
+ // Start JSON object
148
+ outfile << "{\n";
149
+
150
+ // Write z values
151
+ outfile << " \"z_values\": [";
152
+ for (size_t i = 0; i < data[0].size(); ++i) {
153
+ outfile << data[0][i];
154
+ if (i < data[0].size() - 1) outfile << ", ";
155
+ }
156
+ outfile << "],\n";
157
+
158
+ // Write Im(s) values for first root
159
+ outfile << " \"ims_values1\": [";
160
+ for (size_t i = 0; i < data[1].size(); ++i) {
161
+ outfile << data[1][i];
162
+ if (i < data[1].size() - 1) outfile << ", ";
163
+ }
164
+ outfile << "],\n";
165
+
166
+ // Write Im(s) values for second root
167
+ outfile << " \"ims_values2\": [";
168
+ for (size_t i = 0; i < data[2].size(); ++i) {
169
+ outfile << data[2][i];
170
+ if (i < data[2].size() - 1) outfile << ", ";
171
+ }
172
+ outfile << "],\n";
173
+
174
+ // Write Im(s) values for third root
175
+ outfile << " \"ims_values3\": [";
176
+ for (size_t i = 0; i < data[3].size(); ++i) {
177
+ outfile << data[3][i];
178
+ if (i < data[3].size() - 1) outfile << ", ";
179
+ }
180
+ outfile << "]\n";
181
+
182
+ // Close JSON object
183
+ outfile << "}\n";
184
+
185
+ outfile.close();
186
+ }
187
 
188
  // Function to compute the theoretical max value
189
  double compute_theoretical_max(double a, double y, double beta, int grid_points, double tolerance) {
 
347
  }
348
 
349
  int main(int argc, char* argv[]) {
350
+ // Check command mode
351
+ if (argc < 2) {
352
+ std::cerr << "Usage: " << argv[0] << " [eigenvalues|cubic] [parameters...]" << std::endl;
353
  return 1;
354
  }
355
 
356
+ std::string mode = argv[1];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
357
 
358
+ if (mode == "eigenvalues") {
359
+ // ─── Eigenvalue analysis mode ───────────────────────────────────────────
360
+ if (argc != 9) {
361
+ std::cerr << "Usage: " << argv[0] << " eigenvalues <n> <p> <a> <y> <fineness> <theory_grid_points> <theory_tolerance> <output_file>" << std::endl;
362
+ return 1;
363
+ }
364
 
365
+ int n = std::stoi(argv[2]);
366
+ int p = std::stoi(argv[3]);
367
+ double a = std::stod(argv[4]);
368
+ double y = std::stod(argv[5]);
369
+ int fineness = std::stoi(argv[6]);
370
+ int theory_grid_points = std::stoi(argv[7]);
371
+ double theory_tolerance = std::stod(argv[8]);
372
+ std::string output_file = argv[9];
373
+ const double b = 1.0;
374
 
375
+ std::cout << "Running eigenvalue analysis with parameters: n = " << n << ", p = " << p
376
+ << ", a = " << a << ", y = " << y << ", fineness = " << fineness
377
+ << ", theory_grid_points = " << theory_grid_points
378
+ << ", theory_tolerance = " << theory_tolerance << std::endl;
379
+ std::cout << "Output will be saved to: " << output_file << std::endl;
 
380
 
381
+ // ─── Beta range parameters ────────────────────────────────────────
382
+ const int num_beta_points = fineness; // Controlled by fineness parameter
383
+ std::vector<double> beta_values(num_beta_points);
384
+ for (int i = 0; i < num_beta_points; ++i) {
385
+ beta_values[i] = static_cast<double>(i) / (num_beta_points - 1);
386
  }
387
 
388
+ // ─── Storage for results ────────────────────────────────────────
389
+ std::vector<double> max_eigenvalues(num_beta_points);
390
+ std::vector<double> min_eigenvalues(num_beta_points);
391
+ std::vector<double> theoretical_max_values(num_beta_points);
392
+ std::vector<double> theoretical_min_values(num_beta_points);
393
+
394
+ // ─── Random‐Gaussian X and S_n ────────────────────────────────
395
+ std::mt19937_64 rng{std::random_device{}()};
396
+ std::normal_distribution<double> norm(0.0, 1.0);
397
 
398
+ cv::Mat X(p, n, CV_64F);
399
+ for(int i = 0; i < p; ++i)
400
+ for(int j = 0; j < n; ++j)
401
+ X.at<double>(i,j) = norm(rng);
402
+
403
+ // ─── Process each beta value ─────────────────────────────────
404
+ for (int beta_idx = 0; beta_idx < num_beta_points; ++beta_idx) {
405
+ double beta = beta_values[beta_idx];
406
+
407
+ // Compute theoretical values with customizable precision
408
+ theoretical_max_values[beta_idx] = compute_theoretical_max(a, y, beta, theory_grid_points, theory_tolerance);
409
+ theoretical_min_values[beta_idx] = compute_theoretical_min(a, y, beta, theory_grid_points, theory_tolerance);
410
+
411
+ // ─── Build T_n matrix ──────────────────────────────────
412
+ int k = static_cast<int>(std::floor(beta * p));
413
+ std::vector<double> diags(p);
414
+ std::fill_n(diags.begin(), k, a);
415
+ std::fill_n(diags.begin()+k, p-k, b);
416
+ std::shuffle(diags.begin(), diags.end(), rng);
417
+
418
+ cv::Mat T_n = cv::Mat::zeros(p, p, CV_64F);
419
+ for(int i = 0; i < p; ++i){
420
+ T_n.at<double>(i,i) = diags[i];
421
+ }
422
+
423
+ // ─── Form B_n = (1/n) * X * T_n * X^T ────────────
424
+ cv::Mat B = (X.t() * T_n * X) / static_cast<double>(n);
425
+
426
+ // ─── Compute eigenvalues of B ────────────────────────────
427
+ cv::Mat eigVals;
428
+ cv::eigen(B, eigVals);
429
+ std::vector<double> eigs(n);
430
+ for(int i = 0; i < n; ++i)
431
+ eigs[i] = eigVals.at<double>(i, 0);
432
+
433
+ max_eigenvalues[beta_idx] = *std::max_element(eigs.begin(), eigs.end());
434
+ min_eigenvalues[beta_idx] = *std::min_element(eigs.begin(), eigs.end());
435
+
436
+ // Progress indicator for Streamlit
437
+ double progress = static_cast<double>(beta_idx + 1) / num_beta_points;
438
+ std::cout << "PROGRESS:" << progress << std::endl;
439
+
440
+ // Less verbose output for Streamlit
441
+ if (beta_idx % 20 == 0 || beta_idx == num_beta_points - 1) {
442
+ std::cout << "Processing beta = " << beta
443
+ << " (" << beta_idx+1 << "/" << num_beta_points << ")" << std::endl;
444
+ }
445
+ }
446
 
447
+ // Save data as JSON for Python to read
448
+ save_as_json(output_file, beta_values, max_eigenvalues, min_eigenvalues,
449
+ theoretical_max_values, theoretical_min_values);
450
 
451
+ std::cout << "Data saved to " << output_file << std::endl;
 
 
452
 
453
+ } else if (mode == "cubic") {
454
+ // ─── Cubic equation analysis mode ───────────────────────────────────────────
455
+ if (argc != 6) {
456
+ std::cerr << "Usage: " << argv[0] << " cubic <a> <y> <beta> <num_points> <output_file>" << std::endl;
457
+ return 1;
458
  }
459
+
460
+ double a = std::stod(argv[2]);
461
+ double y = std::stod(argv[3]);
462
+ double beta = std::stod(argv[4]);
463
+ int num_points = std::stoi(argv[5]);
464
+ std::string output_file = argv[6];
465
+
466
+ std::cout << "Running cubic equation analysis with parameters: a = " << a
467
+ << ", y = " << y << ", beta = " << beta << ", num_points = " << num_points << std::endl;
468
+ std::cout << "Output will be saved to: " << output_file << std::endl;
469
+
470
+ // Compute Im(s) vs z data
471
+ std::vector<std::vector<double>> ims_data = computeImSVsZ(a, y, beta, num_points);
472
+
473
+ // Save to JSON
474
+ saveImSDataAsJSON(output_file, ims_data);
475
+
476
+ std::cout << "Cubic equation data saved to " << output_file << std::endl;
477
+
478
+ } else {
479
+ std::cerr << "Unknown mode: " << mode << std::endl;
480
+ std::cerr << "Use 'eigenvalues' or 'cubic'" << std::endl;
481
+ return 1;
482
  }
483
 
 
 
 
 
 
 
484
  return 0;
485
  }