- added extra tests to check on different sized structures
authorAnatoly <Titov_AI@pnpi.nrcki.ru>
Wed, 9 Sep 2020 12:41:58 +0000 (15:41 +0300)
committerAnatoly <Titov_AI@pnpi.nrcki.ru>
Wed, 9 Sep 2020 12:41:58 +0000 (15:41 +0300)
- 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

src/domaintests.cpp
src/newfit.cpp

index 658ad84360821bf96bd2d0909c70099ede5d0aba..af19dcfdf61dd5b47cbd006d7144866648528230 100644 (file)
@@ -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++) {
index 7d2f81d3bd725ce617347dfc7b74a480de41e31f..fa94efcb894b85880366d5e8c7399b245c571bd1 100644 (file)
@@ -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;
                 }
             }
         }