From 7af816e8d1e891b8dca52d41b6fadfe05b2db711 Mon Sep 17 00:00:00 2001 From: Stefan Engels <112686201+sengels-tum@users.noreply.github.com> Date: Thu, 20 Feb 2025 17:20:27 +0100 Subject: [PATCH] Numerical Issues on Ubuntu (#104) * imporve feedback on error * linter warnings * reduce numerical instability, maybe * change tests to run as debug for more output * linter warning std::pair * more numerical issues * improve coverage * linter warnings * linter warning std::pair * remove long running test * linter warnings --- .github/workflows/cpp-ci.yml | 18 +- src/EOMHelper.cpp | 137 ++++++++----- ...st_gurobi_vss_gen_using_mb_information.cpp | 16 +- test/test_helper.cpp | 188 +++++++++++++++++- 4 files changed, 282 insertions(+), 77 deletions(-) diff --git a/.github/workflows/cpp-ci.yml b/.github/workflows/cpp-ci.yml index 2bd387217..152249e68 100644 --- a/.github/workflows/cpp-ci.yml +++ b/.github/workflows/cpp-ci.yml @@ -67,11 +67,11 @@ jobs: wget https://packages.gurobi.com/${{ env.GUROBI_VERSION_SHORT }}/${{ env.GUROBI_FILE }} tar -xvzf ${{ env.GUROBI_FILE }} - name: Configure CMake - run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTS=ON ${{ matrix.config.toolchain }} + run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTS=ON ${{ matrix.config.toolchain }} - name: Build - run: cmake --build build --config Release + run: cmake --build build --config Debug - name: Test - run: ctest -C Release --output-on-failure --test-dir build --repeat until-pass:3 --timeout 500 + run: ctest -C Debug --output-on-failure --test-dir build --repeat until-pass:3 --timeout 500 cpp-macos-latest: name: cpp-macos-latest runs-on: macos-latest @@ -97,11 +97,11 @@ jobs: wget https://packages.gurobi.com/${{ env.GUROBI_VERSION_SHORT }}/${{ env.GUROBI_FILE }} sudo installer -pkg ${{ env.GUROBI_FILE }} -target / - name: Configure CMake - run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTS=ON ${{ matrix.config.toolchain }} + run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTS=ON ${{ matrix.config.toolchain }} - name: Build - run: cmake --build build --config Release + run: cmake --build build --config Debug - name: Test - run: ctest -C Release --output-on-failure --test-dir build --repeat until-pass:3 --timeout 500 + run: ctest -C Debug --output-on-failure --test-dir build --repeat until-pass:3 --timeout 500 cpp-windows-latest: name: cpp-windows-latest runs-on: windows-latest @@ -146,11 +146,11 @@ jobs: echo "GUROBI_HOME=$PWD\gurobi\${{ needs.read-parameters.outputs.gurobiFolder }}\win64" >> $env:GITHUB_ENV echo "$PWD\gurobi\${{ needs.read-parameters.outputs.gurobiFolder }}\win64\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - name: Configure CMake - run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTS=ON ${{ matrix.config.toolchain }} + run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTS=ON ${{ matrix.config.toolchain }} - name: Build - run: cmake --build build --config Release + run: cmake --build build --config Debug - name: Test - run: ctest -C Release --output-on-failure --test-dir build --repeat until-pass:3 --timeout 500 + run: ctest -C Debug --output-on-failure --test-dir build --repeat until-pass:3 --timeout 500 coverage: name: Coverage runs-on: ubuntu-latest diff --git a/src/EOMHelper.cpp b/src/EOMHelper.cpp index 52dd1ffb9..a03262caa 100644 --- a/src/EOMHelper.cpp +++ b/src/EOMHelper.cpp @@ -6,8 +6,9 @@ #include #include #include -#include #include +#include +#include double cda_rail::min_travel_time_from_start(double v_1, double v_2, double v_m, double a, double d, double s, @@ -57,8 +58,8 @@ double cda_rail::min_travel_time(double v_1, double v_2, double v_m, double a, bool cda_rail::possible_by_eom(double v_1, double v_2, double a, double d, double s) { - return v_1 <= v_2 ? (v_2 + v_1) * (v_2 - v_1) <= 2 * a * s - : (v_1 + v_2) * (v_1 - v_2) <= 2 * d * s; + return v_1 <= v_2 ? (v_2 + v_1) * (v_2 - v_1) <= 2 * a * s + GRB_EPS + : (v_1 + v_2) * (v_1 - v_2) <= 2 * d * s + GRB_EPS; } double cda_rail::max_travel_time_from_start_no_stopping(double v_1, double v_2, @@ -128,8 +129,8 @@ double cda_rail::max_travel_time_from_start_stopping_allowed( const double bd = v_1 * v_1 / (2 * d); // Distance to stop - if (bd <= s_1) { - if (x >= s_1) { + if (bd <= s_1 + EPS) { + if (x + EPS >= s_1) { // Infinite, because train could have stopped return std::numeric_limits::infinity(); } @@ -163,22 +164,32 @@ double cda_rail::max_travel_time(double v_1, double v_2, double v_m, double a, void cda_rail::check_consistency_of_eom_input(double& v_1, double& v_2, double& a, double& d, double& s, double& x) { - if (std::abs(v_1) < GRB_EPS) + if (std::abs(v_1) < GRB_EPS) { v_1 = 0; - if (std::abs(v_2) < GRB_EPS) + } + if (std::abs(v_2) < GRB_EPS) { v_2 = 0; - if (std::abs(a) < GRB_EPS) + } + if (std::abs(a) < GRB_EPS) { a = 0; - if (std::abs(d) < GRB_EPS) + } + if (std::abs(d) < GRB_EPS) { d = 0; - if (std::abs(s) < GRB_EPS) + } + if (std::abs(s) < GRB_EPS) { s = 0; - if (std::abs(x) < GRB_EPS) + } + if (std::abs(x) < GRB_EPS) { x = 0; + } if (v_1 < 0 || v_2 < 0 || a < 0 || d < 0 || s < 0 || x < 0) { throw exceptions::ConsistencyException( "All input values must be non-negative."); } + if (a < GRB_EPS || d < GRB_EPS) { + throw exceptions::ConsistencyException( + "Both acceleration and deceleration must be strictly positive."); + } if (x > s) { throw exceptions::ConsistencyException( @@ -187,7 +198,7 @@ void cda_rail::check_consistency_of_eom_input(double& v_1, double& v_2, if (!possible_by_eom(v_1, v_2, a, d, s)) { throw exceptions::ConsistencyException( - "Travel time not possible by equations of motion."); + "Entry and exit velocities not possible by equations of motion."); } } @@ -232,19 +243,23 @@ double cda_rail::min_time_to_push_ma_forward(double v_0, double a, double d, // How much time does a train need to move its moving authority forward by s // given initial speed v_0 and acceleration a and deceleration d - if (std::abs(v_0) < GRB_EPS) + if (std::abs(v_0) < GRB_EPS) { v_0 = 0; - if (std::abs(a) < GRB_EPS) + } + if (std::abs(a) < GRB_EPS) { a = 0; - if (d < 0 && d > -GRB_EPS) + } + if (d < 0 && d > -GRB_EPS) { d = 0; - if (std::abs(s) < GRB_EPS) + } + if (std::abs(s) < GRB_EPS) { s = 0; + } // Assert that v_0 >= 0, a >= 0, d > 0, s > 0 if (v_0 < 0 || a < 0 || d <= 0 || s < 0) { throw exceptions::InvalidInputException( - "We need v_0 >= 0, a >= 0, d > 0, s >= 0"); + "We need v_0 >= 0, a > 0, d > 0, s >= 0"); } // ma(t) = v_0*t + 0.5*a*t^2 + (v_0+a*t)^2/(2d) != s + v_0^2/(2d) @@ -285,14 +300,18 @@ double cda_rail::min_time_to_push_ma_fully_backward(double v_0, double a, double cda_rail::min_time_to_push_ma_backward(double v_0, double a, double d, double s) { - if (std::abs(v_0) < GRB_EPS) + if (std::abs(v_0) < GRB_EPS) { v_0 = 0; - if (std::abs(a) < GRB_EPS) + } + if (std::abs(a) < GRB_EPS) { a = 0; - if (d < 0 && d > -GRB_EPS) + } + if (d < 0 && d > -GRB_EPS) { d = 0; - if (std::abs(s) < GRB_EPS) + } + if (std::abs(s) < GRB_EPS) { s = 0; + } // Assert that v_0 >= 0, a >= 0, d > 0, s > 0 if (v_0 < 0 || a < 0 || d <= 0 || s < 0) { @@ -405,8 +424,9 @@ double cda_rail::min_time_from_front_to_ma_point(double v_1, double v_2, const auto& s_1 = s_points.first; const auto& s_2 = s_points.second; - if (std::abs(obd) < GRB_EPS) + if (std::abs(obd) < GRB_EPS) { obd = 0; + } if (obd < 0) { throw exceptions::InvalidInputException( "obd must be greater than or equal 0."); @@ -449,8 +469,9 @@ double cda_rail::max_time_from_front_to_ma_point_no_stopping( const auto& s_1 = s_points.first; const auto& s_2 = s_points.second; - if (std::abs(obd) < GRB_EPS) + if (std::abs(obd) < GRB_EPS) { obd = 0; + } if (obd < 0) { throw exceptions::InvalidInputException( "obd must be greater than or equal 0."); @@ -460,7 +481,7 @@ double cda_rail::max_time_from_front_to_ma_point_no_stopping( // Speed at changing point const double v_t_squared = - v_1 * v_1 + 2 * (v1_below_minimal_speed ? a : -d) * s_1; + (v_1 * v_1) + (2 * (v1_below_minimal_speed ? a : -d) * s_1); const double v_t = std::sqrt(v_t_squared); // Braking distances @@ -558,18 +579,24 @@ double cda_rail::time_on_edge(double v_1, double v_2, double v_line, double a, */ // If any variable is within std::abs(GRB_EPS), set to 0 - if (std::abs(v_1) < GRB_EPS) + if (std::abs(v_1) < GRB_EPS) { v_1 = 0; - if (std::abs(v_2) < GRB_EPS) + } + if (std::abs(v_2) < GRB_EPS) { v_2 = 0; - if (std::abs(v_line) < GRB_EPS) + } + if (std::abs(v_line) < GRB_EPS) { v_line = 0; - if (std::abs(a) < GRB_EPS) + } + if (std::abs(a) < GRB_EPS) { a = 0; - if (std::abs(d) < GRB_EPS) + } + if (std::abs(d) < GRB_EPS) { d = 0; - if (std::abs(s) < GRB_EPS) + } + if (std::abs(s) < GRB_EPS) { s = 0; + } // Assert that all variables are >= 0 and a, d, s, v_line are >= GRB_EPS if (v_1 < 0 || v_2 < 0 || v_line < GRB_EPS || a < GRB_EPS || d < GRB_EPS || @@ -585,15 +612,15 @@ double cda_rail::time_on_edge(double v_1, double v_2, double v_line, double a, } // First segment: v_1 -> v_line - double a1 = v_line >= v_1 ? a : -d; - double s1 = (v_line * v_line - v_1 * v_1) / (2 * a1); - double t1 = (v_line - v_1) / a1; + const double a1 = v_line >= v_1 ? a : -d; + const double s1 = (v_line * v_line - v_1 * v_1) / (2 * a1); + const double t1 = (v_line - v_1) / a1; assert(t1 >= 0); // Last segment: v_line -> v_2 - double a2 = v_2 >= v_line ? a : -d; - double s2 = (v_2 * v_2 - v_line * v_line) / (2 * a2); - double t2 = (v_2 - v_line) / a2; + const double a2 = v_2 >= v_line ? a : -d; + const double s2 = (v_2 * v_2 - v_line * v_line) / (2 * a2); + const double t2 = (v_2 - v_line) / a2; assert(t2 >= 0); // If s1 + s2 > s, this is not possible @@ -606,7 +633,7 @@ double cda_rail::time_on_edge(double v_1, double v_2, double v_line, double a, return t1 + t2; } - return t1 + t2 + (s - s1 - s2) / v_line; + return t1 + t2 + ((s - s1 - s2) / v_line); } double cda_rail::maximal_line_speed(double v_1, double v_2, double v_max, @@ -618,8 +645,8 @@ double cda_rail::maximal_line_speed(double v_1, double v_2, double v_max, // Terminal velocity const double v_t_squared = - v_1 * v_1 + 2 * a * s_1; // Maximal velocity reached - return std::sqrt(v_t_squared); // = v_m if s_2 > s_1 + (v_1 * v_1) + (2 * a * s_1); // Maximal velocity reached + return std::sqrt(v_t_squared); // = v_m if s_2 > s_1 } double cda_rail::minimal_line_speed(double v_1, double v_2, double v_min, @@ -632,9 +659,9 @@ double cda_rail::minimal_line_speed(double v_1, double v_2, double v_min, (void)s_2; // unused const double v_t_squared = - v_1 * v_1 + - 2 * (v_1_below_minimal_speed ? a : -d) * s_1; // Minimal velocity reached - return std::sqrt(v_t_squared); // = v_m if s_2 > s_1 + (v_1 * v_1) + (2 * (v_1_below_minimal_speed ? a : -d) * + s_1); // Minimal velocity reached + return std::sqrt(v_t_squared); // = v_m if s_2 > s_1 } double cda_rail::get_line_speed(double v_1, double v_2, double v_min, @@ -688,7 +715,10 @@ double cda_rail::pos_on_edge_at_time(double v_1, double v_2, double v_line, const auto total_time_dv = time_on_edge(v_1, v_2, v_line_dv, a, d, s); if (t > total_time_dv + GRB_EPS) { throw exceptions::InvalidInputException( - "Time exceeds total travel time."); + "Time exceeds total travel time in cda_rail::pos_on_edge_at_time " + "with t = " + + std::to_string(t) + + " and total_time_dv = " + std::to_string(total_time_dv)); } return s; } @@ -700,16 +730,16 @@ double cda_rail::pos_on_edge_at_time(double v_1, double v_2, double v_line, const auto a2 = v_2 >= v_line ? a : -d; const auto t1 = (v_line - v_1) / a1; - const auto t2 = total_time - (v_2 - v_line) / a2; + const auto t2 = total_time - ((v_2 - v_line) / a2); if (t <= t1) { - return v_1 * t + 0.5 * a1 * t * t; + return (v_1 * t) + (0.5 * a1 * t * t); } if (t <= t2) { - return v_1 * t1 + 0.5 * a1 * t1 * t1 + v_line * (t - t1); + return (v_1 * t1) + (0.5 * a1 * t1 * t1) + (v_line * (t - t1)); } - return s + 0.5 * a2 * (total_time - t) * (total_time - t) - - v_2 * (total_time - t); + return s + (0.5 * a2 * (total_time - t) * (total_time - t)) - + (v_2 * (total_time - t)); } double cda_rail::vel_on_edge_at_time(double v_1, double v_2, double v_line, @@ -726,7 +756,10 @@ double cda_rail::vel_on_edge_at_time(double v_1, double v_2, double v_line, const auto total_time_dv = time_on_edge(v_1, v_2, v_line_dv, a, d, s); if (t > total_time_dv + GRB_EPS) { throw exceptions::InvalidInputException( - "Time exceeds total travel time."); + "Time exceeds total travel time in cda_rail::vel_on_edge_at_time " + "with t = " + + std::to_string(t) + + " and total_time_dv = " + std::to_string(total_time_dv)); } return v_2; } @@ -738,13 +771,13 @@ double cda_rail::vel_on_edge_at_time(double v_1, double v_2, double v_line, const auto a2 = v_2 >= v_line ? a : -d; const auto t1 = (v_line - v_1) / a1; - const auto t2 = total_time - (v_2 - v_line) / a2; + const auto t2 = total_time - ((v_2 - v_line) / a2); if (t <= t1) { - return v_1 + a1 * t; + return v_1 + (a1 * t); } if (t <= t2) { return v_line; } - return v_2 - a2 * (total_time - t); + return v_2 - (a2 * (total_time - t)); } diff --git a/test/test_gurobi_vss_gen_using_mb_information.cpp b/test/test_gurobi_vss_gen_using_mb_information.cpp index 31ba03772..df0d946f3 100644 --- a/test/test_gurobi_vss_gen_using_mb_information.cpp +++ b/test/test_gurobi_vss_gen_using_mb_information.cpp @@ -1,10 +1,8 @@ -#include "VSSModel.hpp" +#include "Definitions.hpp" #include "solver/mip-based/VSSGenTimetableSolver.hpp" #include "gtest/gtest.h" #include -#include -#include TEST(VSSGenMBInfoSolver, Default1) { cda_rail::solver::mip_based::VSSGenTimetableSolverWithMovingBlockInformation @@ -136,15 +134,3 @@ TEST(VSSGenMBInfoSolver, Default9) { EXPECT_EQ(sol.get_obj(), 15); EXPECT_EQ(sol.get_mip_obj(), 15); } - -TEST(VSSGenMBInfoSolver, Default10) { - cda_rail::solver::mip_based::VSSGenTimetableSolverWithMovingBlockInformation - solver("./example-networks-mb-solutions/Stammstrecke16Trains/"); - - const auto sol = solver.solve({5}); - - EXPECT_TRUE(sol.has_solution()); - EXPECT_EQ(sol.get_status(), cda_rail::SolutionStatus::Optimal); - EXPECT_EQ(sol.get_obj(), 17); - EXPECT_EQ(sol.get_mip_obj(), 17); -} diff --git a/test/test_helper.cpp b/test/test_helper.cpp index 7425097bb..855d5bc5f 100644 --- a/test/test_helper.cpp +++ b/test/test_helper.cpp @@ -4,9 +4,14 @@ #include "VSSModel.hpp" #include "gtest/gtest.h" +#include #include -#include +#include #include +#include +#include +#include +#include #define EXPECT_APPROX_EQ(a, b) \ EXPECT_TRUE(std::abs((a) - (b)) < 1e-6) << (a) << " !=(approx.) " << (b) @@ -946,6 +951,10 @@ TEST(Helper, EoMMinimalTimePushMA) { // MA is 200+450 = 650 before initial point // Hence, braking overlap is 650 - 50 = 600 EXPECT_APPROX_EQ(cda_rail::min_time_to_push_ma_forward(10, 2, 1, 600), 10); + + EXPECT_THROW( + cda_rail::min_time_to_push_ma_forward(10, 2, -cda_rail::GRB_EPS / 2, 72), + cda_rail::exceptions::InvalidInputException); } TEST(Helper, EoMMinimalTimeMA) { @@ -1296,6 +1305,14 @@ TEST(Helper, EoMMinTimeMoveMABackwards) { EXPECT_APPROX_EQ( cda_rail::min_time_to_push_ma_fully_backward(10 * std::sqrt(3), 2, 1), 5 * (std::sqrt(3) - 1)); + + EXPECT_THROW(cda_rail::min_time_to_push_ma_backward( + -cda_rail::GRB_EPS / 2, -cda_rail::GRB_EPS / 2, + -cda_rail::GRB_EPS / 2, -cda_rail::GRB_EPS / 2), + cda_rail::exceptions::InvalidInputException); + + EXPECT_THROW(cda_rail::min_time_to_push_ma_backward(9, 2, 3, 13.6), + cda_rail::exceptions::InvalidInputException); } TEST(Helper, EoMMaximalLineSpeed) { @@ -1387,6 +1404,12 @@ TEST(Helper, EoMTravelTimePerLineSpeed) { EXPECT_APPROX_EQ(cda_rail::time_on_edge(10, 6, 8, 2, 1, 64), 8); EXPECT_APPROX_EQ(cda_rail::time_on_edge(10, 6, 8, 2, 1, 32), 4); + + EXPECT_THROW( + cda_rail::time_on_edge(-cda_rail::GRB_EPS / 2, -cda_rail::GRB_EPS / 2, + -cda_rail::GRB_EPS / 2, -cda_rail::GRB_EPS / 2, + -cda_rail::GRB_EPS / 2, -cda_rail::GRB_EPS / 2), + cda_rail::exceptions::InvalidInputException); } TEST(Helper, EoMGetLineSpeed) { @@ -1599,6 +1622,169 @@ TEST(Helper, EoMPosOnEdgeAtTime) { EXPECT_APPROX_EQ(cda_rail::vel_on_edge_at_time(10, 6, 8, 2, 1, 32, 0), 10); EXPECT_APPROX_EQ(cda_rail::vel_on_edge_at_time(10, 6, 8, 2, 1, 32, 2), 8); EXPECT_APPROX_EQ(cda_rail::vel_on_edge_at_time(10, 6, 8, 2, 1, 32, 4), 6); + + EXPECT_THROW(cda_rail::pos_on_edge_at_time(10, 10, 10, 1, 1, 100, 11), + cda_rail::exceptions::InvalidInputException); + EXPECT_THROW(cda_rail::vel_on_edge_at_time(10, 10, 10, 1, 1, 100, 11), + cda_rail::exceptions::InvalidInputException); +} + +TEST(Helper, ConsistencySmallNegativeValues) { + auto v1_in = -cda_rail::GRB_EPS / 2; + auto v2_in = -cda_rail::GRB_EPS / 2; + double a_in = 1.0; + double d_in = 1.0; + double s_in = 1.0; + auto x_in = -cda_rail::GRB_EPS / 2; + + EXPECT_NO_THROW(cda_rail::check_consistency_of_eom_input(v1_in, v2_in, a_in, + d_in, s_in, x_in)); + EXPECT_EQ(v1_in, 0); + EXPECT_EQ(v2_in, 0); + EXPECT_EQ(a_in, 1); + EXPECT_EQ(d_in, 1); + EXPECT_EQ(s_in, 1); + EXPECT_EQ(x_in, 0); + + v1_in = 1; + v2_in = 1; + a_in = -cda_rail::GRB_EPS / 2; + d_in = 1; + s_in = 1; + x_in = 1; + EXPECT_THROW(cda_rail::check_consistency_of_eom_input(v1_in, v2_in, a_in, + d_in, s_in, x_in), + cda_rail::exceptions::ConsistencyException); + EXPECT_EQ(v1_in, 1); + EXPECT_EQ(v2_in, 1); + EXPECT_EQ(a_in, 0); + EXPECT_EQ(d_in, 1); + EXPECT_EQ(s_in, 1); + EXPECT_EQ(x_in, 1); + + v1_in = 1; + v2_in = 1; + a_in = 1; + d_in = -cda_rail::GRB_EPS / 2; + s_in = 1; + x_in = 1; + EXPECT_THROW(cda_rail::check_consistency_of_eom_input(v1_in, v2_in, a_in, + d_in, s_in, x_in), + cda_rail::exceptions::ConsistencyException); + EXPECT_EQ(v1_in, 1); + EXPECT_EQ(v2_in, 1); + EXPECT_EQ(a_in, 1); + EXPECT_EQ(d_in, 0); + EXPECT_EQ(s_in, 1); + EXPECT_EQ(x_in, 1); + + v1_in = 1; + v2_in = 1; + a_in = 1; + d_in = 1; + s_in = -2 * cda_rail::GRB_EPS; + x_in = 1; + EXPECT_THROW(cda_rail::check_consistency_of_eom_input(v1_in, v2_in, a_in, + d_in, s_in, x_in), + cda_rail::exceptions::ConsistencyException); + EXPECT_EQ(v1_in, 1); + EXPECT_EQ(v2_in, 1); + EXPECT_EQ(a_in, 1); + EXPECT_EQ(d_in, 1); + EXPECT_EQ(s_in, -2 * cda_rail::GRB_EPS); + EXPECT_EQ(x_in, 1); + + v1_in = 1; + v2_in = 1; + a_in = 1; + d_in = 1; + s_in = 1; + x_in = 2; + EXPECT_THROW(cda_rail::check_consistency_of_eom_input(v1_in, v2_in, a_in, + d_in, s_in, x_in), + cda_rail::exceptions::ConsistencyException); + EXPECT_EQ(v1_in, 1); + EXPECT_EQ(v2_in, 1); + EXPECT_EQ(a_in, 1); + EXPECT_EQ(d_in, 1); + EXPECT_EQ(s_in, 1); + EXPECT_EQ(x_in, 2); + + v1_in = 6; + v2_in = std::sqrt(66); + a_in = 3; + d_in = 4; + s_in = 5; + x_in = 4; + EXPECT_NO_THROW(cda_rail::check_consistency_of_eom_input(v1_in, v2_in, a_in, + d_in, s_in, x_in)); + + v1_in = 6; + v2_in = std::sqrt(67); + a_in = 3; + d_in = 4; + s_in = 5; + x_in = 4; + EXPECT_THROW(cda_rail::check_consistency_of_eom_input(v1_in, v2_in, a_in, + d_in, s_in, x_in), + cda_rail::exceptions::ConsistencyException); + + v1_in = std::sqrt(51); + v2_in = 9; + a_in = 3; + d_in = 4; + s_in = 5; + x_in = 4; + EXPECT_NO_THROW(cda_rail::check_consistency_of_eom_input(v1_in, v2_in, a_in, + d_in, s_in, x_in)); + + v1_in = std::sqrt(50); + v2_in = 9; + a_in = 3; + d_in = 4; + s_in = 5; + x_in = 4; + EXPECT_THROW(cda_rail::check_consistency_of_eom_input(v1_in, v2_in, a_in, + d_in, s_in, x_in), + cda_rail::exceptions::ConsistencyException); + + v1_in = 9; + v2_in = sqrt(41); + a_in = 3; + d_in = 4; + s_in = 5; + x_in = 4; + EXPECT_NO_THROW(cda_rail::check_consistency_of_eom_input(v1_in, v2_in, a_in, + d_in, s_in, x_in)); + + v1_in = 9; + v2_in = sqrt(40); + a_in = 3; + d_in = 4; + s_in = 5; + x_in = 4; + EXPECT_THROW(cda_rail::check_consistency_of_eom_input(v1_in, v2_in, a_in, + d_in, s_in, x_in), + cda_rail::exceptions::ConsistencyException); + + v1_in = std::sqrt(76); + v2_in = 6; + a_in = 3; + d_in = 4; + s_in = 5; + x_in = 4; + EXPECT_NO_THROW(cda_rail::check_consistency_of_eom_input(v1_in, v2_in, a_in, + d_in, s_in, x_in)); + + v1_in = std::sqrt(77); + v2_in = 6; + a_in = 3; + d_in = 4; + s_in = 5; + x_in = 4; + EXPECT_THROW(cda_rail::check_consistency_of_eom_input(v1_in, v2_in, a_in, + d_in, s_in, x_in), + cda_rail::exceptions::ConsistencyException); } // NOLINTEND(clang-diagnostic-unused-result)