Skip to content

Commit

Permalink
feat: stable algorithm with new removeIntersection(with proper edge i…
Browse files Browse the repository at this point in the history
…ntersection checks)
  • Loading branch information
Akhil-CM committed Apr 27, 2024
1 parent de806e4 commit cc6a066
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 69 deletions.
34 changes: 17 additions & 17 deletions DiscreteENN_TSP_table.csv
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
name points error time(us) time per city(us) distance optimal_distance
berlin52,52,9.770000,201.000000,3.870000,8278.690430,7542.000000
st70,70,7.260000,549.000000,7.840000,724.020020,675.000000
eil76,76,6.760000,754.000000,9.920000,574.369995,538.000000
pr76,76,2.510000,755.000000,9.930000,110878.648438,108159.000000
kroA100,100,8.680000,1340.000000,13.400000,23130.140625,21282.000000
kroC100,100,6.870000,1659.000000,16.590000,22175.039062,20749.000000
kroD100,100,3.990000,1500.000000,15.000000,22143.890625,21294.000000
rd100,100,7.710000,1307.000000,13.070000,8519.610352,7910.000000
eil101,101,4.850000,1537.000000,15.220000,659.510010,629.000000
lin105,105,5.330000,1467.000000,13.970000,15146.040039,14379.000000
ch130,130,4.010000,3202.000000,24.629999,6354.850098,6110.000000
ch150,150,3.550000,4451.000000,29.670000,6759.560059,6528.000000
tsp225,225,4.660000,15097.000000,67.099998,4098.439941,3916.000000
a280,280,7.820000,34735.000000,124.050003,2780.639893,2579.000000
pcb442,442,9.480000,126049.000000,285.179993,55593.058594,50778.000000
pr1002,1002,6.740000,1480617.875000,1477.660034,276490.656250,259045.000000
pr2392,2392,10.330000,25431628.000000,10631.950195,417093.625000,378032.000000
berlin52,52,1.580000,255.000000,4.900000,7661.009766,7542.000000
st70,70,2.170000,661.000000,9.440000,689.640015,675.000000
eil76,76,4.850000,741.000000,9.750000,564.099976,538.000000
pr76,76,2.490000,1051.000000,13.830000,110850.609375,108159.000000
kroA100,100,3.750000,1695.000000,16.950001,22080.689453,21282.000000
kroC100,100,3.170000,1591.000000,15.910000,21405.820312,20749.000000
kroD100,100,6.780000,1609.000000,16.090000,22737.619141,21294.000000
rd100,100,8.360000,1675.000000,16.750000,8571.240234,7910.000000
eil101,101,6.060000,2053.000000,20.330000,667.119995,629.000000
lin105,105,6.090000,1564.000000,14.900000,15254.559570,14379.000000
ch130,130,7.320000,3135.000000,24.120001,6557.279785,6110.000000
ch150,150,4.270000,6040.000000,40.270000,6806.850098,6528.000000
tsp225,225,4.060000,18750.000000,83.330002,4074.899902,3916.000000
a280,280,7.400000,32272.000000,115.260002,2769.820068,2579.000000
pcb442,442,10.520000,137540.984375,311.179993,56120.769531,50778.000000
pr1002,1002,7.580000,1523460.000000,1520.420044,278676.968750,259045.000000
pr2392,2392,10.000000,32860496.000000,13737.669922,415825.000000,378032.000000
34 changes: 17 additions & 17 deletions DiscreteENN_TSP_table.txt
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
name points error time(us) time per city(us) distance optimal_distance
berlin52 52 9.770000 201.000000 3.870000 8278.690430 7542.000000
st70 70 7.260000 549.000000 7.840000 724.020020 675.000000
eil76 76 6.760000 754.000000 9.920000 574.369995 538.000000
pr76 76 2.510000 755.000000 9.930000 110878.648438 108159.000000
kroA100 100 8.680000 1340.000000 13.400000 23130.140625 21282.000000
kroC100 100 6.870000 1659.000000 16.590000 22175.039062 20749.000000
kroD100 100 3.990000 1500.000000 15.000000 22143.890625 21294.000000
rd100 100 7.710000 1307.000000 13.070000 8519.610352 7910.000000
eil101 101 4.850000 1537.000000 15.220000 659.510010 629.000000
lin105 105 5.330000 1467.000000 13.970000 15146.040039 14379.000000
ch130 130 4.010000 3202.000000 24.629999 6354.850098 6110.000000
ch150 150 3.550000 4451.000000 29.670000 6759.560059 6528.000000
tsp225 225 4.660000 15097.000000 67.099998 4098.439941 3916.000000
a280 280 7.820000 34735.000000 124.050003 2780.639893 2579.000000
pcb442 442 9.480000 126049.000000 285.179993 55593.058594 50778.000000
pr1002 1002 6.740000 1480617.875000 1477.660034 276490.656250 259045.000000
pr2392 2392 10.330000 25431628.000000 10631.950195 417093.625000 378032.000000
berlin52 52 1.580000 255.000000 4.900000 7661.009766 7542.000000
st70 70 2.170000 661.000000 9.440000 689.640015 675.000000
eil76 76 4.850000 741.000000 9.750000 564.099976 538.000000
pr76 76 2.490000 1051.000000 13.830000 110850.609375 108159.000000
kroA100 100 3.750000 1695.000000 16.950001 22080.689453 21282.000000
kroC100 100 3.170000 1591.000000 15.910000 21405.820312 20749.000000
kroD100 100 6.780000 1609.000000 16.090000 22737.619141 21294.000000
rd100 100 8.360000 1675.000000 16.750000 8571.240234 7910.000000
eil101 101 6.060000 2053.000000 20.330000 667.119995 629.000000
lin105 105 6.090000 1564.000000 14.900000 15254.559570 14379.000000
ch130 130 7.320000 3135.000000 24.120001 6557.279785 6110.000000
ch150 150 4.270000 6040.000000 40.270000 6806.850098 6528.000000
tsp225 225 4.060000 18750.000000 83.330002 4074.899902 3916.000000
a280 280 7.400000 32272.000000 115.260002 2769.820068 2579.000000
pcb442 442 10.520000 137540.984375 311.179993 56120.769531 50778.000000
pr1002 1002 7.580000 1523460.000000 1520.420044 278676.968750 259045.000000
pr2392 2392 10.000000 32860496.000000 13737.669922 415825.000000 378032.000000
107 changes: 73 additions & 34 deletions tsp_discrete_enn.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
#include <map>
#include <stdexcept>
#include <string>
#include <thread>
#include <unordered_set>
#include <cmath>
#include <tuple>
#include <utility>
#include <array>
#include <chrono>

