22#include "absl/strings/match.h"
23#include "absl/strings/str_split.h"
24#include "absl/strings/string_view.h"
36double DoubleEuc2DDistance(
const Coordinates2<double>& from,
37 const Coordinates2<double>&
to) {
38 const double xd = from.x -
to.x;
39 const double yd = from.y -
to.y;
40 return sqrt(xd * xd + yd * yd);
43double Euc2DDistance(
const Coordinates2<double>& from,
44 const Coordinates2<double>&
to) {
45 return std::floor(DoubleEuc2DDistance(from,
to));
48constexpr double kInfinity = std::numeric_limits<double>::infinity();
50std::shared_ptr<zipfile::ZipArchive> OpenZipArchiveIfItExists(
51 absl::string_view file_name) {
52 const absl::string_view archive_name =
file::Dirname(file_name);
65 total_service_time_(0),
66 distance_function_(nullptr),
67 time_function_(nullptr) {}
70 std::shared_ptr<zipfile::ZipArchive> zip_archive(
71 OpenZipArchiveIfItExists(file_name));
73 time_windows_.clear();
74 service_times_.clear();
75 distance_matrix_.clear();
78 total_service_time_ = 0;
79 distance_function_ =
nullptr;
80 time_function_ =
nullptr;
81 return ParseLopezIbanezBlum(file_name) || ParseDaSilvaUrrutia(file_name);
84bool TspTWParser::ParseLopezIbanezBlum(
const std::string& file_name) {
87 for (
const std::string&
line :
89 const std::vector<std::string> words =
90 absl::StrSplit(
line, absl::ByAnyChar(
" :\t"), absl::SkipEmpty());
91 if (words.empty())
continue;
93 if (words[0] ==
"#") {
94 if (absl::StrContains(
line,
"service times")) {
105 if (words.size() != 1)
return false;
107 if (size_ < 0)
return false;
108 distance_matrix_.reserve(size_ * size_);
114 if (words.size() != size_)
return false;
115 for (
const std::string& word : words) {
118 if (
distance == kInfinity)
return false;
119 distance_matrix_.push_back(
distance);
122 if (entry_count == size_) {
129 if (words.size() != 2)
return false;
130 std::vector<double> values;
131 for (
const std::string& word : words) {
134 if (
value == kInfinity)
return false;
135 values.push_back(
value);
137 time_windows_.push_back({values[0], values[1]});
138 service_times_.push_back(0);
140 if (entry_count == size_) {
150 distance_function_ = [
this](
int from,
int to) {
151 return distance_matrix_[from * size_ +
to];
153 time_function_ = distance_function_;
154 return entry_count == size_;
157bool TspTWParser::ParseDaSilvaUrrutia(
const std::string& file_name) {
158 for (
const std::string&
line :
161 if (absl::StartsWith(
line,
"CUST NO."))
continue;
162 const std::vector<std::string> words =
163 absl::StrSplit(
line, absl::ByAnyChar(
" :\t"), absl::SkipEmpty());
165 if (words.empty() || words[0] ==
"!!" || words[0][0] ==
'#')
continue;
166 if (words.size() != 7)
return false;
170 if (
value < 0)
return false;
172 if (
value == 999)
continue;
173 std::vector<double> values;
174 for (
int i = 1;
i < words.size(); ++
i) {
176 words[i], std::numeric_limits<double>::infinity());
177 if (
value == std::numeric_limits<double>::infinity())
return false;
178 values.push_back(
value);
180 coords_.push_back({values[0], values[1]});
181 time_windows_.push_back({values[3], values[4]});
182 service_times_.push_back(values[5]);
184 size_ = coords_.size();
187 distance_matrix_.reserve(size_ * size_);
188 for (
int i = 0;
i < size_; ++
i) {
189 for (
int j = 0; j < size_; ++j) {
190 distance_matrix_.push_back(Euc2DDistance(coords_[i], coords_[j]));
193 for (
int i = 0;
i < size_;
i++) {
194 for (
int j = 0; j < size_; j++) {
195 for (
int k = 0; k < size_; k++) {
196 if (distance_matrix_[i * size_ + j] >
197 distance_matrix_[i * size_ + k] + distance_matrix_[k * size_ + j]) {
198 distance_matrix_[
i * size_ + j] =
199 distance_matrix_[
i * size_ + k] + distance_matrix_[k * size_ + j];
205 distance_function_ = [
this](
int from,
int to) {
206 return distance_matrix_[from * size_ +
to];
208 time_function_ = [
this](
int from,
int to) {
209 return distance_matrix_[from * size_ +
to] + service_times_[from];
static int64_t FastInt64Round(double x)
bool LoadFile(const std::string &file_name)
Loads and parses a routing problem from a given file.
double total_service_time() const
Returns the total service time already included in distance_function.
absl::string_view Extension(absl::string_view path)
absl::string_view Dirname(absl::string_view path)
In SWIG mode, we don't want anything besides these top-level includes.
double ParseLeadingDoubleValue(const char *str, double deflt)
int32_t ParseLeadingInt32Value(const char *str, int32_t deflt)
std::shared_ptr< ZipArchive > OpenZipArchive(absl::string_view path, const ZipFileOptions &options)
trees with all degrees equal to