Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Numerical Issues on Ubuntu #104

Merged
merged 11 commits into from
Feb 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions .github/workflows/cpp-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
137 changes: 85 additions & 52 deletions src/EOMHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
#include <algorithm>
#include <cassert>
#include <cmath>
#include <iostream>
#include <limits>
#include <string>
#include <utility>

double cda_rail::min_travel_time_from_start(double v_1, double v_2, double v_m,
double a, double d, double s,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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<double>::infinity();
}
Expand Down Expand Up @@ -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(
Expand All @@ -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.");
}
}

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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.");
Expand Down Expand Up @@ -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.");
Expand All @@ -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
Expand Down Expand Up @@ -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 ||
Expand All @@ -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
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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;
}
Expand All @@ -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,
Expand All @@ -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;
}
Expand All @@ -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));
}
16 changes: 1 addition & 15 deletions test/test_gurobi_vss_gen_using_mb_information.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
#include "VSSModel.hpp"
#include "Definitions.hpp"
#include "solver/mip-based/VSSGenTimetableSolver.hpp"

#include "gtest/gtest.h"
#include <filesystem>
#include <iostream>
#include <string>

TEST(VSSGenMBInfoSolver, Default1) {
cda_rail::solver::mip_based::VSSGenTimetableSolverWithMovingBlockInformation
Expand Down Expand Up @@ -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);
}
Loading
Loading