#include "utils.hpp"
Expand Down Expand Up @@ -87,7 +87,7 @@ typedef std::optional<std::size_t> IndexOpt_t;
template <typename T> using IndexExp_t = utils::Expected<std::size_t, T>;

void drawPath(const Indices_t& path, const Cities_t& cities, bool show_coords,
const std::string& title);
const std::string& title, float close_time = 3600.0, int highlight = -1);

template <> inline bool utils::MatchItem<City>::operator()(const City& city)
{
Expand Down Expand Up @@ -353,8 +353,9 @@ inline Value_t getDistance(const City& a, const City& b)
inline Value_t insertionCost(const City& new_city, const City& cityA,
const City& cityB)
{
return getDistance(new_city, cityA) + getDistance(new_city, cityB) -
const Value_t cost = getDistance(new_city, cityA) + getDistance(new_city, cityB) -
getDistance(cityA, cityB);
return utils::isEqual(cost, VALUE_ZERO) ? VALUE_ZERO : cost;
}

inline double getArea(const City& a, const City& b, const City& c)
Expand Down Expand Up @@ -402,7 +403,7 @@ inline bool isInside(const City& city, const City& cityA, const City& cityB,
// 2 --> Counterclockwise
inline int getOrientation(const City& a, const City& b, const City& c)
{
Value_t val = (b.y - a.y) * (c.x - b.x) - (b.x - a.x) * (c.y - b.y);
const Value_t val = (b.y - a.y) * (c.x - b.x) - (b.x - a.x) * (c.y - b.y);

if (utils::isEqual(val, VALUE_ZERO))
return 0;
Expand Down Expand Up @@ -596,9 +597,8 @@ class DiscreteENN_TSP
const auto [idx_prev, idx_next] = getNeigbhours(index);
const std::size_t pos_prev{ m_path[idx_prev] },
pos_curr{ m_path[index] }, pos_next{ m_path[idx_next] };
Value_t cost = insertionCost(m_cities[pos_curr], m_cities[pos_prev],
const Value_t cost = insertionCost(m_cities[pos_curr], m_cities[pos_prev],
m_cities[pos_next]);
cost = utils::isEqual(cost, VALUE_ZERO) ? VALUE_ZERO : cost;
m_cities[pos_curr].cost = cost;
return cost;
}
Expand Down Expand Up @@ -785,7 +785,7 @@ class DiscreteENN_TSP
const City& city_end{ m_cities[pos_end] };
std::size_t num_nodes{ m_path.size() };
for (std::size_t idx{ 0 }; idx != num_nodes;) {
if (city_start.on_stack or city_end.on_stack or (num_nodes == 3)) {
if (city_start.on_stack or city_end.on_stack or m_fromScratch) {
break;
}
const std::size_t idx_next{ properIndex(idx + 1) };
Expand All @@ -811,18 +811,19 @@ class DiscreteENN_TSP
}
std::size_t idx_remove{ idx };
std::size_t idx_remove_next{ idx_next };
if (getDistance(city_start, city_end) >
getDistance(city, city_next)) {
auto [start_new, end_new] = findEdge(pos_start, pos_end);
if (start_new == -1) {
utils::printErr("Tried to find a non-existing edge");
throw std::runtime_error{
"Tried to find a non-existing edge"
};
}
idx_remove = start_new;
idx_remove_next = end_new;
}
// const Value_t dist1{ getDistance(city_start, city_end) };
// const Value_t dist2{ getDistance(city, city_next) };
// if ((not utils::isEqual(dist1, dist2)) and (dist1 > dist2)) {
// auto [start_new, end_new] = findEdge(pos_start, pos_end);
// if (start_new == -1) {
// utils::printErr("Tried to find a non-existing edge");
// throw std::runtime_error{
// "Tried to find a non-existing edge"
// };
// }
// idx_remove = start_new;
// idx_remove_next = end_new;
// }
if (pos_erased.has_value()) {
pos_erased =
std::min(*pos_erased, std::min(m_path[idx_remove],
Expand All @@ -838,7 +839,7 @@ class DiscreteENN_TSP
m_fromScratch = true;
break;
}
const std::size_t idx_new{ idx_remove == (num_nodes + 2) ?
const std::size_t idx_new{ idx_remove_next == 0 ?
0 :
properIndex(idx_remove) };
const std::size_t idx_new_prev{ properIndex(int(idx_new) - 1) };
Expand Down Expand Up @@ -1106,6 +1107,10 @@ class DiscreteENN_TSP
[[maybe_unused]] bool print_pos{ false };
std::size_t pos{ stackPopBack() };
int idx_added{ -1 };
[[maybe_unused]] int loop_count{0};
[[maybe_unused]] int loop_check = 1e4;
[[maybe_unused]] float loop_time{10.0};
[[maybe_unused]] std::chrono::seconds sleep_time{10};
while (true) {
if (m_fromScratch) {
idx_added = 0;
Expand Down Expand Up @@ -1146,6 +1151,14 @@ class DiscreteENN_TSP
m_cities[m_path[idx_added]].print();
m_cities[m_path[idx_next]].print();
m_cities[m_path[properIndex(idx_next + 1)]].print();
if (loop_count > loop_check) {
std::cout.flush();
std::cerr.flush();
std::this_thread::sleep_for( sleep_time );
drawPath(m_path, m_cities, true, m_name, loop_time, m_path[idx_added]);
} else {
++loop_count;
}
}
// if (checkIntersectPath()) {
// utils::printErr("intersection after adding node at " +
Expand Down Expand Up @@ -1189,6 +1202,12 @@ class DiscreteENN_TSP
std::to_string(*it_erased1) + " path size " +
std::to_string(m_path.size()));
m_cities[*it_erased1].print();
if (loop_count > loop_check) {
std::cout.flush();
std::cerr.flush();
std::this_thread::sleep_for( sleep_time );
drawPath(m_path, m_cities, true, m_name, loop_time, *it_erased1);
}
}

const auto it_erased2 = validatePath();
Expand All @@ -1204,6 +1223,12 @@ class DiscreteENN_TSP
std::to_string(it_erased2.value()) +
" path size " + std::to_string(m_path.size()));
m_cities[it_erased2.value()].print();
if (loop_count > loop_check) {
std::cout.flush();
std::cerr.flush();
std::this_thread::sleep_for( sleep_time );
drawPath(m_path, m_cities, true, m_name, loop_time, it_erased2.value());
}
}
// if (checkIntersectPath()) {
// utils::printErr(
Expand Down Expand Up @@ -1245,7 +1270,7 @@ class DiscreteENN_TSP
break;
}
if (not pattern_hashes.insert(m_pattern).second) {
// print_pos = true;
print_pos = true;
utils::printInfo(
"Found repeating pattern. Randomize input node", "run");
utils::printInfo("Path progress " +
Expand Down Expand Up @@ -1397,7 +1422,7 @@ void fitPointsInWindow(Cities_t& cities, const sf::Vector2u& window_size,
}

void drawPath(const Indices_t& path, const Cities_t& cities, bool show_coords,
const std::string& title)
const std::string& title, float close_time, int highlight)
{
// Get the current desktop video mode
[[maybe_unused]] sf::VideoMode desktopMode =
Expand Down Expand Up @@ -1437,6 +1462,7 @@ void drawPath(const Indices_t& path, const Cities_t& cities, bool show_coords,
polygon.setOutlineThickness(2); // Line thickness
polygon.setOutlineColor(sf::Color::Red); // Line color

sf::Clock clock;
sf::Font font;
font.loadFromFile("/usr/share/fonts/TTF/Roboto-Regular.ttf");
while (window.isOpen()) {
Expand All @@ -1457,37 +1483,50 @@ void drawPath(const Indices_t& path, const Cities_t& cities, bool show_coords,
// window.close();
}
}
// Check the clock if 10 seconds have passed
if (clock.getElapsedTime().asSeconds() >= close_time) {
std::cout << "10 seconds have elapsed. Closing window." << std::endl;
window.close();
}

window.clear(sf::Color::White); // Clear the window
window.setTitle(title);

for (const auto& point : points) {
sf::CircleShape marker(5); // Small circle with radius 5 pixels
marker.setFillColor(sf::Color::Blue); // Use a contrasting color
marker.setPosition(
point.x,
point.y); // Adjust position to center the marker on the vertex
// for (const auto& point : points) {
// sf::CircleShape marker(5); // Small circle with radius 5 pixels
// marker.setFillColor(sf::Color::Blue); // Use a contrasting color
// marker.setPosition(
// point.x,
// point.y); // Adjust position to center the marker on the vertex

window.draw(marker);
}
// window.draw(marker);
// }
for (const City& city : cities_copy) {
if (show_coords) {
sf::Text label;
label.setFont(font); // Set the font
label.setString(std::to_string(
city.id)); // Set the point's ID as the label text
label.setCharacterSize(14); // Set the character size
label.setFillColor(sf::Color::White); // Set the text color
label.setFillColor(sf::Color::Black); // Set the text color
if (city.id == highlight) {
label.setFillColor(sf::Color::Magenta);
}
label.setPosition(city.x + 10,
city.y -
10); // Position the label near the marker
window.draw(label); // Draw the label
}

if (not city.on_stack)
continue;
sf::CircleShape marker(5); // Small circle with radius 5 pixels
marker.setFillColor(sf::Color::Green); // Use a contrasting color
if (city.on_stack) {
marker.setFillColor(sf::Color::Green); // Use a contrasting color
} else {
marker.setFillColor(sf::Color::Blue); // Use a contrasting color
}
if (city.id == highlight) {
marker.setFillColor(sf::Color::Magenta);
}
marker.setPosition(
city.x,
city.y); // Adjust position to center the marker on the vertex
Expand Down
7 changes: 6 additions & 1 deletion until_fail_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,16 @@ def runCommand(cmd, args):
stderr=subprocess.STDOUT,
text=True
)
command_in_loop = 0
while True:
# if command_in_loop > 1e6:
# return 1
output = process.stdout.readline()
if output == '' and process.poll() is not None:
break
if output:
print(output.strip())
# command_in_loop += 1
if "[Error]" in output:
return 1

Expand All @@ -30,6 +34,7 @@ def runCommand(cmd, args):
def runUntilFailure(cmd, args):
count = 0
while True:
print()
exit_code = runCommand(cmd, args)
time.sleep(1)
if exit_code != 0:
Expand All @@ -38,7 +43,7 @@ def runUntilFailure(cmd, args):
count += 1
os.system('clear')
print(f"\rRun: {count} successful", end='', flush=True)
time.sleep(1)
time.sleep(5)

print(f"Completed runs: {count}")

Expand Down

0 comments on commit cc6a066

Please sign in to comment.