Spaces:
Sleeping
Sleeping
Update app.cpp
Browse files
app.cpp
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
// app.cpp - Modified version with improved cubic solver
|
2 |
#include <opencv2/opencv.hpp>
|
3 |
#include <algorithm>
|
4 |
#include <cmath>
|
@@ -281,148 +281,6 @@ CubicRoots solveCubic(double a, double b, double c, double d) {
|
|
281 |
return roots;
|
282 |
}
|
283 |
|
284 |
-
// Function to compute the cubic equation for Im(s) vs z
|
285 |
-
std::vector<std::vector<double>> computeImSVsZ(double a, double y, double beta, int num_points, double z_min, double z_max) {
|
286 |
-
std::vector<double> z_values(num_points);
|
287 |
-
std::vector<double> ims_values1(num_points);
|
288 |
-
std::vector<double> ims_values2(num_points);
|
289 |
-
std::vector<double> ims_values3(num_points);
|
290 |
-
std::vector<double> real_values1(num_points);
|
291 |
-
std::vector<double> real_values2(num_points);
|
292 |
-
std::vector<double> real_values3(num_points);
|
293 |
-
|
294 |
-
// Use z_min and z_max parameters
|
295 |
-
double z_start = std::max(0.01, z_min); // Avoid z=0 to prevent potential division issues
|
296 |
-
double z_end = z_max;
|
297 |
-
double z_step = (z_end - z_start) / (num_points - 1);
|
298 |
-
|
299 |
-
for (int i = 0; i < num_points; ++i) {
|
300 |
-
double z = z_start + i * z_step;
|
301 |
-
z_values[i] = z;
|
302 |
-
|
303 |
-
// Coefficients for the cubic equation:
|
304 |
-
// zasΒ³ + [z(a+1)+a(1-y)]sΒ² + [z+(a+1)-y-yΞ²(a-1)]s + 1 = 0
|
305 |
-
double coef_a = z * a;
|
306 |
-
double coef_b = z * (a + 1) + a * (1 - y);
|
307 |
-
double coef_c = z + (a + 1) - y - y * beta * (a - 1);
|
308 |
-
double coef_d = 1.0;
|
309 |
-
|
310 |
-
// Solve the cubic equation
|
311 |
-
CubicRoots roots = solveCubic(coef_a, coef_b, coef_c, coef_d);
|
312 |
-
|
313 |
-
// Extract imaginary and real parts
|
314 |
-
ims_values1[i] = std::abs(roots.root1.imag());
|
315 |
-
ims_values2[i] = std::abs(roots.root2.imag());
|
316 |
-
ims_values3[i] = std::abs(roots.root3.imag());
|
317 |
-
|
318 |
-
real_values1[i] = roots.root1.real();
|
319 |
-
real_values2[i] = roots.root2.real();
|
320 |
-
real_values3[i] = roots.root3.real();
|
321 |
-
}
|
322 |
-
|
323 |
-
// Create output vector, now including real values for better analysis
|
324 |
-
std::vector<std::vector<double>> result = {
|
325 |
-
z_values, ims_values1, ims_values2, ims_values3,
|
326 |
-
real_values1, real_values2, real_values3
|
327 |
-
};
|
328 |
-
|
329 |
-
return result;
|
330 |
-
}
|
331 |
-
|
332 |
-
// Function to save Im(s) vs z data as JSON
|
333 |
-
bool saveImSDataAsJSON(const std::string& filename,
|
334 |
-
const std::vector<std::vector<double>>& data) {
|
335 |
-
std::ofstream outfile(filename);
|
336 |
-
|
337 |
-
if (!outfile.is_open()) {
|
338 |
-
std::cerr << "Error: Could not open file " << filename << " for writing." << std::endl;
|
339 |
-
return false;
|
340 |
-
}
|
341 |
-
|
342 |
-
// Helper function to format floating point values safely for JSON
|
343 |
-
auto formatJsonValue = [](double value) -> std::string {
|
344 |
-
if (std::isnan(value)) {
|
345 |
-
return "\"NaN\""; // JSON doesn't support NaN, so use string
|
346 |
-
} else if (std::isinf(value)) {
|
347 |
-
if (value > 0) {
|
348 |
-
return "\"Infinity\""; // JSON doesn't support Infinity, so use string
|
349 |
-
} else {
|
350 |
-
return "\"-Infinity\""; // JSON doesn't support -Infinity, so use string
|
351 |
-
}
|
352 |
-
} else {
|
353 |
-
// Use a fixed precision to avoid excessively long numbers
|
354 |
-
std::ostringstream oss;
|
355 |
-
oss << std::setprecision(15) << value;
|
356 |
-
return oss.str();
|
357 |
-
}
|
358 |
-
};
|
359 |
-
|
360 |
-
// Start JSON object
|
361 |
-
outfile << "{\n";
|
362 |
-
|
363 |
-
// Write z values
|
364 |
-
outfile << " \"z_values\": [";
|
365 |
-
for (size_t i = 0; i < data[0].size(); ++i) {
|
366 |
-
outfile << formatJsonValue(data[0][i]);
|
367 |
-
if (i < data[0].size() - 1) outfile << ", ";
|
368 |
-
}
|
369 |
-
outfile << "],\n";
|
370 |
-
|
371 |
-
// Write Im(s) values for first root
|
372 |
-
outfile << " \"ims_values1\": [";
|
373 |
-
for (size_t i = 0; i < data[1].size(); ++i) {
|
374 |
-
outfile << formatJsonValue(data[1][i]);
|
375 |
-
if (i < data[1].size() - 1) outfile << ", ";
|
376 |
-
}
|
377 |
-
outfile << "],\n";
|
378 |
-
|
379 |
-
// Write Im(s) values for second root
|
380 |
-
outfile << " \"ims_values2\": [";
|
381 |
-
for (size_t i = 0; i < data[2].size(); ++i) {
|
382 |
-
outfile << formatJsonValue(data[2][i]);
|
383 |
-
if (i < data[2].size() - 1) outfile << ", ";
|
384 |
-
}
|
385 |
-
outfile << "],\n";
|
386 |
-
|
387 |
-
// Write Im(s) values for third root
|
388 |
-
outfile << " \"ims_values3\": [";
|
389 |
-
for (size_t i = 0; i < data[3].size(); ++i) {
|
390 |
-
outfile << formatJsonValue(data[3][i]);
|
391 |
-
if (i < data[3].size() - 1) outfile << ", ";
|
392 |
-
}
|
393 |
-
outfile << "],\n";
|
394 |
-
|
395 |
-
// Write Real(s) values for first root
|
396 |
-
outfile << " \"real_values1\": [";
|
397 |
-
for (size_t i = 0; i < data[4].size(); ++i) {
|
398 |
-
outfile << formatJsonValue(data[4][i]);
|
399 |
-
if (i < data[4].size() - 1) outfile << ", ";
|
400 |
-
}
|
401 |
-
outfile << "],\n";
|
402 |
-
|
403 |
-
// Write Real(s) values for second root
|
404 |
-
outfile << " \"real_values2\": [";
|
405 |
-
for (size_t i = 0; i < data[5].size(); ++i) {
|
406 |
-
outfile << formatJsonValue(data[5][i]);
|
407 |
-
if (i < data[5].size() - 1) outfile << ", ";
|
408 |
-
}
|
409 |
-
outfile << "],\n";
|
410 |
-
|
411 |
-
// Write Real(s) values for third root
|
412 |
-
outfile << " \"real_values3\": [";
|
413 |
-
for (size_t i = 0; i < data[6].size(); ++i) {
|
414 |
-
outfile << formatJsonValue(data[6][i]);
|
415 |
-
if (i < data[6].size() - 1) outfile << ", ";
|
416 |
-
}
|
417 |
-
outfile << "]\n";
|
418 |
-
|
419 |
-
// Close JSON object
|
420 |
-
outfile << "}\n";
|
421 |
-
|
422 |
-
outfile.close();
|
423 |
-
return true;
|
424 |
-
}
|
425 |
-
|
426 |
// Function to compute the theoretical max value
|
427 |
double compute_theoretical_max(double a, double y, double beta, int grid_points, double tolerance) {
|
428 |
auto f = [a, y, beta](double k) -> double {
|
@@ -614,21 +472,21 @@ bool eigenvalueAnalysis(int n, int p, double a, double y, int fineness,
|
|
614 |
<< ", theory_tolerance = " << theory_tolerance << std::endl;
|
615 |
std::cout << "Output will be saved to: " << output_file << std::endl;
|
616 |
|
617 |
-
// βββ Beta range parameters
|
618 |
const int num_beta_points = fineness; // Controlled by fineness parameter
|
619 |
std::vector<double> beta_values(num_beta_points);
|
620 |
for (int i = 0; i < num_beta_points; ++i) {
|
621 |
beta_values[i] = static_cast<double>(i) / (num_beta_points - 1);
|
622 |
}
|
623 |
|
624 |
-
// βββ Storage for results
|
625 |
std::vector<double> max_eigenvalues(num_beta_points);
|
626 |
std::vector<double> min_eigenvalues(num_beta_points);
|
627 |
std::vector<double> theoretical_max_values(num_beta_points);
|
628 |
std::vector<double> theoretical_min_values(num_beta_points);
|
629 |
|
630 |
try {
|
631 |
-
// βββ Random
|
632 |
std::random_device rd;
|
633 |
std::mt19937_64 rng{rd()};
|
634 |
std::normal_distribution<double> norm(0.0, 1.0);
|
@@ -638,7 +496,7 @@ bool eigenvalueAnalysis(int n, int p, double a, double y, int fineness,
|
|
638 |
for(int j = 0; j < n; ++j)
|
639 |
X.at<double>(i,j) = norm(rng);
|
640 |
|
641 |
-
// βββ Process each beta value
|
642 |
for (int beta_idx = 0; beta_idx < num_beta_points; ++beta_idx) {
|
643 |
double beta = beta_values[beta_idx];
|
644 |
|
@@ -646,7 +504,7 @@ bool eigenvalueAnalysis(int n, int p, double a, double y, int fineness,
|
|
646 |
theoretical_max_values[beta_idx] = compute_theoretical_max(a, y, beta, theory_grid_points, theory_tolerance);
|
647 |
theoretical_min_values[beta_idx] = compute_theoretical_min(a, y, beta, theory_grid_points, theory_tolerance);
|
648 |
|
649 |
-
// βββ Build T_n matrix
|
650 |
int k = static_cast<int>(std::floor(beta * p));
|
651 |
std::vector<double> diags(p, 1.0);
|
652 |
std::fill_n(diags.begin(), k, a);
|
@@ -657,10 +515,10 @@ bool eigenvalueAnalysis(int n, int p, double a, double y, int fineness,
|
|
657 |
T_n.at<double>(i,i) = diags[i];
|
658 |
}
|
659 |
|
660 |
-
// βββ Form B_n = (1/n) * X * T_n * X^T
|
661 |
cv::Mat B = (X.t() * T_n * X) / static_cast<double>(n);
|
662 |
|
663 |
-
// βββ Compute eigenvalues of B
|
664 |
cv::Mat eigVals;
|
665 |
cv::eigen(B, eigVals);
|
666 |
std::vector<double> eigs(n);
|
@@ -700,6 +558,314 @@ bool eigenvalueAnalysis(int n, int p, double a, double y, int fineness,
|
|
700 |
}
|
701 |
}
|
702 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
703 |
// Cubic equation analysis function
|
704 |
bool cubicAnalysis(double a, double y, double beta, int num_points, double z_min, double z_max, const std::string& output_file) {
|
705 |
std::cout << "Running cubic equation analysis with parameters: a = " << a
|
@@ -740,6 +906,7 @@ int main(int argc, char* argv[]) {
|
|
740 |
if (argc < 2) {
|
741 |
std::cerr << "Error: Missing mode argument." << std::endl;
|
742 |
std::cerr << "Usage: " << argv[0] << " eigenvalues <n> <p> <a> <y> <fineness> <theory_grid_points> <theory_tolerance> <output_file>" << std::endl;
|
|
|
743 |
std::cerr << " or: " << argv[0] << " cubic <a> <y> <beta> <num_points> <z_min> <z_max> <output_file>" << std::endl;
|
744 |
return 1;
|
745 |
}
|
@@ -748,7 +915,7 @@ int main(int argc, char* argv[]) {
|
|
748 |
|
749 |
try {
|
750 |
if (mode == "eigenvalues") {
|
751 |
-
// βββ Eigenvalue analysis mode
|
752 |
if (argc != 10) {
|
753 |
std::cerr << "Error: Incorrect number of arguments for eigenvalues mode." << std::endl;
|
754 |
std::cerr << "Usage: " << argv[0] << " eigenvalues <n> <p> <a> <y> <fineness> <theory_grid_points> <theory_tolerance> <output_file>" << std::endl;
|
@@ -769,8 +936,32 @@ int main(int argc, char* argv[]) {
|
|
769 |
return 1;
|
770 |
}
|
771 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
772 |
} else if (mode == "cubic") {
|
773 |
-
// βββ Cubic equation analysis mode
|
774 |
if (argc != 9) {
|
775 |
std::cerr << "Error: Incorrect number of arguments for cubic mode." << std::endl;
|
776 |
std::cerr << "Usage: " << argv[0] << " cubic <a> <y> <beta> <num_points> <z_min> <z_max> <output_file>" << std::endl;
|
@@ -792,7 +983,7 @@ int main(int argc, char* argv[]) {
|
|
792 |
|
793 |
} else {
|
794 |
std::cerr << "Error: Unknown mode: " << mode << std::endl;
|
795 |
-
std::cerr << "Use 'eigenvalues' or 'cubic'" << std::endl;
|
796 |
return 1;
|
797 |
}
|
798 |
}
|
|
|
1 |
+
// app.cpp - Modified version with improved cubic solver and fixed beta analysis
|
2 |
#include <opencv2/opencv.hpp>
|
3 |
#include <algorithm>
|
4 |
#include <cmath>
|
|
|
281 |
return roots;
|
282 |
}
|
283 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
284 |
// Function to compute the theoretical max value
|
285 |
double compute_theoretical_max(double a, double y, double beta, int grid_points, double tolerance) {
|
286 |
auto f = [a, y, beta](double k) -> double {
|
|
|
472 |
<< ", theory_tolerance = " << theory_tolerance << std::endl;
|
473 |
std::cout << "Output will be saved to: " << output_file << std::endl;
|
474 |
|
475 |
+
// βββ Beta range parameters ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
476 |
const int num_beta_points = fineness; // Controlled by fineness parameter
|
477 |
std::vector<double> beta_values(num_beta_points);
|
478 |
for (int i = 0; i < num_beta_points; ++i) {
|
479 |
beta_values[i] = static_cast<double>(i) / (num_beta_points - 1);
|
480 |
}
|
481 |
|
482 |
+
// βββ Storage for results βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
483 |
std::vector<double> max_eigenvalues(num_beta_points);
|
484 |
std::vector<double> min_eigenvalues(num_beta_points);
|
485 |
std::vector<double> theoretical_max_values(num_beta_points);
|
486 |
std::vector<double> theoretical_min_values(num_beta_points);
|
487 |
|
488 |
try {
|
489 |
+
// βββ Random Gaussian X and S_n βββββββββββββββββββββββββββββββββββββββββββββ
|
490 |
std::random_device rd;
|
491 |
std::mt19937_64 rng{rd()};
|
492 |
std::normal_distribution<double> norm(0.0, 1.0);
|
|
|
496 |
for(int j = 0; j < n; ++j)
|
497 |
X.at<double>(i,j) = norm(rng);
|
498 |
|
499 |
+
// βββ Process each beta value ββββββββββββββββββββββββββββββββββββββββββββββββββ
|
500 |
for (int beta_idx = 0; beta_idx < num_beta_points; ++beta_idx) {
|
501 |
double beta = beta_values[beta_idx];
|
502 |
|
|
|
504 |
theoretical_max_values[beta_idx] = compute_theoretical_max(a, y, beta, theory_grid_points, theory_tolerance);
|
505 |
theoretical_min_values[beta_idx] = compute_theoretical_min(a, y, beta, theory_grid_points, theory_tolerance);
|
506 |
|
507 |
+
// βββ Build T_n matrix ββββββββββββββββββββββββββββββββββββββββββββββββββ
|
508 |
int k = static_cast<int>(std::floor(beta * p));
|
509 |
std::vector<double> diags(p, 1.0);
|
510 |
std::fill_n(diags.begin(), k, a);
|
|
|
515 |
T_n.at<double>(i,i) = diags[i];
|
516 |
}
|
517 |
|
518 |
+
// βββ Form B_n = (1/n) * X * T_n * X^T ββββββββββββββββββββββββββ
|
519 |
cv::Mat B = (X.t() * T_n * X) / static_cast<double>(n);
|
520 |
|
521 |
+
// βββ Compute eigenvalues of B βββββββββββββββββββββββββββββββββββββ
|
522 |
cv::Mat eigVals;
|
523 |
cv::eigen(B, eigVals);
|
524 |
std::vector<double> eigs(n);
|
|
|
558 |
}
|
559 |
}
|
560 |
|
561 |
+
// Fixed beta eigenvalue analysis function
|
562 |
+
bool fixedBetaEigenvalueAnalysis(int n, int p, double y, double beta, double a_min, double a_max, int fineness,
|
563 |
+
int theory_grid_points, double theory_tolerance,
|
564 |
+
const std::string& output_file) {
|
565 |
+
|
566 |
+
std::cout << "Running fixed beta eigenvalue analysis with parameters: n = " << n << ", p = " << p
|
567 |
+
<< ", y = " << y << ", beta = " << beta << ", a_min = " << a_min << ", a_max = " << a_max
|
568 |
+
<< ", fineness = " << fineness
|
569 |
+
<< ", theory_grid_points = " << theory_grid_points
|
570 |
+
<< ", theory_tolerance = " << theory_tolerance << std::endl;
|
571 |
+
std::cout << "Output will be saved to: " << output_file << std::endl;
|
572 |
+
|
573 |
+
// βββ a range parameters ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
574 |
+
const int num_a_points = fineness; // Controlled by fineness parameter
|
575 |
+
std::vector<double> a_values(num_a_points);
|
576 |
+
for (int i = 0; i < num_a_points; ++i) {
|
577 |
+
a_values[i] = a_min + (a_max - a_min) * static_cast<double>(i) / (num_a_points - 1);
|
578 |
+
}
|
579 |
+
|
580 |
+
// βββ Storage for results βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
581 |
+
std::vector<double> max_eigenvalues(num_a_points);
|
582 |
+
std::vector<double> min_eigenvalues(num_a_points);
|
583 |
+
std::vector<double> theoretical_max_values(num_a_points);
|
584 |
+
std::vector<double> theoretical_min_values(num_a_points);
|
585 |
+
|
586 |
+
try {
|
587 |
+
// βββ Random Gaussian X and S_n βββββββββββββββββββββββββββββββββββββββββββββ
|
588 |
+
std::random_device rd;
|
589 |
+
std::mt19937_64 rng{rd()};
|
590 |
+
std::normal_distribution<double> norm(0.0, 1.0);
|
591 |
+
|
592 |
+
cv::Mat X(p, n, CV_64F);
|
593 |
+
for(int i = 0; i < p; ++i)
|
594 |
+
for(int j = 0; j < n; ++j)
|
595 |
+
X.at<double>(i,j) = norm(rng);
|
596 |
+
|
597 |
+
// βββ Process each a value ββββββββββββββββββββββββββββββββββββββββββββββββββ
|
598 |
+
for (int a_idx = 0; a_idx < num_a_points; ++a_idx) {
|
599 |
+
double a = a_values[a_idx];
|
600 |
+
|
601 |
+
// Compute theoretical values with customizable precision
|
602 |
+
theoretical_max_values[a_idx] = compute_theoretical_max(a, y, beta, theory_grid_points, theory_tolerance);
|
603 |
+
theoretical_min_values[a_idx] = compute_theoretical_min(a, y, beta, theory_grid_points, theory_tolerance);
|
604 |
+
|
605 |
+
// βββ Build T_n matrix ββββββββββββββββββββββββββββββββββββββββββββββββββ
|
606 |
+
int k = static_cast<int>(std::floor(beta * p));
|
607 |
+
std::vector<double> diags(p, 1.0);
|
608 |
+
std::fill_n(diags.begin(), k, a);
|
609 |
+
std::shuffle(diags.begin(), diags.end(), rng);
|
610 |
+
|
611 |
+
cv::Mat T_n = cv::Mat::zeros(p, p, CV_64F);
|
612 |
+
for(int i = 0; i < p; ++i){
|
613 |
+
T_n.at<double>(i,i) = diags[i];
|
614 |
+
}
|
615 |
+
|
616 |
+
// βββ Form B_n = (1/n) * X * T_n * X^T ββββββββββββββββββββββββββ
|
617 |
+
cv::Mat B = (X.t() * T_n * X) / static_cast<double>(n);
|
618 |
+
|
619 |
+
// βββ Compute eigenvalues of B βββββββββββββββββββββββββββββββββββββ
|
620 |
+
cv::Mat eigVals;
|
621 |
+
cv::eigen(B, eigVals);
|
622 |
+
std::vector<double> eigs(n);
|
623 |
+
for(int i = 0; i < n; ++i)
|
624 |
+
eigs[i] = eigVals.at<double>(i, 0);
|
625 |
+
|
626 |
+
max_eigenvalues[a_idx] = *std::max_element(eigs.begin(), eigs.end());
|
627 |
+
min_eigenvalues[a_idx] = *std::min_element(eigs.begin(), eigs.end());
|
628 |
+
|
629 |
+
// Progress indicator for Streamlit
|
630 |
+
double progress = static_cast<double>(a_idx + 1) / num_a_points;
|
631 |
+
std::cout << "PROGRESS:" << progress << std::endl;
|
632 |
+
|
633 |
+
// Less verbose output for Streamlit
|
634 |
+
if (a_idx % 20 == 0 || a_idx == num_a_points - 1) {
|
635 |
+
std::cout << "Processing a = " << a
|
636 |
+
<< " (" << a_idx+1 << "/" << num_a_points << ")" << std::endl;
|
637 |
+
}
|
638 |
+
}
|
639 |
+
|
640 |
+
// Save data as JSON for Python to read - use same format but with a_values instead of beta_values
|
641 |
+
std::ofstream outfile(output_file);
|
642 |
+
|
643 |
+
if (!outfile.is_open()) {
|
644 |
+
std::cerr << "Error: Could not open file " << output_file << " for writing." << std::endl;
|
645 |
+
return false;
|
646 |
+
}
|
647 |
+
|
648 |
+
// Helper function to format floating point values safely for JSON
|
649 |
+
auto formatJsonValue = [](double value) -> std::string {
|
650 |
+
if (std::isnan(value)) {
|
651 |
+
return "\"NaN\""; // JSON doesn't support NaN, so use string
|
652 |
+
} else if (std::isinf(value)) {
|
653 |
+
if (value > 0) {
|
654 |
+
return "\"Infinity\""; // JSON doesn't support Infinity, so use string
|
655 |
+
} else {
|
656 |
+
return "\"-Infinity\""; // JSON doesn't support -Infinity, so use string
|
657 |
+
}
|
658 |
+
} else {
|
659 |
+
// Use a fixed precision to avoid excessively long numbers
|
660 |
+
std::ostringstream oss;
|
661 |
+
oss << std::setprecision(15) << value;
|
662 |
+
return oss.str();
|
663 |
+
}
|
664 |
+
};
|
665 |
+
|
666 |
+
// Start JSON object
|
667 |
+
outfile << "{\n";
|
668 |
+
|
669 |
+
// Write a values (instead of beta values)
|
670 |
+
outfile << " \"a_values\": [";
|
671 |
+
for (size_t i = 0; i < a_values.size(); ++i) {
|
672 |
+
outfile << formatJsonValue(a_values[i]);
|
673 |
+
if (i < a_values.size() - 1) outfile << ", ";
|
674 |
+
}
|
675 |
+
outfile << "],\n";
|
676 |
+
|
677 |
+
// Write max eigenvalues
|
678 |
+
outfile << " \"max_eigenvalues\": [";
|
679 |
+
for (size_t i = 0; i < max_eigenvalues.size(); ++i) {
|
680 |
+
outfile << formatJsonValue(max_eigenvalues[i]);
|
681 |
+
if (i < max_eigenvalues.size() - 1) outfile << ", ";
|
682 |
+
}
|
683 |
+
outfile << "],\n";
|
684 |
+
|
685 |
+
// Write min eigenvalues
|
686 |
+
outfile << " \"min_eigenvalues\": [";
|
687 |
+
for (size_t i = 0; i < min_eigenvalues.size(); ++i) {
|
688 |
+
outfile << formatJsonValue(min_eigenvalues[i]);
|
689 |
+
if (i < min_eigenvalues.size() - 1) outfile << ", ";
|
690 |
+
}
|
691 |
+
outfile << "],\n";
|
692 |
+
|
693 |
+
// Write theoretical max values
|
694 |
+
outfile << " \"theoretical_max\": [";
|
695 |
+
for (size_t i = 0; i < theoretical_max_values.size(); ++i) {
|
696 |
+
outfile << formatJsonValue(theoretical_max_values[i]);
|
697 |
+
if (i < theoretical_max_values.size() - 1) outfile << ", ";
|
698 |
+
}
|
699 |
+
outfile << "],\n";
|
700 |
+
|
701 |
+
// Write theoretical min values
|
702 |
+
outfile << " \"theoretical_min\": [";
|
703 |
+
for (size_t i = 0; i < theoretical_min_values.size(); ++i) {
|
704 |
+
outfile << formatJsonValue(theoretical_min_values[i]);
|
705 |
+
if (i < theoretical_min_values.size() - 1) outfile << ", ";
|
706 |
+
}
|
707 |
+
outfile << "]\n";
|
708 |
+
|
709 |
+
// Close JSON object
|
710 |
+
outfile << "}\n";
|
711 |
+
|
712 |
+
outfile.close();
|
713 |
+
|
714 |
+
std::cout << "Data saved to " << output_file << std::endl;
|
715 |
+
return true;
|
716 |
+
}
|
717 |
+
catch (const std::exception& e) {
|
718 |
+
std::cerr << "Error in fixed beta eigenvalue analysis: " << e.what() << std::endl;
|
719 |
+
return false;
|
720 |
+
}
|
721 |
+
catch (...) {
|
722 |
+
std::cerr << "Unknown error in fixed beta eigenvalue analysis" << std::endl;
|
723 |
+
return false;
|
724 |
+
}
|
725 |
+
}
|
726 |
+
|
727 |
+
// Function to compute the cubic equation for Im(s) vs z
|
728 |
+
std::vector<std::vector<double>> computeImSVsZ(double a, double y, double beta, int num_points, double z_min, double z_max) {
|
729 |
+
std::vector<double> z_values(num_points);
|
730 |
+
std::vector<double> ims_values1(num_points);
|
731 |
+
std::vector<double> ims_values2(num_points);
|
732 |
+
std::vector<double> ims_values3(num_points);
|
733 |
+
std::vector<double> real_values1(num_points);
|
734 |
+
std::vector<double> real_values2(num_points);
|
735 |
+
std::vector<double> real_values3(num_points);
|
736 |
+
|
737 |
+
// Use z_min and z_max parameters
|
738 |
+
double z_start = std::max(0.01, z_min); // Avoid z=0 to prevent potential division issues
|
739 |
+
double z_end = z_max;
|
740 |
+
double z_step = (z_end - z_start) / (num_points - 1);
|
741 |
+
|
742 |
+
for (int i = 0; i < num_points; ++i) {
|
743 |
+
double z = z_start + i * z_step;
|
744 |
+
z_values[i] = z;
|
745 |
+
|
746 |
+
// Coefficients for the cubic equation:
|
747 |
+
// zasΓΒ³ + [z(a+1)+a(1-y)]sΓΒ² + [z+(a+1)-y-yΓΒ²(a-1)]s + 1 = 0
|
748 |
+
double coef_a = z * a;
|
749 |
+
double coef_b = z * (a + 1) + a * (1 - y);
|
750 |
+
double coef_c = z + (a + 1) - y - y * beta * (a - 1);
|
751 |
+
double coef_d = 1.0;
|
752 |
+
|
753 |
+
// Solve the cubic equation
|
754 |
+
CubicRoots roots = solveCubic(coef_a, coef_b, coef_c, coef_d);
|
755 |
+
|
756 |
+
// Extract imaginary and real parts
|
757 |
+
ims_values1[i] = std::abs(roots.root1.imag());
|
758 |
+
ims_values2[i] = std::abs(roots.root2.imag());
|
759 |
+
ims_values3[i] = std::abs(roots.root3.imag());
|
760 |
+
|
761 |
+
real_values1[i] = roots.root1.real();
|
762 |
+
real_values2[i] = roots.root2.real();
|
763 |
+
real_values3[i] = roots.root3.real();
|
764 |
+
}
|
765 |
+
|
766 |
+
// Create output vector, now including real values for better analysis
|
767 |
+
std::vector<std::vector<double>> result = {
|
768 |
+
z_values, ims_values1, ims_values2, ims_values3,
|
769 |
+
real_values1, real_values2, real_values3
|
770 |
+
};
|
771 |
+
|
772 |
+
return result;
|
773 |
+
}
|
774 |
+
|
775 |
+
// Function to save Im(s) vs z data as JSON
|
776 |
+
bool saveImSDataAsJSON(const std::string& filename,
|
777 |
+
const std::vector<std::vector<double>>& data) {
|
778 |
+
std::ofstream outfile(filename);
|
779 |
+
|
780 |
+
if (!outfile.is_open()) {
|
781 |
+
std::cerr << "Error: Could not open file " << filename << " for writing." << std::endl;
|
782 |
+
return false;
|
783 |
+
}
|
784 |
+
|
785 |
+
// Helper function to format floating point values safely for JSON
|
786 |
+
auto formatJsonValue = [](double value) -> std::string {
|
787 |
+
if (std::isnan(value)) {
|
788 |
+
return "\"NaN\""; // JSON doesn't support NaN, so use string
|
789 |
+
} else if (std::isinf(value)) {
|
790 |
+
if (value > 0) {
|
791 |
+
return "\"Infinity\""; // JSON doesn't support Infinity, so use string
|
792 |
+
} else {
|
793 |
+
return "\"-Infinity\""; // JSON doesn't support -Infinity, so use string
|
794 |
+
}
|
795 |
+
} else {
|
796 |
+
// Use a fixed precision to avoid excessively long numbers
|
797 |
+
std::ostringstream oss;
|
798 |
+
oss << std::setprecision(15) << value;
|
799 |
+
return oss.str();
|
800 |
+
}
|
801 |
+
};
|
802 |
+
|
803 |
+
// Start JSON object
|
804 |
+
outfile << "{\n";
|
805 |
+
|
806 |
+
// Write z values
|
807 |
+
outfile << " \"z_values\": [";
|
808 |
+
for (size_t i = 0; i < data[0].size(); ++i) {
|
809 |
+
outfile << formatJsonValue(data[0][i]);
|
810 |
+
if (i < data[0].size() - 1) outfile << ", ";
|
811 |
+
}
|
812 |
+
outfile << "],\n";
|
813 |
+
|
814 |
+
// Write Im(s) values for first root
|
815 |
+
outfile << " \"ims_values1\": [";
|
816 |
+
for (size_t i = 0; i < data[1].size(); ++i) {
|
817 |
+
outfile << formatJsonValue(data[1][i]);
|
818 |
+
if (i < data[1].size() - 1) outfile << ", ";
|
819 |
+
}
|
820 |
+
outfile << "],\n";
|
821 |
+
|
822 |
+
// Write Im(s) values for second root
|
823 |
+
outfile << " \"ims_values2\": [";
|
824 |
+
for (size_t i = 0; i < data[2].size(); ++i) {
|
825 |
+
outfile << formatJsonValue(data[2][i]);
|
826 |
+
if (i < data[2].size() - 1) outfile << ", ";
|
827 |
+
}
|
828 |
+
outfile << "],\n";
|
829 |
+
|
830 |
+
// Write Im(s) values for third root
|
831 |
+
outfile << " \"ims_values3\": [";
|
832 |
+
for (size_t i = 0; i < data[3].size(); ++i) {
|
833 |
+
outfile << formatJsonValue(data[3][i]);
|
834 |
+
if (i < data[3].size() - 1) outfile << ", ";
|
835 |
+
}
|
836 |
+
outfile << "],\n";
|
837 |
+
|
838 |
+
// Write Real(s) values for first root
|
839 |
+
outfile << " \"real_values1\": [";
|
840 |
+
for (size_t i = 0; i < data[4].size(); ++i) {
|
841 |
+
outfile << formatJsonValue(data[4][i]);
|
842 |
+
if (i < data[4].size() - 1) outfile << ", ";
|
843 |
+
}
|
844 |
+
outfile << "],\n";
|
845 |
+
|
846 |
+
// Write Real(s) values for second root
|
847 |
+
outfile << " \"real_values2\": [";
|
848 |
+
for (size_t i = 0; i < data[5].size(); ++i) {
|
849 |
+
outfile << formatJsonValue(data[5][i]);
|
850 |
+
if (i < data[5].size() - 1) outfile << ", ";
|
851 |
+
}
|
852 |
+
outfile << "],\n";
|
853 |
+
|
854 |
+
// Write Real(s) values for third root
|
855 |
+
outfile << " \"real_values3\": [";
|
856 |
+
for (size_t i = 0; i < data[6].size(); ++i) {
|
857 |
+
outfile << formatJsonValue(data[6][i]);
|
858 |
+
if (i < data[6].size() - 1) outfile << ", ";
|
859 |
+
}
|
860 |
+
outfile << "]\n";
|
861 |
+
|
862 |
+
// Close JSON object
|
863 |
+
outfile << "}\n";
|
864 |
+
|
865 |
+
outfile.close();
|
866 |
+
return true;
|
867 |
+
}
|
868 |
+
|
869 |
// Cubic equation analysis function
|
870 |
bool cubicAnalysis(double a, double y, double beta, int num_points, double z_min, double z_max, const std::string& output_file) {
|
871 |
std::cout << "Running cubic equation analysis with parameters: a = " << a
|
|
|
906 |
if (argc < 2) {
|
907 |
std::cerr << "Error: Missing mode argument." << std::endl;
|
908 |
std::cerr << "Usage: " << argv[0] << " eigenvalues <n> <p> <a> <y> <fineness> <theory_grid_points> <theory_tolerance> <output_file>" << std::endl;
|
909 |
+
std::cerr << " or: " << argv[0] << " eigenvalues_fixed_beta <n> <p> <y> <beta> <a_min> <a_max> <fineness> <theory_grid_points> <theory_tolerance> <output_file>" << std::endl;
|
910 |
std::cerr << " or: " << argv[0] << " cubic <a> <y> <beta> <num_points> <z_min> <z_max> <output_file>" << std::endl;
|
911 |
return 1;
|
912 |
}
|
|
|
915 |
|
916 |
try {
|
917 |
if (mode == "eigenvalues") {
|
918 |
+
// βββ Eigenvalue analysis mode βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
919 |
if (argc != 10) {
|
920 |
std::cerr << "Error: Incorrect number of arguments for eigenvalues mode." << std::endl;
|
921 |
std::cerr << "Usage: " << argv[0] << " eigenvalues <n> <p> <a> <y> <fineness> <theory_grid_points> <theory_tolerance> <output_file>" << std::endl;
|
|
|
936 |
return 1;
|
937 |
}
|
938 |
|
939 |
+
} else if (mode == "eigenvalues_fixed_beta") {
|
940 |
+
// βββ Fixed beta eigenvalue analysis mode ββββββββββββββββββββββββββββββββββββββββββββ
|
941 |
+
if (argc != 12) {
|
942 |
+
std::cerr << "Error: Incorrect number of arguments for eigenvalues_fixed_beta mode." << std::endl;
|
943 |
+
std::cerr << "Usage: " << argv[0] << " eigenvalues_fixed_beta <n> <p> <y> <beta> <a_min> <a_max> <fineness> <theory_grid_points> <theory_tolerance> <output_file>" << std::endl;
|
944 |
+
std::cerr << "Received " << argc << " arguments, expected 12." << std::endl;
|
945 |
+
return 1;
|
946 |
+
}
|
947 |
+
|
948 |
+
int n = std::stoi(argv[2]);
|
949 |
+
int p = std::stoi(argv[3]);
|
950 |
+
double y = std::stod(argv[4]);
|
951 |
+
double beta = std::stod(argv[5]);
|
952 |
+
double a_min = std::stod(argv[6]);
|
953 |
+
double a_max = std::stod(argv[7]);
|
954 |
+
int fineness = std::stoi(argv[8]);
|
955 |
+
int theory_grid_points = std::stoi(argv[9]);
|
956 |
+
double theory_tolerance = std::stod(argv[10]);
|
957 |
+
std::string output_file = argv[11];
|
958 |
+
|
959 |
+
if (!fixedBetaEigenvalueAnalysis(n, p, y, beta, a_min, a_max, fineness, theory_grid_points, theory_tolerance, output_file)) {
|
960 |
+
return 1;
|
961 |
+
}
|
962 |
+
|
963 |
} else if (mode == "cubic") {
|
964 |
+
// βββ Cubic equation analysis mode ββββββββββββββββββββββββββββββββββββββββββββββββββ
|
965 |
if (argc != 9) {
|
966 |
std::cerr << "Error: Incorrect number of arguments for cubic mode." << std::endl;
|
967 |
std::cerr << "Usage: " << argv[0] << " cubic <a> <y> <beta> <num_points> <z_min> <z_max> <output_file>" << std::endl;
|
|
|
983 |
|
984 |
} else {
|
985 |
std::cerr << "Error: Unknown mode: " << mode << std::endl;
|
986 |
+
std::cerr << "Use 'eigenvalues', 'eigenvalues_fixed_beta', or 'cubic'" << std::endl;
|
987 |
return 1;
|
988 |
}
|
989 |
}
|