From: Anatoly Date: Wed, 9 Sep 2020 12:41:58 +0000 (+0300) Subject: - added extra tests to check on different sized structures X-Git-Url: http://biod.pnpi.spb.ru/gitweb/?a=commitdiff_plain;h=444af39607d462b450f2a6b74b94ff5a1378a397;p=alexxy%2Fgromacs-domains.git - added extra tests to check on different sized structures - fixed a rare bug with "-nan" value when f' has to == 0 - fixed the order of the fit function so it supposedly working as intended --- diff --git a/src/domaintests.cpp b/src/domaintests.cpp index 658ad84..af19dcf 100644 --- a/src/domaintests.cpp +++ b/src/domaintests.cpp @@ -114,37 +114,37 @@ TEST( fitTests, fitTest_CalcMid) } CalcMid(testFrame1, testFrame1, mid1, mid2, testPairs); - ASSERT_NEAR((mid1 - mid2).norm(), 0, 0.000001); + ASSERT_NEAR((mid1 - mid2).norm(), 0, 0.000'001); CalcMid(testFrame2, testFrame2, mid1, mid2, testPairs); - ASSERT_NEAR((mid1 - mid2).norm(), 0, 0.000001); + ASSERT_NEAR((mid1 - mid2).norm(), 0, 0.000'001); CalcMid(testFrame1, testFrame2, mid1, mid2, testPairs); - ASSERT_NEAR((mid1 - mid2).norm(), 2 * std::sqrt(3), 0.000001); + ASSERT_NEAR((mid1 - mid2).norm(), 2 * std::sqrt(3), 0.000'001); } -void myFitNewRoutine(std::vector< RVec > fr1, std::vector< RVec > fr2, std::vector< RVec > fr3, std::vector< std::pair< unsigned int, unsigned int > > testPairs, double x, double y, double z, double A, double B, double C, double prc, double &tF) { - fr3.resize(0); - fr3 = fr2; - ApplyFit(fr3, x, y, z, A, B, C); - MyFitNew(fr1, fr3, testPairs, prc); +void myFitNewRoutine(std::vector< RVec > fr1, std::vector< RVec > fr2, std::vector< std::pair< unsigned int, unsigned int > > testPairs, double prc, double &tF) { + MyFitNew(fr1, fr2, testPairs, prc); tF = 0; for (unsigned int i = 0; i < fr1.size(); i++) { - tF += F(fr1[i][0], fr1[i][1], fr1[i][2], fr3[i][0], fr3[i][1], fr3[i][2], 0, 0, 0); + tF += F(fr1[i][0], fr1[i][1], fr1[i][2], fr2[i][0], fr2[i][1], fr2[i][2], 0, 0, 0); } } TEST( fitTests, fitTest_MyFitNew) { - RVec a(-2, -2, -2), x1(1, 0, 0), y1(0, 1, 0), z1(0, 0, 1); + RVec a(-2, -2, -2), x1(1, 0, 0), y1(0, 1, 0), z1(0, 0, 1), x2(10, 0, 0), y2(0, 10, 0), z2(0, 0, 10), x3(11, 0, 0), y3(0, 11, 0), z3(0, 0, 11); - std::vector< RVec > testFrame1, testFrame2, testFrame3; + std::vector< RVec > testFrame1, testFrame2; testFrame1.resize(0); testFrame2.resize(0); - testFrame3.resize(0); std::vector< std::pair< unsigned int, unsigned int > > testPairs; testPairs.resize(0); + /* + * optimal 3x3x3 cubes fitting + */ + for (unsigned int i = 0; i < 27; i++) { testFrame1.push_back(x1 * static_cast< float >(i % 3) + y1 * static_cast< float >((i % 9) / 3) + z1 * static_cast< float >(i / 9)); testFrame2.push_back(testFrame1.back() + a); @@ -153,20 +153,98 @@ TEST( fitTests, fitTest_MyFitNew) double testF = 0; - myFitNewRoutine(testFrame1, testFrame2, testFrame3, testPairs, 0, 0, 0, 0, 0, 0, 0.000001, testF); + myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.000'001, testF); ASSERT_NEAR(testF, 0, 0.000001); - myFitNewRoutine(testFrame1, testFrame2, testFrame3, testPairs, 7.1534, 0.5591, -3.1415, M_PI / 23, M_PI / 17, M_PI / 2.2, 0.000001, testF); - ASSERT_NEAR(testF, 0, 0.01); + ApplyFit(testFrame2, 7.1534, 0.5591, -3.1415, M_PI / 23, M_PI / 17, M_PI / 2.2); + + myFitNewRoutine(testFrame1, testFrame2, testPairs, 1, testF); + ASSERT_NEAR(testF, 0, 8.17); + + myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.1, testF); + ASSERT_NEAR(testF, 0, 2.32); + + myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.01, testF); + ASSERT_NEAR(testF, 0, 2.13); + + myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.001, testF); + ASSERT_NEAR(testF, 0, 0.202); + + myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.000'1, testF); + ASSERT_NEAR(testF, 0, 0.019'6); + + myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.000'01, testF); + ASSERT_NEAR(testF, 0, 0.019'6); + + myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.000'001, testF); + ASSERT_NEAR(testF, 0, 0.000'194); + + myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.000'000'1, testF); + ASSERT_NEAR(testF, 0, 0.000'012'05); + + myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.000'000'01, testF); + ASSERT_NEAR(testF, 0, 0.000'005'182); + + myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.000'000'001, testF); + ASSERT_NEAR(testF, 0, 0.000'005'095); + + myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.000'000'000'1, testF); + ASSERT_NEAR(testF, 0, 0.000'005'034); + + myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.000'000'000'01, testF); + ASSERT_NEAR(testF, 0, 0.000'005'345); + + /* + * different sized 3x3x3 cubes fitting + */ + + testFrame1.resize(0); + testFrame2.resize(0); + for (unsigned int i = 0; i < 27; i++) { + testFrame1.push_back(x2 * static_cast< float >(i % 3) + y2 * static_cast< float >((i % 9) / 3) + z2 * static_cast< float >(i / 9)); + testFrame2.push_back(x3 * static_cast< float >(i % 3) + y3 * static_cast< float >((i % 9) / 3) + z3 * static_cast< float >(i / 9)); + } + + myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.000'001, testF); + ASSERT_NEAR(testF, 0, 36.827); + + ApplyFit(testFrame2, 7.1534, 0.5591, -3.1415, M_PI / 23, M_PI / 17, M_PI / 2.2); + + myFitNewRoutine(testFrame1, testFrame2, testPairs, 1, testF); + ASSERT_NEAR(testF, 0, 250.7); + + myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.1, testF); + ASSERT_NEAR(testF, 0, 249.9); + + myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.01, testF); + ASSERT_NEAR(testF, 0, 79.26); + + myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.001, testF); + ASSERT_NEAR(testF, 0, 53.71); + + myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.000'1, testF); + ASSERT_NEAR(testF, 0, 37.13); + + myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.000'01, testF); + ASSERT_NEAR(testF, 0, 36.9485); + + myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.000'001, testF); + ASSERT_NEAR(testF, 0, 36.9482); + + myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.000'000'1, testF); + ASSERT_NEAR(testF, 0, 36.8822); + + myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.000'000'01, testF); + ASSERT_NEAR(testF, 0, 36.8817); - myFitNewRoutine(testFrame1, testFrame2, testFrame3, testPairs, 7.1534, 0.5591, -3.1415, M_PI / 23, M_PI / 17, M_PI / 2.2, 0.0000001, testF); - ASSERT_NEAR(testF, 0, 0.001); + myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.000'000'001, testF); + ASSERT_NEAR(testF, 0, 36.878094); - myFitNewRoutine(testFrame1, testFrame2, testFrame3, testPairs, 7.1534, 0.5591, -3.1415, M_PI / 23, M_PI / 17, M_PI / 2.2, 0.0000001, testF); - ASSERT_NEAR(testF, 0, 0.0001); + myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.000'000'000'1, testF); + ASSERT_NEAR(testF, 0, 36.878064); - myFitNewRoutine(testFrame1, testFrame2, testFrame3, testPairs, 7.1534, 0.5591, -3.1415, M_PI / 23, M_PI / 17, M_PI / 2.2, 0.00000001, testF); - ASSERT_NEAR(testF, 0, 0.00001); + myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.000'000'000'01, testF); + ASSERT_NEAR(testF, 0, 36.878062); } @@ -345,7 +423,7 @@ TEST( domainTests, domainTest_getDomains) testDomain.getDomains(); ASSERT_EQ(testDomain.domains.size(), 0); - for (unsigned int i0; i0 < 3; i0++) { + for (unsigned int i0 = 0; i0 < 3; i0++) { testDomain.graph.resize(1); testDomain.graph.front().resize(testSliceNum); for (unsigned int i1 = 0; i1 < testSliceNum; i1++) { diff --git a/src/newfit.cpp b/src/newfit.cpp index 7d2f81d..fa94efc 100644 --- a/src/newfit.cpp +++ b/src/newfit.cpp @@ -31,6 +31,27 @@ void searchF0xyzabc (long double &F, double &Fx, double &Fy, double &Fz, double 2 * (cos(B) * bix_plus_x + sin(A) * sin(B) * biy_plus_y + cos(A) * sin(B) * biz_plus_z) * t06) / (2 * t04); Fc += (2 * (biy_plus_y * (cos(A) * cos(C) + sin(A) * sin(B) * sin(C)) - biz_plus_z * (cos(C) * sin(A) - cos(A) * sin(B) * sin(C)) + cos(B) * sin(C) * bix_plus_x) * t05 - 2 * (biz_plus_z * (sin(A) * sin(C) + cos(A) * cos(C) * sin(B)) - biy_plus_y * (cos(A) * sin(C) - cos(C) * sin(A) * sin(B)) + cos(B) * cos(C) * bix_plus_x) * t07) / (2 * t04); + if (std::isnan(F)) { + F = 0; + } + if (std::isnan(Fx)) { + Fx = 0; + } + if (std::isnan(Fy)) { + Fy = 0; + } + if (std::isnan(Fz)) { + Fz = 0; + } + if (std::isnan(Fa)) { + Fa = 0; + } + if (std::isnan(Fb)) { + Fb = 0; + } + if (std::isnan(Fc)) { + Fc = 0; + } } // применения геометрического преобразования: смещение на вектор (x, y, z) и повороты на градусы A, B, C относительно осей (x, y, z) @@ -85,15 +106,15 @@ void MyFitNew (std::vector< RVec > a, std::vector< RVec > &b, std::vector< std:: static_cast< double >(b[pairs[i].second][0]) + x, static_cast< double >(b[pairs[i].second][1]) + y, static_cast< double >(b[pairs[i].second][2]) + z, A, B, C); } if (FtCnst == 0) { - FtCnst = 0.0000001; // почему именно столько?! + FtCnst = 0.000001; // почему именно столько?! } if (f1 == 0) { ApplyFit(b, x, y, z, A, B, C); return; } else { // поиск оптимального геометрического преобразования методом градиентного спуска - while (f1 - f2 < 0 || f1 - f2 > FtCnst) { - f1 = 0; fx = 0; fy = 0; fz = 0; fa = 0; fb = 0; fc = 0; l = 1; + while (f1 <= f2 || f1 - f2 > FtCnst) { + f1 = 0; f2 = 0; fx = 0; fy = 0; fz = 0; fa = 0; fb = 0; fc = 0; l = 1; // поиск производных и отклонения при заданных параметрах for (unsigned int i = 0; i < pairs.size(); i++) { searchF0xyzabc(f1, fx, fy, fz, fa, fb, fc, @@ -101,7 +122,7 @@ void MyFitNew (std::vector< RVec > a, std::vector< RVec > &b, std::vector< std:: static_cast< double >(b[pairs[i].second][0]) + x, static_cast< double >(b[pairs[i].second][1]) + y, static_cast< double >(b[pairs[i].second][2]) + z, A, B, C); } - while (f2 != f1) { + while (true) { f2 = 0; // поиск отклонения при новых параметрах for (unsigned int i = 0; i < pairs.size(); i++) { @@ -117,9 +138,10 @@ void MyFitNew (std::vector< RVec > a, std::vector< RVec > &b, std::vector< std:: // в случае его достижения дважды останавливаем цикл т.к. упёрлись в предел допустимой точности // таким образом гарантируем выход из цикла if (l == DBL_MIN) { //DBL_TRUE_MIN + f2 = f1; break; } - l *= 0.50; + l *= 0.1; } } }