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

Integrate GLKH-Solver #56

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
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
3 changes: 1 addition & 2 deletions install/prepare-jenkins-slave.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ sudo apt-get install -y python3-wstool python3-catkin-tools
# Package dependencies.
echo "Installing CGAL dependencies."
sudo apt-get install -y libcgal-dev
echo "Installing MONO dependencies."
sudo apt-get install -y mono-devel
sudo apt-get install -y libgmp-dev libmpfr-dev
echo "Installig GLOG dependencices."
sudo apt-get install -y libgoogle-glog-dev
4 changes: 0 additions & 4 deletions polygon_coverage_planners/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@ set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
set(CMAKE_BUILD_TYPE Release)

# TODO(rikba): Make catkin package.
find_package(PkgConfig)
pkg_check_modules(MONO mono-2 REQUIRED)
include_directories(${MONO_INCLUDE_DIRS})

catkin_package(
INCLUDE_DIRS include ${catkin_INCLUDE_DIRS}
Expand Down
10 changes: 5 additions & 5 deletions polygon_coverage_planners/src/graphs/sweep_plan_graph.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
#include <polygon_coverage_geometry/tcd.h>
#include <polygon_coverage_geometry/visibility_polygon.h>

#include <polygon_coverage_solvers/gk_ma.h>
#include <polygon_coverage_solvers/glkh.h>

#include <CGAL/Boolean_set_operations_2.h>
#include <CGAL/create_offset_polygons_from_polygon_with_holes_2.h>
Expand Down Expand Up @@ -522,20 +522,20 @@ bool SweepPlanGraph::solve(const Point_2& start, const Point_2& goal,
const size_t goal_idx = temp_gtsp_graph.size() - 1;
const size_t start_idx = temp_gtsp_graph.size() - 2;

// Solve using GK MA.
// Solve using GLKH.
std::vector<std::vector<int>> m = temp_gtsp_graph.getAdjacencyMatrix();
std::vector<std::vector<int>> clusters;
if (!temp_gtsp_graph.getClusters(&clusters)) {
ROS_ERROR("Cannot get clusters.");
return false;
}
gk_ma::Task task(m, clusters);
gk_ma::GkMa& solver = gk_ma::GkMa::getInstance();
glkh::Task task(m, clusters);
glkh::Glkh& solver = glkh::Glkh::getInstance();
solver.setSolver(task);

ROS_INFO("Start solving GTSP");
if (!solver.solve()) {
ROS_ERROR("GkMa solution failed.");
ROS_ERROR("GLKH solution failed.");
return false;
}
ROS_INFO("Finished solving GTSP");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ bool PolygonStripmapPlanner::runSolver(const Point_2& start,
std::vector<Point_2>* solution) const {
ROS_ASSERT(solution);

ROS_INFO("Start solving GTSP using GK MA.");
ROS_INFO("Start solving GTSP using GLKH.");
return sweep_plan_graph_.solve(start, goal, solution);
}

Expand Down
62 changes: 17 additions & 45 deletions polygon_coverage_solvers/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,49 +13,18 @@ catkin_package(
)
include_directories(include ${catkin_INCLUDE_DIRS})

# Add mono to invoke gk_ma.
find_package(PkgConfig)
pkg_check_modules(MONO mono-2 REQUIRED)
include_directories(${MONO_INCLUDE_DIRS})

# Download gk_ma
set(GKMA_INCLUDE_DIR ${CMAKE_BINARY_DIR}/gk_ma-prefix/src/gk_ma)
# Download glkh
include(ExternalProject)
ExternalProject_Add(
gk_ma
URL http://www.cs.nott.ac.uk/~pszdk/gtsp_ma_source_codes.zip
URL https://polybox.ethz.ch/index.php/s/H4NXeaNPWo6VBrf/download
DOWNLOAD_NAME gtsp_ma_source_codes.zip
URL_MD5 765fad8e3746fa3dd9b81be0afb34d35
glkh
URL http://webhotel4.ruc.dk/~keld/research/GLKH/GLKH-1.0.tgz
DOWNLOAD_NAME glkh_source_codes.tgz
URL_MD5 9b0ba92053dac798f550c5c8a9524120
BINARY_DIR ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_BIN_DESTINATION}
PATCH_COMMAND
COMMAND patch GkMa/OurHeuristic/Algorithm.cs ${CMAKE_CURRENT_SOURCE_DIR}/patches/Algorithm.patch
COMMAND patch NativeHelper/ClusterOptimisation.cpp ${CMAKE_CURRENT_SOURCE_DIR}/patches/ClusterOptimisationCpp.patch
COMMAND patch GkMa/OurHeuristic/Types/Generation.cs ${CMAKE_CURRENT_SOURCE_DIR}/patches/Generation.patch
COMMAND patch GkMa/OurHeuristic/GeneticAlgorithm.cs ${CMAKE_CURRENT_SOURCE_DIR}/patches/GeneticAlgorithm.patch
COMMAND patch GkMa/Helper.cs ${CMAKE_CURRENT_SOURCE_DIR}/patches/Helper.patch
COMMAND patch NativeHelper/ClusterOptimisation.h ${CMAKE_CURRENT_SOURCE_DIR}/patches/ClusterOptimisationH.patch
COMMAND patch NativeHelper/ImprovementManager.h ${CMAKE_CURRENT_SOURCE_DIR}/patches/ImprovementManagerH.patch
COMMAND patch NativeHelper/Insert.cpp ${CMAKE_CURRENT_SOURCE_DIR}/patches/InsertCpp.patch
COMMAND patch NativeHelper/Insert.h ${CMAKE_CURRENT_SOURCE_DIR}/patches/InsertH.patch
COMMAND patch NativeHelper/NativeHelper.cpp ${CMAKE_CURRENT_SOURCE_DIR}/patches/NativeHelperCpp.patch
COMMAND patch NativeHelper/Swap.cpp ${CMAKE_CURRENT_SOURCE_DIR}/patches/SwapCpp.patch
COMMAND patch NativeHelper/NativeHelper.h ${CMAKE_CURRENT_SOURCE_DIR}/patches/NativeHelperH.patch
COMMAND patch GkMa/OurHeuristic/NativeHelper.cs ${CMAKE_CURRENT_SOURCE_DIR}/patches/NativeHelper.patch
COMMAND patch GkMa/OurSolver.cs ${CMAKE_CURRENT_SOURCE_DIR}/patches/OurSolver.patch
COMMAND patch GkMa/OurHeuristic/Types/Permutation.cs ${CMAKE_CURRENT_SOURCE_DIR}/patches/Permutation.patch
COMMAND patch GkMa/Program.cs ${CMAKE_CURRENT_SOURCE_DIR}/patches/Program.patch
COMMAND patch GkMa/Solver.cs ${CMAKE_CURRENT_SOURCE_DIR}/patches/Solver.patch
COMMAND patch GkMa/Loader/Task.cs ${CMAKE_CURRENT_SOURCE_DIR}/patches/Task.patch
COMMAND patch GkMa/OurHeuristic/Types/Tour.cs ${CMAKE_CURRENT_SOURCE_DIR}/patches/Tour.patch
UPDATE_COMMAND ""
CONFIGURE_COMMAND
COMMAND cp ${PROJECT_SOURCE_DIR}/patches/MakefileCpp ./MakefileCpp
COMMAND cp ${PROJECT_SOURCE_DIR}/patches/MakefileCs ./MakefileCs
BUILD_COMMAND
COMMAND $(MAKE) -f MakefileCs BUILD_PATH="${CMAKE_LIBRARY_OUTPUT_DIRECTORY}"
COMMAND $(MAKE) -f MakefileCpp BUILD_PATH="${CMAKE_LIBRARY_OUTPUT_DIRECTORY}"
INSTALL_COMMAND
COMMAND ${CMAKE_COMMAND} -E create_symlink /usr/lib/libmono-native.so ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/System.Native
COMMAND patch --forward ./SRC/SolveTSP.c < ${PROJECT_SOURCE_DIR}/patches/SolveTSP.patch
COMMAND cp ${PROJECT_SOURCE_DIR}/patches/CMakeLists.txt ./
INSTALL_COMMAND ""
)

# Download GTSP test instances.
Expand All @@ -76,20 +45,23 @@ ExternalProject_Add(
# LIBRARIES #
#############
add_library(${PROJECT_NAME}
src/gk_ma.cc
src/glkh.cc
src/combinatorics.cc
src/boolean_lattice.cc
)
target_link_libraries(${PROJECT_NAME} ${MONO_LIBRARIES} ${catkin_LIBRARIES})

target_link_libraries(${PROJECT_NAME} ${catkin_LIBRARIES})

#########
# TESTS #
#########
catkin_add_gtest(test_combinatorics test/combinatorics-test.cpp)
catkin_add_gtest(test_combinatorics
test/combinatorics-test.cpp
)
target_link_libraries(test_combinatorics ${PROJECT_NAME} ${catkin_LIBRARIES})

catkin_add_gtest(test_gk_ma test/gk_ma-test.cpp)
target_link_libraries(test_gk_ma ${PROJECT_NAME} ${catkin_LIBRARIES})
catkin_add_gtest(test_glkh test/glkh-test.cpp)
target_link_libraries(test_glkh ${PROJECT_NAME} ${catkin_LIBRARIES})


##########
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,15 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef POLYGON_COVERAGE_SOLVERS_GK_MA_H_
#define POLYGON_COVERAGE_SOLVERS_GK_MA_H_
#ifndef POLYGON_COVERAGE_SOLVERS_GLKH_H_
#define POLYGON_COVERAGE_SOLVERS_GLKH_H_

#include <string>
#include <vector>

#include <mono/metadata/object.h>

// Interfaces with the GK MA GTSP solver.
// Interfaces with the GLKH GTSP solver.
namespace polygon_coverage_planning {
namespace gk_ma {
namespace glkh {
struct Task {
Task(const std::vector<std::vector<int>>& m,
const std::vector<std::vector<int>>& clusters)
Expand All @@ -38,37 +36,29 @@ struct Task {
std::vector<std::vector<int>> clusters;
};

// References GkMa.exe. Singleton, because it may only be referenced once during
// References GLKH. Singleton, because it may only be referenced once during
// runtime.
// https://stackoverflow.com/questions/1008019/c-singleton-design-pattern
class GkMa {
class Glkh {
public:
inline static GkMa& getInstance() {
static GkMa instance;
inline static Glkh& getInstance() {
static Glkh instance;
return instance;
}
GkMa(GkMa const&) = delete;
void operator=(GkMa const&) = delete;
Glkh(Glkh const&) = delete;
void operator=(Glkh const&) = delete;

void setSolver(const std::string& file, bool binary);
void setSolver(const Task& task);
bool solve();
inline std::vector<int> getSolution() const { return solution_; }

private:
GkMa();
~GkMa();

MonoArray* vectorOfVectorToMonoArray(
const std::vector<std::vector<int>>& in) const;

MonoDomain* domain_;
MonoObject* solver_;
MonoClass* solver_class_;
Glkh();
~Glkh() = default;

std::vector<int> solution_;
};
} // namespace gk_ma
} // namespace glkh
} // namespace polygon_coverage_planning

#endif // POLYGON_COVERAGE_SOLVERS_GK_MA_H_
#endif // POLYGON_COVERAGE_SOLVERS_GLKH_H_
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ GraphBase<NodeProperty, EdgeProperty>::getAdjacencyMatrix() const {
if (edgeExists(edge) && getEdgeCost(edge, &cost)) {
m[i][j] = static_cast<int>(cost * scale);
} else {
m[i][j] = std::numeric_limits<int>::max();
m[i][j] = std::numeric_limits<int>::max(); // TODO: overflow!
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rikba You might want to have a look at this line. Setting the weights to std::numeric_limits<int>::max() causes an integer overflow within GLKH. What value should we use instead?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I remember correctly std::numeric_limits<int>::max()was used in gkma to note edges in the adjacency matrix that are not traversable. I had a look into the GTSPLIB instances in GLKH-1.0/GTSPLIB and they have different large values there, e.g., 10ftv47.gtsp has 100000000, 4br17.gtsp has 9999, 11ft53.gtsp has 9999999. So maybe it's ok to allocate 9999999 like you do below but add a TODO that we want to setup the problem in EDGE_DATA_FORMAT and let GKLH handle the disconnected edges.

}
}
}
Expand Down
34 changes: 34 additions & 0 deletions polygon_coverage_solvers/include/polygon_coverage_solvers/utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@


#ifndef POLYGON_COVERAGE_SOLVERS_UTILS_H_
#define POLYGON_COVERAGE_SOLVERS_UTILS_H_

#include <string>
#include <algorithm>
#include <cctype>

namespace polygon_coverage_planning {

// trim from start (in place)
static inline void ltrim(std::string &s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) {
return !std::isspace(ch);
}));
}

// trim from end (in place)
static inline void rtrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) {
return !std::isspace(ch);
}).base(), s.end());
}

// trim from both ends (in place)
static inline void trim(std::string &s) {
ltrim(s);
rtrim(s);
}

} // namespace polygon_coverage_planning

#endif // POLYGON_COVERAGE_SOLVERS_UTILS_H_
22 changes: 0 additions & 22 deletions polygon_coverage_solvers/patches/Algorithm.patch

This file was deleted.

Loading