From f73a92cced0b4dbee7b5492a2eacf9caf8849e21 Mon Sep 17 00:00:00 2001 From: Corentin Le Molgat Date: Fri, 15 Nov 2024 14:53:24 +0100 Subject: [PATCH] routing/parser: change namespace --- ortools/routing/parsers/BUILD.bazel | 12 +- .../routing/parsers/capacity_planning.proto | 6 +- ortools/routing/parsers/carp_parser.cc | 9 +- ortools/routing/parsers/carp_parser.h | 9 +- ortools/routing/parsers/carp_parser_test.cc | 49 +- ortools/routing/parsers/dow_parser.cc | 4 +- ortools/routing/parsers/dow_parser.h | 4 +- ortools/routing/parsers/dow_parser_test.cc | 25 +- ortools/routing/parsers/lilim_parser.cc | 4 +- ortools/routing/parsers/lilim_parser.h | 4 +- ortools/routing/parsers/lilim_parser_test.cc | 26 +- ortools/routing/parsers/nearp_parser.cc | 10 +- ortools/routing/parsers/nearp_parser.h | 9 +- ortools/routing/parsers/nearp_parser_test.cc | 27 +- ortools/routing/parsers/pdtsp_parser.cc | 6 +- ortools/routing/parsers/pdtsp_parser.h | 7 +- ortools/routing/parsers/pdtsp_parser_test.cc | 16 +- ortools/routing/parsers/simple_graph.cc | 4 +- ortools/routing/parsers/simple_graph.h | 4 +- ortools/routing/parsers/simple_graph_test.cc | 4 +- ortools/routing/parsers/solomon_parser.cc | 54 +- ortools/routing/parsers/solomon_parser.h | 50 +- .../routing/parsers/solomon_parser_test.cc | 41 +- .../routing/parsers/solution_serializer.cc | 12 +- ortools/routing/parsers/solution_serializer.h | 6 +- .../parsers/solution_serializer_test.cc | 4 +- ortools/routing/parsers/testdata/BUILD.bazel | 1 + ortools/routing/parsers/testdata/C1_10_2.TXT | 1010 +++++++++++++++++ .../parsers/testdata/c1_10_2-90-42222.96.txt | 95 ++ ortools/routing/parsers/tsplib_parser.cc | 12 +- ortools/routing/parsers/tsplib_parser.h | 13 +- ortools/routing/parsers/tsplib_parser_test.cc | 27 +- ortools/routing/parsers/tsptw_parser.cc | 10 +- ortools/routing/parsers/tsptw_parser.h | 11 +- ortools/routing/parsers/tsptw_parser_test.cc | 16 +- 35 files changed, 1394 insertions(+), 207 deletions(-) create mode 100644 ortools/routing/parsers/testdata/C1_10_2.TXT create mode 100644 ortools/routing/parsers/testdata/c1_10_2-90-42222.96.txt diff --git a/ortools/routing/parsers/BUILD.bazel b/ortools/routing/parsers/BUILD.bazel index 94690f386f..3bc2e3e258 100644 --- a/ortools/routing/parsers/BUILD.bazel +++ b/ortools/routing/parsers/BUILD.bazel @@ -11,8 +11,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -load("@rules_cc//cc:defs.bzl", "cc_library", "cc_proto_library") -load("@rules_proto//proto:defs.bzl", "proto_library") +load("@com_google_protobuf//bazel:cc_proto_library.bzl", "cc_proto_library") +load("@com_google_protobuf//bazel:proto_library.bzl", "proto_library") +load("@rules_cc//cc:defs.bzl", "cc_library") package(default_visibility = ["//visibility:public"]) @@ -59,6 +60,7 @@ cc_library( "//ortools/base:zipfile", "//ortools/util:filelineiter", "@com_google_absl//absl/strings", + "@com_google_re2//:re2", ], ) @@ -66,11 +68,15 @@ cc_test( name = "solomon_parser_test", size = "small", srcs = ["solomon_parser_test.cc"], - data = ["//ortools/routing/parsers/testdata:solomon.zip"], + data = [ + "//ortools/routing/parsers/testdata:c1_10_2-90-42222.96.txt", + "//ortools/routing/parsers/testdata:solomon.zip", + ], deps = [ ":solomon_parser", "//ortools/base", "//ortools/base:file", + "//ortools/base:gmock", "@com_google_googletest//:gtest_main", ], ) diff --git a/ortools/routing/parsers/capacity_planning.proto b/ortools/routing/parsers/capacity_planning.proto index 2d089df73a..71bd0515c5 100644 --- a/ortools/routing/parsers/capacity_planning.proto +++ b/ortools/routing/parsers/capacity_planning.proto @@ -13,7 +13,11 @@ syntax = "proto3"; -package operations_research; +option java_package = "com.google.ortools.routing.parser"; +option java_multiple_files = true; +option csharp_namespace = "Google.OrTools.Routing.Parser"; + +package operations_research.routing; // This is the proto for describing the multicommodity fixed-charged network // design problem. diff --git a/ortools/routing/parsers/carp_parser.cc b/ortools/routing/parsers/carp_parser.cc index a259974dff..243b953e5a 100644 --- a/ortools/routing/parsers/carp_parser.cc +++ b/ortools/routing/parsers/carp_parser.cc @@ -21,11 +21,12 @@ #include "absl/strings/str_join.h" #include "absl/strings/str_split.h" +#include "absl/strings/string_view.h" #include "absl/types/span.h" #include "ortools/base/numbers.h" #include "ortools/util/filelineiter.h" -namespace operations_research { +namespace operations_research::routing { CarpParser::CarpParser() { Initialize(); } @@ -44,12 +45,12 @@ void CarpParser::Initialize() { section_ = METADATA; } -bool CarpParser::LoadFile(const std::string& file_name) { +bool CarpParser::LoadFile(absl::string_view file_name) { Initialize(); return ParseFile(file_name); } -bool CarpParser::ParseFile(const std::string& file_name) { +bool CarpParser::ParseFile(absl::string_view file_name) { static auto section_headers = std::array({ "NOMBRE", "COMENTARIO", @@ -246,4 +247,4 @@ std::optional ParseNodeIndex(std::string_view text) { return {node - 1}; } } // namespace -} // namespace operations_research +} // namespace operations_research::routing diff --git a/ortools/routing/parsers/carp_parser.h b/ortools/routing/parsers/carp_parser.h index 8a40cd0c73..d5697c9e09 100644 --- a/ortools/routing/parsers/carp_parser.h +++ b/ortools/routing/parsers/carp_parser.h @@ -60,12 +60,13 @@ #include #include +#include "absl/strings/string_view.h" #include "absl/types/span.h" #include "ortools/base/linked_hash_map.h" #include "ortools/base/logging.h" #include "ortools/routing/parsers/simple_graph.h" -namespace operations_research { +namespace operations_research::routing { class CarpParser { public: CarpParser(); @@ -76,7 +77,7 @@ class CarpParser { #endif // Loads instance from a file into this parser object. - bool LoadFile(const std::string& file_name); + bool LoadFile(absl::string_view file_name); // Returns the name of the instance being solved. const std::string& name() const { return name_; } @@ -156,7 +157,7 @@ class CarpParser { }; void Initialize(); - bool ParseFile(const std::string& file_name); + bool ParseFile(absl::string_view file_name); bool ParseMetadataLine(absl::Span words); bool ParseEdge(std::string_view line, bool with_servicing); @@ -181,6 +182,6 @@ class CarpParser { int64_t n_vehicles_; int64_t capacity_; }; -} // namespace operations_research +} // namespace operations_research::routing #endif // OR_TOOLS_ROUTING_PARSERS_CARP_PARSER_H_ diff --git a/ortools/routing/parsers/carp_parser_test.cc b/ortools/routing/parsers/carp_parser_test.cc index 977737f57b..00f5f8d4bc 100644 --- a/ortools/routing/parsers/carp_parser_test.cc +++ b/ortools/routing/parsers/carp_parser_test.cc @@ -16,21 +16,14 @@ #include #include "absl/base/log_severity.h" -#include "absl/flags/flag.h" #include "absl/log/scoped_mock_log.h" #include "gtest/gtest.h" #include "ortools/base/gmock.h" #include "ortools/base/path.h" -#if defined(_MSC_VER) -#define ROOT_DIR "../../../../../../../" -#else -#define ROOT_DIR -#endif // _MSC_VER +#define ROOT_DIR "_main/" -ABSL_FLAG(std::string, test_srcdir, "", "REQUIRED: src dir"); - -namespace operations_research { +namespace operations_research::routing { namespace { TEST(CarpParserTest, Constructor) { CarpParser parser; @@ -69,7 +62,7 @@ TEST(CarpParserTest, LoadInvalidFileIncorrectNumberOfNodes) { CarpParser parser; EXPECT_FALSE( - parser.LoadFile(file::JoinPath(absl::GetFlag(FLAGS_test_srcdir), ROOT_DIR + parser.LoadFile(file::JoinPath(::testing::SrcDir(), ROOT_DIR "ortools/routing/parsers/testdata/" "carp_gdb19_incorrecto_vertices.dat"))); } @@ -86,7 +79,7 @@ TEST(CarpParserTest, LoadInvalidFileIncorrectNumberOfArcsWithServicings) { CarpParser parser; EXPECT_FALSE( - parser.LoadFile(file::JoinPath(absl::GetFlag(FLAGS_test_srcdir), ROOT_DIR + parser.LoadFile(file::JoinPath(::testing::SrcDir(), ROOT_DIR "ortools/routing/parsers/testdata/" "carp_gdb19_incorrecto_arireq.dat"))); } @@ -103,7 +96,7 @@ TEST(CarpParserTest, LoadInvalidFileIncorrectNumberOfArcsWithoutServicings) { CarpParser parser; EXPECT_FALSE( - parser.LoadFile(file::JoinPath(absl::GetFlag(FLAGS_test_srcdir), ROOT_DIR + parser.LoadFile(file::JoinPath(::testing::SrcDir(), ROOT_DIR "ortools/routing/parsers/testdata/" "carp_gdb19_incorrecto_arinoreq.dat"))); } @@ -120,7 +113,7 @@ TEST(CarpParserTest, LoadInvalidFileIncorrectNumberOfVehicles) { CarpParser parser; EXPECT_FALSE( - parser.LoadFile(file::JoinPath(absl::GetFlag(FLAGS_test_srcdir), ROOT_DIR + parser.LoadFile(file::JoinPath(::testing::SrcDir(), ROOT_DIR "ortools/routing/parsers/testdata/" "carp_gdb19_incorrecto_vehiculos.dat"))); } @@ -137,7 +130,7 @@ TEST(CarpParserTest, LoadInvalidFileIncorrectCapacity) { CarpParser parser; EXPECT_FALSE( - parser.LoadFile(file::JoinPath(absl::GetFlag(FLAGS_test_srcdir), ROOT_DIR + parser.LoadFile(file::JoinPath(::testing::SrcDir(), ROOT_DIR "ortools/routing/parsers/testdata/" "carp_gdb19_incorrecto_capacidad.dat"))); } @@ -154,7 +147,7 @@ TEST(CarpParserTest, LoadInvalidFileIncorrectTypeOfArcCost) { CarpParser parser; EXPECT_FALSE( - parser.LoadFile(file::JoinPath(absl::GetFlag(FLAGS_test_srcdir), ROOT_DIR + parser.LoadFile(file::JoinPath(::testing::SrcDir(), ROOT_DIR "ortools/routing/parsers/testdata/" "carp_gdb19_incorrecto_tipo.dat"))); } @@ -170,7 +163,7 @@ TEST(CarpParserTest, LoadInvalidFileIncorrectTotalServicingCost) { CarpParser parser; EXPECT_FALSE( - parser.LoadFile(file::JoinPath(absl::GetFlag(FLAGS_test_srcdir), ROOT_DIR + parser.LoadFile(file::JoinPath(::testing::SrcDir(), ROOT_DIR "ortools/routing/parsers/testdata/" "carp_gdb19_incorrecto_coste.dat"))); } @@ -189,7 +182,7 @@ TEST(CarpParserTest, LoadInvalidFileIncorrectDepot) { CarpParser parser; EXPECT_FALSE( - parser.LoadFile(file::JoinPath(absl::GetFlag(FLAGS_test_srcdir), ROOT_DIR + parser.LoadFile(file::JoinPath(::testing::SrcDir(), ROOT_DIR "ortools/routing/parsers/testdata/" "carp_gdb19_incorrecto_deposito.dat"))); } @@ -207,7 +200,7 @@ TEST(CarpParserTest, LoadInvalidFileNoEdgeWithServicing) { CarpParser parser; EXPECT_FALSE(parser.LoadFile( - file::JoinPath(absl::GetFlag(FLAGS_test_srcdir), + file::JoinPath(::testing::SrcDir(), ROOT_DIR "ortools/routing/parsers" "/testdata/carp_gdb19_no_arista_req.dat"))); } @@ -223,7 +216,7 @@ TEST(CarpParserTest, LoadInvalidFileServicingForArcsWithoutServicing) { CarpParser parser; EXPECT_FALSE( - parser.LoadFile(file::JoinPath(absl::GetFlag(FLAGS_test_srcdir), ROOT_DIR + parser.LoadFile(file::JoinPath(::testing::SrcDir(), ROOT_DIR "ortools/routing/parsers" "/testdata/carp_gdb19_mixed_arcs.dat"))); } @@ -239,16 +232,15 @@ TEST(CarpParserTest, LoadInvalidFileServicingForArcsInWrongOrder) { CarpParser parser; EXPECT_FALSE(parser.LoadFile( - file::JoinPath(absl::GetFlag(FLAGS_test_srcdir), + file::JoinPath(::testing::SrcDir(), ROOT_DIR "ortools/routing/parsers/testdata/" "carp_gdb19_incorrecta_lista_aristas_req.dat"))); } TEST(CarpParserTest, LoadInstanceFile) { - std::string file_name = - file::JoinPath(absl::GetFlag(FLAGS_test_srcdir), ROOT_DIR - "ortools/routing/parsers/testdata/" - "carp_gdb19.dat"); + std::string file_name = file::JoinPath(::testing::SrcDir(), ROOT_DIR + "ortools/routing/parsers/testdata/" + "carp_gdb19.dat"); CarpParser parser; EXPECT_TRUE(parser.LoadFile(file_name)); EXPECT_EQ(parser.name(), "gdb19"); @@ -271,13 +263,12 @@ TEST(CarpParserTest, LoadInstanceFile) { } TEST(CarpParserTest, LoadInstanceFileWithDifferentDepot) { - std::string file_name = - file::JoinPath(absl::GetFlag(FLAGS_test_srcdir), ROOT_DIR - "ortools/routing/parsers/testdata/" - "carp_gdb19_diferente_deposito.dat"); + std::string file_name = file::JoinPath(::testing::SrcDir(), ROOT_DIR + "ortools/routing/parsers/testdata/" + "carp_gdb19_diferente_deposito.dat"); CarpParser parser; EXPECT_TRUE(parser.LoadFile(file_name)); EXPECT_EQ(parser.depot(), 4); } } // namespace -} // namespace operations_research +} // namespace operations_research::routing diff --git a/ortools/routing/parsers/dow_parser.cc b/ortools/routing/parsers/dow_parser.cc index 29dc375a44..af276bcdd7 100644 --- a/ortools/routing/parsers/dow_parser.cc +++ b/ortools/routing/parsers/dow_parser.cc @@ -29,7 +29,7 @@ #include "ortools/routing/parsers/capacity_planning.pb.h" #include "ortools/util/filelineiter.h" -namespace operations_research { +namespace operations_research::routing { ::absl::Status ReadFile(absl::string_view file_name, CapacityPlanningInstance* request) { if (!file::Exists(file_name, file::Defaults()).ok()) { @@ -103,4 +103,4 @@ namespace operations_research { return absl::OkStatus(); } -} // namespace operations_research +} // namespace operations_research::routing diff --git a/ortools/routing/parsers/dow_parser.h b/ortools/routing/parsers/dow_parser.h index 8d78b8443e..e3a9c5c540 100644 --- a/ortools/routing/parsers/dow_parser.h +++ b/ortools/routing/parsers/dow_parser.h @@ -21,9 +21,9 @@ // Reader for Multicommodity fixed-charge Network Design (MCND) files using the // .dow format. -namespace operations_research { +namespace operations_research::routing { ::absl::Status ReadFile(absl::string_view file_name, CapacityPlanningInstance* request); -} // namespace operations_research +} // namespace operations_research::routing #endif // OR_TOOLS_ROUTING_PARSERS_DOW_PARSER_H_ diff --git a/ortools/routing/parsers/dow_parser_test.cc b/ortools/routing/parsers/dow_parser_test.cc index 99f74430ee..3ec5395f67 100644 --- a/ortools/routing/parsers/dow_parser_test.cc +++ b/ortools/routing/parsers/dow_parser_test.cc @@ -15,22 +15,21 @@ #include -#include "absl/flags/flag.h" #include "absl/status/status.h" #include "gtest/gtest.h" #include "ortools/base/gmock.h" #include "ortools/base/path.h" #include "ortools/routing/parsers/capacity_planning.pb.h" -namespace operations_research { +namespace operations_research::routing { namespace { TEST(CapacityPlanningReaderTest, C33PassesOK) { CapacityPlanningInstance request; - ::absl::Status status = ReadFile( - file::JoinPathRespectAbsolute( - absl::GetFlag(FLAGS_test_srcdir), "operations_research_data/", - "MULTICOM_FIXED_CHARGE_NETWORK_DESIGN/C/c33.dow"), - &request); + ::absl::Status status = + ReadFile(file::JoinPathRespectAbsolute( + ::testing::SrcDir(), "operations_research_data/", + "MULTICOM_FIXED_CHARGE_NETWORK_DESIGN/C/c33.dow"), + &request); EXPECT_OK(status); const NetworkTopology& topology = request.topology(); const int num_arcs = topology.from_node_size(); @@ -48,14 +47,14 @@ TEST(CapacityPlanningReaderTest, C33PassesOK) { TEST(CapacityPlanningReaderTest, C34DoesNotExist) { CapacityPlanningInstance request; - ::absl::Status status = ReadFile( - file::JoinPathRespectAbsolute( - absl::GetFlag(FLAGS_test_srcdir), "operations_research_data/", - "MULTICOM_FIXED_CHARGE_NETWORK_DESIGN/C/c34.dow"), - &request); + ::absl::Status status = + ReadFile(file::JoinPathRespectAbsolute( + ::testing::SrcDir(), "operations_research_data/", + "MULTICOM_FIXED_CHARGE_NETWORK_DESIGN/C/c34.dow"), + &request); EXPECT_THAT(::util::StatusToString(status), testing::HasSubstr("generic::not_found")); } } // namespace -} // namespace operations_research +} // namespace operations_research::routing diff --git a/ortools/routing/parsers/lilim_parser.cc b/ortools/routing/parsers/lilim_parser.cc index 5fb8deb0ab..3e0d29771c 100644 --- a/ortools/routing/parsers/lilim_parser.cc +++ b/ortools/routing/parsers/lilim_parser.cc @@ -30,7 +30,7 @@ #include "ortools/base/zipfile.h" #include "ortools/util/filelineiter.h" -namespace operations_research { +namespace operations_research::routing { bool LiLimParser::LoadFile(absl::string_view file_name) { Initialize(); @@ -126,4 +126,4 @@ bool LiLimParser::ParseFile(absl::string_view file_name) { #undef PARSE_AND_RETURN_IF_NEGATIVE -} // namespace operations_research +} // namespace operations_research::routing diff --git a/ortools/routing/parsers/lilim_parser.h b/ortools/routing/parsers/lilim_parser.h index 2c2f441667..9cfe63f0cc 100644 --- a/ortools/routing/parsers/lilim_parser.h +++ b/ortools/routing/parsers/lilim_parser.h @@ -51,7 +51,7 @@ #include "absl/strings/string_view.h" #include "ortools/routing/parsers/simple_graph.h" -namespace operations_research { +namespace operations_research::routing { // Li&Lim parser class class LiLimParser { @@ -122,6 +122,6 @@ class LiLimParser { std::vector> time_windows_; std::vector service_times_; }; -} // namespace operations_research +} // namespace operations_research::routing #endif // OR_TOOLS_ROUTING_PARSERS_LILIM_PARSER_H_ diff --git a/ortools/routing/parsers/lilim_parser_test.cc b/ortools/routing/parsers/lilim_parser_test.cc index 5b3d0b024d..4cce991109 100644 --- a/ortools/routing/parsers/lilim_parser_test.cc +++ b/ortools/routing/parsers/lilim_parser_test.cc @@ -19,15 +19,9 @@ #include "gtest/gtest.h" #include "ortools/base/path.h" -#if defined(_MSC_VER) -#define ROOT_DIR "../../../../../../../" -#else -#define ROOT_DIR -#endif // _MSC_VER +#define ROOT_DIR "_main/" -ABSL_FLAG(std::string, test_srcdir, "", "REQUIRED: src dir"); - -namespace operations_research { +namespace operations_research::routing { namespace { void CheckData(const LiLimParser& parser) { @@ -55,10 +49,9 @@ TEST(LiLimParserTest, LoadNonExistingFile) { TEST(LiLimParserTest, LoadExistingFile) { LiLimParser parser; - EXPECT_TRUE( - parser.LoadFile(file::JoinPath(absl::GetFlag(FLAGS_test_srcdir), ROOT_DIR - "ortools/routing/parsers" - "/testdata/pdptw_LRC2_10_6.txt"))); + EXPECT_TRUE(parser.LoadFile(file::JoinPath(::testing::SrcDir(), ROOT_DIR + "ortools/routing/parsers" + "/testdata/pdptw_LRC2_10_6.txt"))); CheckData(parser); // Load a non-existing file to check the parser was cleaned. EXPECT_FALSE(parser.LoadFile("doesnotexist.txt")); @@ -78,12 +71,11 @@ TEST(LiLimParserTest, LoadNonExistingArchive) { TEST(LiLimParserTest, LoadNonExistingInstance) { LiLimParser parser; - EXPECT_FALSE( - parser.LoadFile("doesnotexist.txt", - file::JoinPath(absl::GetFlag(FLAGS_test_srcdir), - ROOT_DIR "ortools/routing/" + EXPECT_FALSE(parser.LoadFile("doesnotexist.txt", + file::JoinPath(::testing::SrcDir(), ROOT_DIR + "ortools/routing/" "/parsers/testdata/lilim.zip"))); } } // namespace -} // namespace operations_research +} // namespace operations_research::routing diff --git a/ortools/routing/parsers/nearp_parser.cc b/ortools/routing/parsers/nearp_parser.cc index ece0e93fba..095ce085ec 100644 --- a/ortools/routing/parsers/nearp_parser.cc +++ b/ortools/routing/parsers/nearp_parser.cc @@ -22,10 +22,11 @@ #include "absl/strings/str_join.h" #include "absl/strings/str_split.h" +#include "absl/strings/string_view.h" #include "ortools/base/numbers.h" #include "ortools/util/filelineiter.h" -namespace operations_research { +namespace operations_research::routing { NearpParser::NearpParser() { Initialize(); } @@ -49,12 +50,12 @@ void NearpParser::Initialize() { section_ = METADATA; } -bool NearpParser::LoadFile(const std::string& file_name) { +bool NearpParser::LoadFile(absl::string_view file_name) { Initialize(); return ParseFile(file_name); } -bool NearpParser::ParseFile(const std::string& file_name) { +bool NearpParser::ParseFile(absl::string_view file_name) { // Only put the first word as header, as the main check is just done on this // first word (no ambiguity is possible for well-formed files; a more precise // check is done for metadata). @@ -357,7 +358,6 @@ std::optional ParseArcOrEdge(std::string_view line, absl::StrSplit(line, absl::ByAnyChar(" :\t(),"), absl::SkipEmpty()); // Parse the name. - const std::string name = words[0]; // Parse the tail and the head of the arc/edge. std::optional opt_tail = ParseNodeIndex(words[1]); @@ -447,4 +447,4 @@ std::string NearpParser::GetEdgeName(Edge edge) const { return absl::StrCat("NrE", edge_position - num_edges_with_servicing_ + 1); } } -} // namespace operations_research +} // namespace operations_research::routing diff --git a/ortools/routing/parsers/nearp_parser.h b/ortools/routing/parsers/nearp_parser.h index a07535c0ea..57c32644af 100644 --- a/ortools/routing/parsers/nearp_parser.h +++ b/ortools/routing/parsers/nearp_parser.h @@ -80,11 +80,12 @@ #include #include +#include "absl/strings/string_view.h" #include "ortools/base/linked_hash_map.h" #include "ortools/base/logging.h" #include "ortools/routing/parsers/simple_graph.h" -namespace operations_research { +namespace operations_research::routing { class NearpParser { public: NearpParser(); @@ -95,7 +96,7 @@ class NearpParser { #endif // Loads instance from a file into this parser object. - bool LoadFile(const std::string& file_name); + bool LoadFile(absl::string_view file_name); // Returns the name of the instance being solved. const std::string& name() const { return name_; } @@ -211,7 +212,7 @@ class NearpParser { }; void Initialize(); - bool ParseFile(const std::string& file_name); + bool ParseFile(absl::string_view file_name); bool ParseMetadataLine(const std::vector& words); bool ParseArc(std::string_view line, bool with_servicing); bool ParseEdge(std::string_view line, bool with_servicing); @@ -252,6 +253,6 @@ class NearpParser { int num_vehicles_; int64_t capacity_; }; -} // namespace operations_research +} // namespace operations_research::routing #endif // OR_TOOLS_ROUTING_PARSERS_NEARP_PARSER_H_ diff --git a/ortools/routing/parsers/nearp_parser_test.cc b/ortools/routing/parsers/nearp_parser_test.cc index d28abd65f2..160caebe55 100644 --- a/ortools/routing/parsers/nearp_parser_test.cc +++ b/ortools/routing/parsers/nearp_parser_test.cc @@ -15,20 +15,13 @@ #include -#include "absl/flags/flag.h" #include "gtest/gtest.h" #include "ortools/base/path.h" #include "ortools/routing/parsers/simple_graph.h" -#if defined(_MSC_VER) -#define ROOT_DIR "../../../../../../../" -#else -#define ROOT_DIR -#endif // _MSC_VER +#define ROOT_DIR "_main/" -ABSL_FLAG(std::string, test_srcdir, "", "REQUIRED: src dir"); - -namespace operations_research { +namespace operations_research::routing { namespace { TEST(NearpParserTest, Constructor) { NearpParser parser; @@ -55,10 +48,9 @@ TEST(NearpParserTest, LoadNonExistingFile) { } TEST(NearpParserTest, LoadBHW1) { - std::string file_name = - file::JoinPath(absl::GetFlag(FLAGS_test_srcdir), ROOT_DIR - "ortools/routing/parsers/testdata/" - "nearp_BHW1.dat"); + std::string file_name = file::JoinPath(::testing::SrcDir(), ROOT_DIR + "ortools/routing/parsers/testdata/" + "nearp_BHW1.dat"); NearpParser parser; EXPECT_TRUE(parser.LoadFile(file_name)); EXPECT_EQ(parser.name(), "BHW1"); @@ -97,10 +89,9 @@ TEST(NearpParserTest, LoadBHW1) { } TEST(NearpParserTest, LoadToy) { - std::string file_name = - file::JoinPath(absl::GetFlag(FLAGS_test_srcdir), ROOT_DIR - "ortools/routing/parsers/" - "testdata/nearp_toy.dat"); + std::string file_name = file::JoinPath(::testing::SrcDir(), ROOT_DIR + "ortools/routing/parsers/" + "testdata/nearp_toy.dat"); NearpParser parser; EXPECT_TRUE(parser.LoadFile(file_name)); EXPECT_EQ(parser.name(), "Toy"); @@ -139,4 +130,4 @@ TEST(NearpParserTest, LoadToy) { EXPECT_EQ(parser.GetNodeName(3), "N4"); } } // namespace -} // namespace operations_research +} // namespace operations_research::routing diff --git a/ortools/routing/parsers/pdtsp_parser.cc b/ortools/routing/parsers/pdtsp_parser.cc index 426c2ab511..e291fe644a 100644 --- a/ortools/routing/parsers/pdtsp_parser.cc +++ b/ortools/routing/parsers/pdtsp_parser.cc @@ -26,7 +26,7 @@ #include "ortools/base/strtoint.h" #include "ortools/util/filelineiter.h" -namespace operations_research { +namespace operations_research::routing { namespace { using absl::ByAnyChar; @@ -43,7 +43,7 @@ File* OpenReadOnly(absl::string_view file_name) { PdTspParser::PdTspParser() : section_(SIZE_SECTION) {} -bool PdTspParser::LoadFile(const std::string& file_name) { +bool PdTspParser::LoadFile(absl::string_view file_name) { for (const std::string& line : FileLines(file_name, FileLineIterator::REMOVE_INLINE_CR)) { ProcessNewLine(line); @@ -104,4 +104,4 @@ void PdTspParser::ProcessNewLine(const std::string& line) { } } -} // namespace operations_research +} // namespace operations_research::routing diff --git a/ortools/routing/parsers/pdtsp_parser.h b/ortools/routing/parsers/pdtsp_parser.h index 2039c68463..fcb56d1af9 100644 --- a/ortools/routing/parsers/pdtsp_parser.h +++ b/ortools/routing/parsers/pdtsp_parser.h @@ -22,16 +22,17 @@ #include #include +#include "absl/strings/string_view.h" #include "ortools/base/types.h" -namespace operations_research { +namespace operations_research::routing { class PdTspParser { public: PdTspParser(); ~PdTspParser() = default; // Loads and parse a PDTSP from a given file. - bool LoadFile(const std::string& file_name); + bool LoadFile(absl::string_view file_name); // Returns the index of the depot. int depot() const { return depot_; } // Returns the number of nodes in the PDTSP. @@ -54,6 +55,6 @@ class PdTspParser { std::vector deliveries_; }; -} // namespace operations_research +} // namespace operations_research::routing #endif // OR_TOOLS_ROUTING_PARSERS_PDTSP_PARSER_H_ diff --git a/ortools/routing/parsers/pdtsp_parser_test.cc b/ortools/routing/parsers/pdtsp_parser_test.cc index b2ced79f49..1c34658602 100644 --- a/ortools/routing/parsers/pdtsp_parser_test.cc +++ b/ortools/routing/parsers/pdtsp_parser_test.cc @@ -17,19 +17,12 @@ #include #include -#include "absl/flags/flag.h" #include "gtest/gtest.h" #include "ortools/base/path.h" -#if defined(_MSC_VER) -#define ROOT_DIR "../../../../../../../" -#else -#define ROOT_DIR -#endif // _MSC_VER +#define ROOT_DIR "_main/" -ABSL_FLAG(std::string, test_srcdir, "", "REQUIRED: src dir"); - -namespace operations_research { +namespace operations_research::routing { namespace { TEST(PdTspParserTest, LoadDataSet) { for (const std::string& data : { @@ -37,8 +30,7 @@ TEST(PdTspParserTest, LoadDataSet) { "pdtsp_prob10b.txt", }) { PdTspParser parser; - EXPECT_TRUE(parser.LoadFile( - file::JoinPath(absl::GetFlag(FLAGS_test_srcdir), data))); + EXPECT_TRUE(parser.LoadFile(file::JoinPath(::testing::SrcDir(), data))); EXPECT_EQ(0, parser.depot()); EXPECT_EQ(21, parser.Size()); EXPECT_FALSE(parser.IsPickup(0)); // depot @@ -53,4 +45,4 @@ TEST(PdTspParserTest, LoadDataSet) { } } } // namespace -} // namespace operations_research +} // namespace operations_research::routing diff --git a/ortools/routing/parsers/simple_graph.cc b/ortools/routing/parsers/simple_graph.cc index b5d95d35a7..1ee3d99cbc 100644 --- a/ortools/routing/parsers/simple_graph.cc +++ b/ortools/routing/parsers/simple_graph.cc @@ -13,9 +13,9 @@ #include "ortools/routing/parsers/simple_graph.h" -namespace operations_research { +namespace operations_research::routing { Edge::Edge(const Arc& arc) : tail_(arc.tail()), head_(arc.head()) {} Arc::Arc(const Edge& edge) : tail_(edge.tail()), head_(edge.head()) {} -} // namespace operations_research +} // namespace operations_research::routing diff --git a/ortools/routing/parsers/simple_graph.h b/ortools/routing/parsers/simple_graph.h index 13dc5d0eed..6ac9d6a9b1 100644 --- a/ortools/routing/parsers/simple_graph.h +++ b/ortools/routing/parsers/simple_graph.h @@ -23,7 +23,7 @@ #include "absl/hash/hash.h" -namespace operations_research { +namespace operations_research::routing { class Arc; @@ -150,6 +150,6 @@ struct SimpleTimeWindow { T end; }; -} // namespace operations_research +} // namespace operations_research::routing #endif // OR_TOOLS_ROUTING_PARSERS_SIMPLE_GRAPH_H_ diff --git a/ortools/routing/parsers/simple_graph_test.cc b/ortools/routing/parsers/simple_graph_test.cc index 88c6846b26..75adb23585 100644 --- a/ortools/routing/parsers/simple_graph_test.cc +++ b/ortools/routing/parsers/simple_graph_test.cc @@ -19,7 +19,7 @@ #include "absl/hash/hash_testing.h" #include "gtest/gtest.h" -namespace operations_research { +namespace operations_research::routing { namespace { TEST(SimpleGraphTest, EdgeHashing) { EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({ @@ -100,4 +100,4 @@ TEST(Coordinates3Test, Double) { Coordinates3(1.0, 2.0, 3.0)})); } } // namespace -} // namespace operations_research +} // namespace operations_research::routing diff --git a/ortools/routing/parsers/solomon_parser.cc b/ortools/routing/parsers/solomon_parser.cc index 00d2ebc4cb..936a1c8a7f 100644 --- a/ortools/routing/parsers/solomon_parser.cc +++ b/ortools/routing/parsers/solomon_parser.cc @@ -18,25 +18,27 @@ #include #include +#include "absl/strings/ascii.h" #include "absl/strings/match.h" +#include "absl/strings/str_join.h" #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" #include "ortools/base/logging.h" #include "ortools/base/map_util.h" #include "ortools/base/numbers.h" #include "ortools/base/path.h" -#include "ortools/base/types.h" #include "ortools/base/zipfile.h" #include "ortools/util/filelineiter.h" +#include "re2/re2.h" -namespace operations_research { +namespace operations_research::routing { SolomonParser::SolomonParser() : sections_({{"VEHICLE", VEHICLE}, {"CUSTOMER", CUSTOMER}}) { Initialize(); } -bool SolomonParser::LoadFile(const std::string& file_name) { +bool SolomonParser::LoadFile(absl::string_view file_name) { Initialize(); return ParseFile(file_name); } @@ -67,7 +69,7 @@ void SolomonParser::Initialize() { to_read_ = 1; } -bool SolomonParser::ParseFile(const std::string& file_name) { +bool SolomonParser::ParseFile(absl::string_view file_name) { for (const std::string& line : FileLines(file_name, FileLineIterator::REMOVE_INLINE_CR)) { const std::vector words = @@ -135,4 +137,46 @@ bool SolomonParser::ParseFile(const std::string& file_name) { return section_ == CUSTOMER; } -} // namespace operations_research +SolomonSolutionParser::SolomonSolutionParser() { Initialize(); } + +bool SolomonSolutionParser::LoadFile(absl::string_view file_name) { + Initialize(); + return ParseFile(file_name); +} + +void SolomonSolutionParser::Initialize() { + routes_.clear(); + key_values_.clear(); +} + +bool SolomonSolutionParser::ParseFile(absl::string_view file_name) { + bool success = false; + for (const std::string& line : + FileLines(file_name, FileLineIterator::REMOVE_INLINE_CR)) { + success = true; + const std::vector words = + absl::StrSplit(line, ':', absl::SkipEmpty()); + // Skip blank lines + if (words.empty()) continue; + std::string key = words[0]; + std::string value = words.size() > 1 + ? absl::StrJoin(words.begin() + 1, words.end(), ":") + : ""; + if (!RE2::FullMatch(key, "Route\\s*(\\d+)\\s*")) { + absl::StripAsciiWhitespace(&key); + absl::StripAsciiWhitespace(&value); + key_values_[key] = value; + // Note: the "Solution" key will be captured here. That key has no actual + // usefulness and serves as a separator before reading routes. + continue; + } + routes_.push_back(std::vector()); + for (const auto item : + absl::StrSplit(value, absl::ByAnyChar(" \t"), absl::SkipEmpty())) { + routes_.back().push_back(strings::ParseLeadingInt32Value(item, -1)); + } + } + return success; +} + +} // namespace operations_research::routing diff --git a/ortools/routing/parsers/solomon_parser.h b/ortools/routing/parsers/solomon_parser.h index d02a7e357d..e4de718f02 100644 --- a/ortools/routing/parsers/solomon_parser.h +++ b/ortools/routing/parsers/solomon_parser.h @@ -49,12 +49,11 @@ #include #include +#include "absl/container/flat_hash_map.h" #include "absl/strings/string_view.h" -#include "ortools/base/macros.h" -#include "ortools/base/types.h" #include "ortools/routing/parsers/simple_graph.h" -namespace operations_research { +namespace operations_research::routing { // Solomon parser class. class SolomonParser { @@ -70,7 +69,7 @@ class SolomonParser { // the instance. Loading a new instance clears the previously loaded instance. // Loads instance from a file. - bool LoadFile(const std::string& file_name); + bool LoadFile(absl::string_view file_name); // Loads instance from a file contained in a zipped archive; the archive can // contain multiple files. bool LoadFile(absl::string_view file_name, const std::string& archive_name); @@ -115,7 +114,7 @@ class SolomonParser { // Parsing void Initialize(); - bool ParseFile(const std::string& file_name); + bool ParseFile(absl::string_view file_name); // Parsing data const std::map sections_; @@ -134,6 +133,45 @@ class SolomonParser { std::vector> time_windows_; std::vector service_times_; }; -} // namespace operations_research + +// Solomon solution parser class. +class SolomonSolutionParser { + public: + SolomonSolutionParser(); + +#ifndef SWIG + SolomonSolutionParser(const SolomonSolutionParser&) = delete; + const SolomonSolutionParser& operator=(const SolomonSolutionParser&) = delete; +#endif + + // Loads solution from a file. Returns false in case of failure to read + // the file. Loading a new solution clears the previously loaded solution. + bool LoadFile(absl::string_view file_name); + + // Returns the number of routes used in the solution. + int NumberOfRoutes() const { return routes_.size(); } + // Returns the sequence of the ith route, excluding depot nodes. + const std::vector& route(int i) const { return routes_[i]; } + // Returns the value corresponding to a key. Keys can be (but are not limited + // to) "Authors", "Date", "Instance Name", or "Reference". These keys might + // vary slightly per instance (refer to the input file). + const std::string& GetValueFromKey(absl::string_view key) const { + static const std::string* default_value = new std::string{}; + auto it = key_values_.find(key); + if (it != key_values_.end()) return it->second; + return *default_value; + } + + private: + // Parsing + void Initialize(); + bool ParseFile(absl::string_view file_name); + + // Parsing data + std::vector> routes_; + absl::flat_hash_map key_values_; +}; + +} // namespace operations_research::routing #endif // OR_TOOLS_ROUTING_PARSERS_SOLOMON_PARSER_H_ diff --git a/ortools/routing/parsers/solomon_parser_test.cc b/ortools/routing/parsers/solomon_parser_test.cc index e9426ac60f..a56bd81842 100644 --- a/ortools/routing/parsers/solomon_parser_test.cc +++ b/ortools/routing/parsers/solomon_parser_test.cc @@ -18,9 +18,10 @@ #include "absl/flags/flag.h" #include "gtest/gtest.h" #include "ortools/base/commandlineflags.h" +#include "ortools/base/gmock.h" #include "ortools/base/path.h" -ABSL_FLAG(std::string, test_srcdir, "", "REQUIRED: src dir"); +#define ROOT_DIR "_main/" ABSL_FLAG(std::string, solomon_test_archive, "ortools/bench/solomon/" @@ -29,7 +30,7 @@ ABSL_FLAG(std::string, solomon_test_archive, ABSL_FLAG(std::string, solomon_test_instance, "google2.txt", "Solomon: testing instance"); -namespace operations_research { +namespace operations_research::routing { namespace { TEST(SolomonParserTest, LoadEmptyFileName) { std::string empty_file_name; @@ -58,8 +59,40 @@ TEST(SolomonParserTest, LoadNonExistingInstance) { SolomonParser parser; EXPECT_FALSE(parser.LoadFile( "doesnotexist.txt", - file::JoinPath(absl::GetFlag(FLAGS_test_srcdir), + file::JoinPath(::testing::SrcDir(), absl::GetFlag(FLAGS_solomon_test_archive)))); } + +TEST(SolomonSolutionParserTest, LoadEmptyFileName) { + std::string empty_file_name; + SolomonSolutionParser parser; + EXPECT_FALSE(parser.LoadFile(empty_file_name)); +} + +TEST(SolomonSolutionParserTest, LoadNonExistingFile) { + SolomonSolutionParser parser; + EXPECT_FALSE(parser.LoadFile("")); +} + +TEST(SolomonSolutionParserTest, LoadFile) { + SolomonSolutionParser parser; + EXPECT_TRUE(parser.LoadFile(file::JoinPath(::testing::SrcDir(), ROOT_DIR + "ortools/routing/parsers/testdata/" + "c1_10_2-90-42222.96.txt"))); + EXPECT_EQ(parser.NumberOfRoutes(), 90); + EXPECT_EQ(parser.GetValueFromKey("Instance Name"), "c1_10_2"); + EXPECT_EQ( + parser.GetValueFromKey("Authors"), + "Zhu He, Longfei Wang, Weibo Lin, Yujie Chen, Haoyuan Hu " + "(haoyuan.huhy@cainiao.com), Yinghui Xu & VRP Team (Ying Zhang, Guotao " + "Wu, Kunpeng Han et al.), unpublished result of CAINIAO AI."); + EXPECT_EQ(parser.GetValueFromKey("Date"), "05-10-2018"); + EXPECT_EQ(parser.GetValueFromKey("Reference"), + "\"New Algorithm for VRPTW\", unpublished result of CAINIAO AI."); + EXPECT_EQ(parser.GetValueFromKey("NonExistingKey"), ""); + EXPECT_THAT(parser.route(0), ::testing::ElementsAre(1, 987, 466, 279, 31, 276, + 263, 207, 646, 193, 3)); +} + } // namespace -} // namespace operations_research +} // namespace operations_research::routing diff --git a/ortools/routing/parsers/solution_serializer.cc b/ortools/routing/parsers/solution_serializer.cc index 5be2974aca..1beade35c2 100644 --- a/ortools/routing/parsers/solution_serializer.cc +++ b/ortools/routing/parsers/solution_serializer.cc @@ -25,7 +25,7 @@ #include "absl/types/span.h" #include "ortools/base/logging.h" -namespace operations_research { +namespace operations_research::routing { RoutingOutputFormat RoutingOutputFormatFromString(std::string_view format) { const std::string format_normalized = @@ -45,7 +45,7 @@ std::vector RoutesFromVector( } // namespace std::vector> RoutingSolution::SplitRoutes( - const std::vector& solution, int64_t separator) { + absl::Span solution, int64_t separator) { // The solution vector separates routes by -1: split this vector into a vector // per route, where the other helpers can make the rest of the way to a proper // RoutingSolution object. @@ -384,7 +384,7 @@ std::string SerializeRouteToCVRPLIBString(const RoutingSolution::Route& route) { // Before serializing the route, make some tests to check that the hypotheses // are respected (otherwise, the output of the function is highly likely // pure garbage). - RoutingSolution::Event first_event = route[0]; + const RoutingSolution::Event& first_event = route[0]; CHECK(first_event.type == RoutingSolution::Event::Type::kStart) << "The route does not begin with a Start event to indicate " "the depot."; @@ -397,7 +397,7 @@ std::string SerializeRouteToCVRPLIBString(const RoutingSolution::Route& route) { std::string current_route; for (int64_t i = 1; i < route.size() - 1; ++i) { - RoutingSolution::Event event = route[i]; + const RoutingSolution::Event& event = route[i]; // Ignore the depot, as CVRPLIB doesn't output the depot in the routes // (all routes implicitly start and end at the depot). @@ -410,7 +410,7 @@ std::string SerializeRouteToCVRPLIBString(const RoutingSolution::Route& route) { // Last event: end at a depot. Due to the strange way CVRPLIB // outputs nodes, the depot must be the same at the beginning and the // end of the route. - RoutingSolution::Event last_event = route.back(); + const RoutingSolution::Event& last_event = route.back(); if (last_event.type == RoutingSolution::Event::Type::kEnd) { CHECK_EQ(depot, last_event.arc.tail()); CHECK_EQ(last_event.arc.tail(), last_event.arc.head()); @@ -422,4 +422,4 @@ std::string SerializeRouteToCVRPLIBString(const RoutingSolution::Route& route) { return current_route; } } // namespace -} // namespace operations_research +} // namespace operations_research::routing diff --git a/ortools/routing/parsers/solution_serializer.h b/ortools/routing/parsers/solution_serializer.h index 874093bab4..a9b9239fad 100644 --- a/ortools/routing/parsers/solution_serializer.h +++ b/ortools/routing/parsers/solution_serializer.h @@ -32,7 +32,7 @@ #include "ortools/base/logging.h" #include "ortools/routing/parsers/simple_graph.h" -namespace operations_research { +namespace operations_research::routing { // Indicates the format in which the output should be done. This enumeration is // used for solutions and solver statistics. @@ -137,7 +137,7 @@ class RoutingSolution { // (TSPLIB uses -1; it is crucial that the separator cannot be a node) into // a vector per route, for use in FromSplit* functions. static std::vector> SplitRoutes( - const std::vector& solution, int64_t separator); + absl::Span solution, int64_t separator); // Builds a RoutingSolution object from a vector of routes, each represented // as a vector of nodes being traversed. All the routes are supposed to start @@ -291,6 +291,6 @@ void PrintStatistic(absl::string_view name, T value, RoutingOutputFormat format) { absl::PrintF("%s\n", FormatStatistic(name, value, format)); } -} // namespace operations_research +} // namespace operations_research::routing #endif // OR_TOOLS_ROUTING_PARSERS_SOLUTION_SERIALIZER_H_ diff --git a/ortools/routing/parsers/solution_serializer_test.cc b/ortools/routing/parsers/solution_serializer_test.cc index 726f143496..795ab304c2 100644 --- a/ortools/routing/parsers/solution_serializer_test.cc +++ b/ortools/routing/parsers/solution_serializer_test.cc @@ -28,7 +28,7 @@ #include "ortools/base/options.h" #include "ortools/routing/parsers/simple_graph.h" -namespace operations_research { +namespace operations_research::routing { namespace { using testing::MatchesRegex; @@ -629,4 +629,4 @@ TEST(RoutingSolutionSerializerTest, FormatStatisticAsNearplibLongPrecision) { "STAT : 591.556557"); } } // namespace -} // namespace operations_research +} // namespace operations_research::routing diff --git a/ortools/routing/parsers/testdata/BUILD.bazel b/ortools/routing/parsers/testdata/BUILD.bazel index c82b516dc4..11c136e5ab 100644 --- a/ortools/routing/parsers/testdata/BUILD.bazel +++ b/ortools/routing/parsers/testdata/BUILD.bazel @@ -12,6 +12,7 @@ # limitations under the License. exports_files([ + "c1_10_2-90-42222.96.txt", "carp_gdb19.dat", # https://github.com/vidalt/HGS-CARP/blob/master/Instances/CARP/gdb19.dat # https://www.sciencedirect.com/science/article/abs/pii/0305054883900266 "carp_gdb19_diferente_deposito.dat", diff --git a/ortools/routing/parsers/testdata/C1_10_2.TXT b/ortools/routing/parsers/testdata/C1_10_2.TXT new file mode 100644 index 0000000000..5ebcf051eb --- /dev/null +++ b/ortools/routing/parsers/testdata/C1_10_2.TXT @@ -0,0 +1,1010 @@ +c1_10_2 + +VEHICLE +NUMBER CAPACITY + 250 200 + +CUSTOMER +CUST NO. XCOORD. YCOORD. DEMAND READY TIME DUE DATE SERVICE TIME + + 0 250 250 0 0 1824 0 + 1 387 297 10 200 270 90 + 2 5 297 10 955 1017 90 + 3 355 177 20 0 1607 90 + 4 78 346 30 355 403 90 + 5 286 159 20 530 597 90 + 6 322 465 10 226 291 90 + 7 393 408 30 0 1521 90 + 8 89 216 10 495 562 90 + 9 76 345 30 0 1536 90 + 10 410 285 20 499 556 90 + 11 472 189 30 0 1504 90 + 12 270 49 30 925 970 90 + 13 219 325 10 520 563 90 + 14 437 12 20 557 613 90 + 15 418 218 20 974 1030 90 + 16 20 488 10 754 820 90 + 17 77 347 20 436 505 90 + 18 73 346 10 726 772 90 + 19 480 455 10 1123 1179 90 + 20 129 292 10 552 610 90 + 21 337 257 20 805 863 90 + 22 237 254 20 0 1721 90 + 23 131 220 30 0 1612 90 + 24 417 417 10 954 1020 90 + 25 287 143 10 748 793 90 + 26 379 80 20 737 789 90 + 27 87 285 30 709 764 90 + 28 374 489 20 269 339 90 + 29 440 247 20 717 779 90 + 30 281 137 10 370 416 90 + 31 379 196 20 665 714 90 + 32 297 102 10 214 281 90 + 33 39 76 10 328 399 90 + 34 35 306 20 369 440 90 + 35 435 68 10 0 1475 90 + 36 245 251 10 60 130 90 + 37 409 88 20 655 715 90 + 38 273 55 20 196 246 90 + 39 163 340 30 468 513 90 + 40 129 223 20 274 340 90 + 41 371 200 10 0 1604 90 + 42 357 26 20 0 1486 90 + 43 470 473 10 1221 1270 90 + 44 77 344 10 254 319 90 + 45 478 461 10 462 529 90 + 46 128 291 10 639 706 90 + 47 111 113 10 632 694 90 + 48 164 21 20 578 639 90 + 49 21 485 30 487 540 90 + 50 108 26 10 423 491 90 + 51 424 286 10 0 1557 90 + 52 200 270 20 0 1681 90 + 53 7 300 30 1056 1104 90 + 54 433 31 10 285 333 90 + 55 420 295 20 0 1559 90 + 56 451 367 20 1134 1195 90 + 57 118 157 20 403 465 90 + 58 489 101 20 0 1453 90 + 59 200 261 10 945 1017 90 + 60 476 483 10 657 722 90 + 61 30 302 10 572 632 90 + 62 8 300 10 1131 1211 90 + 63 275 45 20 444 515 90 + 64 238 46 40 735 784 90 + 65 152 206 10 910 973 90 + 66 99 218 30 154 205 90 + 67 393 410 20 913 982 90 + 68 480 460 20 549 627 90 + 69 337 256 20 154 201 90 + 70 389 300 10 0 1587 90 + 71 90 237 20 0 1574 90 + 72 321 280 30 143 194 90 + 73 417 218 10 0 1564 90 + 74 64 108 10 473 539 90 + 75 57 432 10 973 1033 90 + 76 356 24 20 249 323 90 + 77 143 207 30 0 1619 90 + 78 221 325 10 0 1654 90 + 79 22 483 30 325 389 90 + 80 24 65 10 0 1442 90 + 81 141 431 30 362 423 90 + 82 202 9 10 0 1489 90 + 83 20 48 10 1294 1358 90 + 84 457 163 20 284 346 90 + 85 470 290 10 835 895 90 + 86 268 400 20 869 928 90 + 87 337 251 10 0 1647 90 + 88 366 20 10 874 927 90 + 89 72 344 20 0 1533 90 + 90 149 203 10 553 597 90 + 91 55 428 20 511 568 90 + 92 189 7 30 0 1484 90 + 93 397 18 10 519 575 90 + 94 481 122 30 607 653 90 + 95 20 73 10 0 1444 90 + 96 54 430 20 610 652 90 + 97 74 350 10 915 955 90 + 98 202 8 10 0 1488 90 + 99 406 285 20 0 1575 90 + 100 460 2 20 655 720 90 + 101 441 244 10 909 955 90 + 102 1 293 10 0 1482 90 + 103 115 465 10 409 465 90 + 104 422 420 20 0 1493 90 + 105 75 347 10 810 872 90 + 106 141 428 20 0 1526 90 + 107 404 264 20 395 462 90 + 108 398 23 10 270 334 90 + 109 148 211 20 167 233 90 + 110 362 22 20 1050 1121 90 + 111 479 127 20 412 478 90 + 112 443 246 20 536 593 90 + 113 22 37 10 0 1422 90 + 114 65 100 10 763 811 90 + 115 404 447 20 250 280 90 + 116 102 264 10 148 215 90 + 117 444 271 10 633 688 90 + 118 325 466 40 0 1506 90 + 119 124 219 20 571 615 90 + 120 335 243 20 428 495 90 + 121 26 42 20 455 519 90 + 122 113 106 20 198 260 90 + 123 399 450 20 971 1056 90 + 124 146 439 10 642 707 90 + 125 162 336 20 0 1611 90 + 126 2 295 30 774 828 90 + 127 122 35 10 0 1484 90 + 128 346 60 10 1027 1086 90 + 129 93 213 30 0 1573 90 + 130 218 316 20 73 134 90 + 131 116 156 10 495 557 90 + 132 419 422 20 0 1493 90 + 133 467 141 10 0 1492 90 + 134 187 491 20 771 854 90 + 135 433 25 20 0 1444 90 + 136 286 137 10 0 1616 90 + 137 370 82 40 0 1528 90 + 138 132 290 10 818 898 90 + 139 435 11 40 0 1432 90 + 140 206 261 10 1050 1104 90 + 141 428 291 10 698 764 90 + 142 95 384 30 719 785 90 + 143 205 223 20 491 544 90 + 144 463 140 10 295 366 90 + 145 343 47 20 0 1511 90 + 146 435 62 30 1156 1218 90 + 147 387 488 20 987 1046 90 + 148 121 157 10 220 279 90 + 149 182 463 30 372 440 90 + 150 92 216 10 0 1573 90 + 151 370 83 20 357 419 90 + 152 444 242 10 441 501 90 + 153 90 285 40 981 1042 90 + 154 446 64 10 600 665 90 + 155 312 264 20 131 179 90 + 156 208 11 20 0 1492 90 + 157 442 247 10 623 689 90 + 158 140 431 30 280 324 90 + 159 118 153 30 949 1028 90 + 160 134 428 20 935 992 90 + 161 91 235 10 1140 1188 90 + 162 406 257 10 0 1578 90 + 163 377 76 20 638 699 90 + 164 474 96 30 271 327 90 + 165 346 57 20 0 1519 90 + 166 393 301 30 482 545 90 + 167 412 214 10 165 215 90 + 168 210 398 10 592 647 90 + 169 346 150 20 948 998 90 + 170 62 453 10 515 584 90 + 171 437 61 10 1063 1127 90 + 172 87 96 30 0 1510 90 + 173 367 83 30 0 1531 90 + 174 91 268 10 869 931 90 + 175 459 145 40 233 291 90 + 176 63 444 20 1084 1146 90 + 177 433 27 20 628 694 90 + 178 60 454 10 892 952 90 + 179 478 99 10 0 1461 90 + 180 485 454 10 0 1423 90 + 181 6 292 10 316 360 90 + 182 398 20 20 333 394 90 + 183 248 251 20 2 63 90 + 184 433 15 20 297 344 90 + 185 64 426 10 1162 1223 90 + 186 154 207 20 0 1629 90 + 187 481 456 40 1028 1091 90 + 188 380 498 10 523 582 90 + 189 88 286 10 795 859 90 + 190 111 23 10 266 326 90 + 191 199 187 20 433 490 90 + 192 269 48 20 0 1532 90 + 193 367 178 20 0 1597 90 + 194 452 163 30 0 1515 90 + 195 431 28 20 0 1448 90 + 196 8 116 20 894 957 90 + 197 233 47 20 356 415 90 + 198 237 43 20 631 702 90 + 199 320 262 10 585 656 90 + 200 188 4 20 413 455 90 + 201 180 6 10 0 1481 90 + 202 328 466 30 847 906 90 + 203 393 12 10 0 1457 90 + 204 409 90 20 0 1509 90 + 205 406 87 10 936 999 90 + 206 394 407 20 733 789 90 + 207 358 183 20 932 1005 90 + 208 186 461 20 220 284 90 + 209 38 72 30 420 496 90 + 210 323 471 30 0 1502 90 + 211 224 192 10 215 274 90 + 212 278 46 20 205 269 90 + 213 272 403 30 494 555 90 + 214 232 42 10 545 599 90 + 215 18 63 10 716 792 90 + 216 58 458 10 702 774 90 + 217 416 417 20 1057 1099 90 + 218 205 230 30 203 263 90 + 219 65 453 30 423 490 90 + 220 421 294 10 883 953 90 + 221 434 245 10 1377 1416 90 + 222 2 116 20 526 586 90 + 223 411 421 20 862 917 90 + 224 315 260 10 223 278 90 + 225 136 288 10 1023 1063 90 + 226 173 490 20 406 462 90 + 227 90 232 10 682 732 90 + 228 402 265 20 306 365 90 + 229 361 14 10 686 738 90 + 230 348 147 10 845 914 90 + 231 385 295 20 0 1592 90 + 232 394 23 20 1271 1326 90 + 233 466 295 20 0 1514 90 + 234 71 103 20 0 1503 90 + 235 125 29 30 0 1481 90 + 236 25 65 10 1005 1057 90 + 237 58 449 30 993 1042 90 + 238 246 398 40 148 199 90 + 239 423 294 10 0 1556 90 + 240 59 459 20 0 1451 90 + 241 348 145 20 763 813 90 + 242 477 97 10 421 495 90 + 243 307 102 40 0 1576 90 + 244 169 31 20 0 1501 90 + 245 381 495 20 705 769 90 + 246 95 234 10 315 362 90 + 247 22 33 10 735 803 90 + 248 435 268 10 1100 1154 90 + 249 135 293 30 0 1612 90 + 250 439 266 10 0 1545 90 + 251 269 402 20 587 648 90 + 252 267 400 10 779 836 90 + 253 473 196 10 564 642 90 + 254 445 237 10 349 402 90 + 255 461 284 10 275 340 90 + 256 167 339 10 648 710 90 + 257 26 43 10 365 427 90 + 258 101 386 20 349 415 90 + 259 342 54 20 553 616 90 + 260 243 399 10 782 837 90 + 261 288 44 20 0 1525 90 + 262 274 48 10 368 405 90 + 263 360 184 10 846 906 90 + 264 23 67 30 0 1443 90 + 265 6 296 10 863 926 90 + 266 249 258 30 910 974 90 + 267 421 415 30 297 364 90 + 268 319 468 10 289 353 90 + 269 50 438 20 0 1460 90 + 270 440 61 30 971 1032 90 + 271 17 65 20 625 699 90 + 272 323 118 20 0 1584 90 + 273 402 281 20 886 924 90 + 274 71 153 20 746 816 90 + 275 52 432 20 789 843 90 + 276 378 199 10 761 804 90 + 277 238 204 20 566 634 90 + 278 208 184 20 146 192 90 + 279 376 195 10 576 616 90 + 280 473 475 10 0 1418 90 + 281 215 395 20 865 928 90 + 282 123 222 30 376 430 90 + 283 436 241 20 1271 1333 90 + 284 70 100 10 1119 1191 90 + 285 73 328 20 193 270 90 + 286 241 205 30 0 1689 90 + 287 250 405 20 303 370 90 + 288 483 14 10 0 1403 90 + 289 466 287 10 467 525 90 + 290 467 114 10 1159 1223 90 + 291 120 159 10 306 377 90 + 292 408 84 10 745 814 90 + 293 413 217 20 230 289 90 + 294 338 142 40 204 256 90 + 295 483 457 20 735 811 90 + 296 479 169 20 774 834 90 + 297 95 224 20 0 1577 90 + 298 122 216 10 461 537 90 + 299 477 179 20 0 1497 90 + 300 406 99 20 367 438 90 + 301 44 47 20 0 1445 90 + 302 487 450 10 929 993 90 + 303 172 488 10 310 374 90 + 304 460 374 20 753 831 90 + 305 279 138 40 281 320 90 + 306 338 147 10 135 193 90 + 307 395 295 20 677 736 90 + 308 195 185 20 335 399 90 + 309 463 194 20 220 279 90 + 310 30 72 10 0 1452 90 + 311 244 254 20 723 787 90 + 312 317 261 20 398 473 90 + 313 67 108 10 297 346 90 + 314 442 310 20 643 698 90 + 315 63 336 20 822 861 90 + 316 109 107 20 357 416 90 + 317 100 387 10 0 1531 90 + 318 494 94 10 634 692 90 + 319 343 49 10 650 710 90 + 320 40 52 40 546 591 90 + 321 319 124 20 400 465 90 + 322 94 97 20 285 334 90 + 323 476 94 20 334 396 90 + 324 283 47 10 373 420 90 + 325 398 325 30 774 843 90 + 326 460 13 20 0 1418 90 + 327 305 107 20 0 1581 90 + 328 188 12 30 245 309 90 + 329 136 290 20 272 332 90 + 330 439 268 10 0 1545 90 + 331 112 467 10 505 557 90 + 332 181 469 20 468 536 90 + 333 358 18 10 0 1479 90 + 334 459 10 10 0 1416 90 + 335 199 268 20 284 368 90 + 336 436 237 20 186 264 90 + 337 318 280 20 319 384 90 + 338 64 99 10 853 904 90 + 339 394 333 20 0 1568 90 + 340 366 93 20 936 989 90 + 341 95 391 10 909 973 90 + 342 391 425 20 842 909 90 + 343 344 146 10 496 529 90 + 344 198 12 10 582 631 90 + 345 186 472 20 564 633 90 + 346 390 408 30 0 1523 90 + 347 19 43 20 1203 1259 90 + 348 307 108 10 777 847 90 + 349 59 457 30 810 848 90 + 350 49 451 20 340 409 90 + 351 125 39 20 245 318 90 + 352 61 147 40 0 1519 90 + 353 317 123 20 497 554 90 + 354 392 426 10 666 722 90 + 355 237 213 10 846 917 90 + 356 71 333 10 0 1537 90 + 357 304 97 20 407 466 90 + 358 196 462 10 955 1003 90 + 359 224 191 20 312 359 90 + 360 37 51 10 0 1443 90 + 361 491 25 10 0 1405 90 + 362 270 401 20 217 268 90 + 363 474 461 30 307 379 90 + 364 66 448 10 270 345 90 + 365 337 241 20 0 1647 90 + 366 269 46 20 733 794 90 + 367 22 41 10 1110 1164 90 + 368 198 271 20 0 1678 90 + 369 287 43 10 555 609 90 + 370 446 63 20 697 750 90 + 371 200 229 30 301 355 90 + 372 48 72 30 711 768 90 + 373 465 142 10 0 1494 90 + 374 123 155 10 1143 1209 90 + 375 16 497 20 1038 1123 90 + 376 220 319 30 971 1037 90 + 377 484 171 10 680 736 90 + 378 55 431 20 694 752 90 + 379 428 24 10 0 1447 90 + 380 80 342 10 193 275 90 + 381 16 68 20 521 617 90 + 382 124 56 20 0 1503 90 + 383 95 218 20 873 927 90 + 384 481 26 30 0 1413 90 + 385 145 434 20 462 514 90 + 386 335 57 30 210 261 90 + 387 26 490 10 1345 1394 90 + 388 324 127 30 143 200 90 + 389 109 114 10 829 871 90 + 390 72 148 20 0 1529 90 + 391 220 392 20 970 1015 90 + 392 442 243 10 996 1052 90 + 393 69 336 20 440 507 90 + 394 131 226 20 121 183 90 + 395 150 204 20 639 694 90 + 396 423 217 20 785 849 90 + 397 419 459 20 785 838 90 + 398 285 163 10 714 780 90 + 399 203 7 20 1033 1108 90 + 400 54 445 10 534 593 90 + 401 109 463 30 0 1479 90 + 402 355 180 30 279 345 90 + 403 13 455 10 381 430 90 + 404 165 337 20 0 1613 90 + 405 314 124 20 0 1593 90 + 406 9 124 20 271 336 90 + 407 3 292 20 404 457 90 + 408 16 462 10 935 986 90 + 409 189 464 10 856 906 90 + 410 288 154 10 442 494 90 + 411 90 296 20 0 1568 90 + 412 138 438 20 832 893 90 + 413 13 459 20 646 718 90 + 414 461 8 20 0 1413 90 + 415 96 97 20 217 280 90 + 416 68 99 10 1040 1085 90 + 417 146 205 10 0 1621 90 + 418 117 152 20 0 1569 90 + 419 481 96 20 526 577 90 + 420 338 260 20 0 1646 90 + 421 285 44 10 0 1526 90 + 422 111 464 10 775 837 90 + 423 468 291 30 748 798 90 + 424 148 206 20 458 506 90 + 425 184 464 10 285 344 90 + 426 197 11 10 0 1490 90 + 427 396 410 10 829 880 90 + 428 133 53 20 668 720 90 + 429 132 30 20 875 926 90 + 430 464 13 20 853 906 90 + 431 100 394 10 0 1527 90 + 432 483 22 10 476 543 90 + 433 93 235 10 951 1012 90 + 434 174 26 10 1037 1105 90 + 435 436 264 20 0 1548 90 + 436 24 492 10 1252 1302 90 + 437 406 94 10 375 430 90 + 438 234 246 10 0 1718 90 + 439 315 287 30 693 754 90 + 440 408 453 10 0 1477 90 + 441 128 225 10 0 1610 90 + 442 226 191 20 397 459 90 + 443 391 407 10 0 1523 90 + 444 198 264 20 770 821 90 + 445 179 7 20 864 930 90 + 446 425 215 10 699 748 90 + 447 483 27 20 1322 1384 90 + 448 22 40 30 1012 1080 90 + 449 479 176 20 0 1494 90 + 450 476 102 20 797 866 90 + 451 386 405 20 206 266 90 + 452 22 38 20 929 980 90 + 453 440 241 10 0 1544 90 + 454 182 14 10 1062 1116 90 + 455 266 405 20 680 745 90 + 456 357 181 20 367 441 90 + 457 395 332 10 593 648 90 + 458 423 290 10 0 1557 90 + 459 104 28 20 0 1469 90 + 460 131 56 10 0 1507 90 + 461 111 110 20 550 590 90 + 462 97 93 20 0 1515 90 + 463 90 274 20 411 458 90 + 464 214 394 10 0 1586 90 + 465 6 114 10 0 1455 90 + 466 375 191 30 473 531 90 + 467 356 21 20 414 452 90 + 468 466 165 30 747 805 90 + 469 415 223 20 1257 1302 90 + 470 397 20 20 433 477 90 + 471 241 403 10 686 744 90 + 472 69 334 30 0 1535 90 + 473 152 210 20 105 163 90 + 474 67 335 20 629 684 90 + 475 126 30 10 495 558 90 + 476 390 423 10 290 336 90 + 477 285 162 30 625 688 90 + 478 285 158 30 340 405 90 + 479 406 96 20 280 342 90 + 480 459 374 20 848 917 90 + 481 67 109 20 388 438 90 + 482 468 475 10 313 373 90 + 483 438 31 10 348 413 90 + 484 168 24 10 770 816 90 + 485 267 394 10 962 1027 90 + 486 406 450 20 405 464 90 + 487 460 288 10 213 265 90 + 488 224 203 20 0 1681 90 + 489 21 487 10 582 629 90 + 490 21 488 10 0 1404 90 + 491 87 217 10 0 1568 90 + 492 67 452 30 327 402 90 + 493 119 223 10 853 906 90 + 494 398 428 10 0 1503 90 + 495 344 262 20 0 1640 90 + 496 390 301 10 0 1585 90 + 497 167 27 30 487 536 90 + 498 236 247 20 0 1720 90 + 499 313 119 30 679 742 90 + 500 13 51 10 1366 1425 90 + 501 200 13 10 397 453 90 + 502 0 120 30 431 492 90 + 503 202 4 10 950 1004 90 + 504 343 144 10 0 1593 90 + 505 94 383 10 636 687 90 + 506 250 411 30 492 554 90 + 507 464 134 20 0 1491 90 + 508 443 237 20 248 318 90 + 509 4 114 10 712 769 90 + 510 169 336 30 838 892 90 + 511 200 178 20 240 298 90 + 512 412 453 10 0 1475 90 + 513 121 151 20 0 1572 90 + 514 403 93 10 1131 1181 90 + 515 399 301 30 584 634 90 + 516 97 387 10 823 869 90 + 517 176 8 10 0 1481 90 + 518 62 326 20 0 1532 90 + 519 151 207 10 0 1627 90 + 520 299 98 30 320 364 90 + 521 334 240 30 0 1650 90 + 522 92 270 20 954 1029 90 + 523 444 269 20 0 1540 90 + 524 132 223 30 0 1613 90 + 525 428 25 20 1175 1251 90 + 526 413 421 10 768 828 90 + 527 382 498 10 619 669 90 + 528 391 429 20 0 1507 90 + 529 398 97 10 264 344 90 + 530 192 265 10 678 721 90 + 531 438 26 10 0 1442 90 + 532 44 79 10 267 333 90 + 533 137 290 10 176 245 90 + 534 446 319 30 364 416 90 + 535 175 487 20 248 308 90 + 536 26 45 30 0 1431 90 + 537 147 435 20 553 607 90 + 538 111 459 20 0 1483 90 + 539 472 132 10 767 826 90 + 540 349 158 20 1050 1093 90 + 541 86 268 10 689 735 90 + 542 415 216 10 319 384 90 + 543 121 218 20 191 257 90 + 544 210 185 20 0 1658 90 + 545 98 215 20 218 278 90 + 546 484 174 10 0 1488 90 + 547 328 458 10 0 1512 90 + 548 313 126 10 873 923 90 + 549 390 415 20 0 1518 90 + 550 459 17 20 1039 1094 90 + 551 481 124 10 505 571 90 + 552 386 414 10 1109 1162 90 + 553 116 466 20 318 373 90 + 554 468 295 10 934 987 90 + 555 391 426 10 0 1509 90 + 556 408 279 20 682 747 90 + 557 15 68 10 448 508 90 + 558 392 424 10 926 1007 90 + 559 88 95 20 658 712 90 + 560 116 151 20 774 836 90 + 561 240 250 10 0 1724 90 + 562 123 159 20 156 216 90 + 563 89 290 20 225 300 90 + 564 39 50 30 440 511 90 + 565 359 179 20 465 529 90 + 566 338 257 20 0 1646 90 + 567 92 236 20 1041 1104 90 + 568 413 417 10 1135 1207 90 + 569 91 101 10 0 1517 90 + 570 55 449 20 0 1456 90 + 571 57 425 20 260 317 90 + 572 465 287 10 556 617 90 + 573 320 280 10 221 298 90 + 574 322 468 20 575 625 90 + 575 483 458 10 656 708 90 + 576 312 267 10 862 941 90 + 577 139 291 10 118 187 90 + 578 388 408 10 361 425 90 + 579 110 459 30 0 1483 90 + 580 459 372 20 0 1492 90 + 581 204 269 30 49 98 90 + 582 407 98 10 0 1516 90 + 583 335 256 10 890 962 90 + 584 471 484 10 0 1413 90 + 585 339 244 30 251 299 90 + 586 89 272 10 498 555 90 + 587 488 96 10 909 973 90 + 588 316 286 30 601 662 90 + 589 235 50 30 813 896 90 + 590 316 258 20 0 1668 90 + 591 425 288 10 0 1555 90 + 592 213 397 10 680 744 90 + 593 113 156 10 0 1568 90 + 594 199 9 20 853 911 90 + 595 463 167 10 657 709 90 + 596 129 27 10 680 745 90 + 597 248 404 30 214 274 90 + 598 405 276 20 771 848 90 + 599 400 288 30 154 232 90 + 600 61 156 30 462 532 90 + 601 393 20 20 1190 1222 90 + 602 484 177 20 390 463 90 + 603 108 116 30 911 973 90 + 604 112 217 20 383 443 90 + 605 389 404 10 267 331 90 + 606 102 391 20 1098 1161 90 + 607 434 26 10 0 1445 90 + 608 488 26 30 0 1408 90 + 609 477 120 10 968 1026 90 + 610 126 220 20 0 1607 90 + 611 439 310 10 198 256 90 + 612 212 319 30 0 1656 90 + 613 320 283 30 421 471 90 + 614 17 459 10 1200 1275 90 + 615 236 213 20 0 1695 90 + 616 68 108 10 230 324 90 + 617 390 294 20 853 931 90 + 618 275 42 30 537 608 90 + 619 423 214 20 0 1558 90 + 620 460 367 20 392 450 90 + 621 272 402 10 317 353 90 + 622 478 102 10 704 775 90 + 623 400 260 40 150 212 90 + 624 181 6 20 678 753 90 + 625 470 475 30 381 429 90 + 626 245 408 10 585 652 90 + 627 93 96 20 374 427 90 + 628 218 318 20 884 939 90 + 629 441 265 40 344 400 90 + 630 21 64 20 818 876 90 + 631 356 23 20 309 373 90 + 632 267 44 20 649 693 90 + 633 277 50 10 0 1533 90 + 634 182 4 10 586 659 90 + 635 26 36 10 646 702 90 + 636 384 491 20 897 948 90 + 637 418 290 10 1172 1221 90 + 638 321 277 10 75 140 90 + 639 358 16 30 596 641 90 + 640 389 334 20 0 1572 90 + 641 48 78 20 0 1469 90 + 642 24 68 20 1282 1337 90 + 643 206 225 10 0 1684 90 + 644 290 141 30 645 709 90 + 645 439 15 20 650 706 90 + 646 359 182 20 0 1606 90 + 647 413 287 10 1348 1417 90 + 648 230 49 20 201 253 90 + 649 407 280 10 595 653 90 + 650 459 295 20 1209 1273 90 + 651 468 199 20 669 730 90 + 652 101 384 30 200 262 90 + 653 170 26 10 855 918 90 + 654 197 270 30 474 548 90 + 655 415 289 20 169 228 90 + 656 203 390 40 307 361 90 + 657 443 272 10 821 869 90 + 658 210 391 30 202 272 90 + 659 363 22 20 964 1025 90 + 660 352 176 20 126 175 90 + 661 212 223 40 758 832 90 + 662 8 120 10 1169 1232 90 + 663 244 250 10 0 1728 90 + 664 18 484 10 397 444 90 + 665 379 82 10 827 884 90 + 666 84 346 20 1095 1157 90 + 667 233 207 10 105 167 90 + 668 344 62 10 1208 1274 90 + 669 20 489 10 856 901 90 + 670 361 181 20 662 723 90 + 671 174 494 10 0 1479 90 + 672 49 76 20 0 1469 90 + 673 390 325 30 883 929 90 + 674 7 118 20 0 1458 90 + 675 107 26 10 0 1469 90 + 676 312 270 30 0 1669 90 + 677 399 102 20 0 1524 90 + 678 109 108 10 0 1534 90 + 679 115 218 10 298 341 90 + 680 88 287 30 0 1568 90 + 681 54 424 10 320 387 90 + 682 125 32 30 407 462 90 + 683 199 12 20 475 557 90 + 684 457 374 10 0 1493 90 + 685 391 413 10 1013 1069 90 + 686 304 102 30 505 559 90 + 687 391 293 20 768 834 90 + 688 66 336 10 719 778 90 + 689 132 291 10 0 1610 90 + 690 18 462 20 0 1420 90 + 691 347 62 10 1121 1176 90 + 692 466 142 10 0 1493 90 + 693 389 17 10 993 1049 90 + 694 342 254 10 0 1642 90 + 695 92 223 10 0 1574 90 + 696 404 83 30 831 916 90 + 697 290 46 20 832 896 90 + 698 95 92 20 0 1513 90 + 699 200 265 10 853 922 90 + 700 435 16 10 829 895 90 + 701 25 499 10 1154 1206 90 + 702 319 260 20 489 566 90 + 703 116 225 20 752 820 90 + 704 402 284 30 313 367 90 + 705 108 105 20 258 329 90 + 706 386 13 10 785 878 90 + 707 472 129 10 312 383 90 + 708 132 57 20 396 443 90 + 709 43 71 40 525 581 90 + 710 493 91 30 542 599 90 + 711 12 451 20 0 1423 90 + 712 201 188 10 526 581 90 + 713 60 428 20 1059 1137 90 + 714 243 248 30 243 314 90 + 715 230 197 40 588 645 90 + 716 389 11 20 707 769 90 + 717 401 281 20 968 1024 90 + 718 459 14 20 372 439 90 + 719 411 95 30 475 521 90 + 720 0 297 10 679 737 90 + 721 476 196 30 476 544 90 + 722 458 16 20 313 369 90 + 723 92 230 20 0 1575 90 + 724 432 24 20 1000 1056 90 + 725 215 317 10 140 194 90 + 726 371 192 30 190 259 90 + 727 481 20 20 572 631 90 + 728 152 207 20 824 877 90 + 729 14 459 20 559 622 90 + 730 361 17 20 777 832 90 + 731 8 497 40 959 1006 90 + 732 206 186 10 891 955 90 + 733 421 218 10 880 939 90 + 734 402 264 20 216 273 90 + 735 388 325 10 971 1026 90 + 736 35 304 30 280 345 90 + 737 321 263 20 680 743 90 + 738 444 313 20 462 511 90 + 739 188 462 40 0 1514 90 + 740 400 103 10 546 636 90 + 741 418 221 10 1150 1223 90 + 742 112 219 20 469 541 90 + 743 408 452 10 490 564 90 + 744 30 301 10 660 726 90 + 745 205 228 10 110 173 90 + 746 407 88 10 1035 1083 90 + 747 380 489 20 1084 1143 90 + 748 395 331 20 690 734 90 + 749 133 26 10 0 1482 90 + 750 21 68 20 1189 1243 90 + 751 313 282 20 790 847 90 + 752 53 440 10 633 684 90 + 753 458 130 20 0 1494 90 + 754 437 15 30 0 1434 90 + 755 400 286 10 217 276 90 + 756 346 144 10 0 1591 90 + 757 440 244 10 809 874 90 + 758 280 162 30 158 210 90 + 759 488 173 20 0 1484 90 + 760 326 118 10 213 272 90 + 761 207 400 20 489 562 90 + 762 391 18 10 1085 1141 90 + 763 37 55 10 730 780 90 + 764 204 15 20 0 1495 90 + 765 173 28 10 1134 1191 90 + 766 343 148 20 399 441 90 + 767 231 43 10 447 513 90 + 768 445 273 20 725 781 90 + 769 432 27 10 810 878 90 + 770 439 305 30 0 1538 90 + 771 208 396 20 401 462 90 + 772 249 407 10 403 455 90 + 773 107 112 30 728 787 90 + 774 279 159 20 252 301 90 + 775 376 494 30 334 396 90 + 776 403 262 30 493 547 90 + 777 41 47 20 359 406 90 + 778 96 213 30 0 1576 90 + 779 461 167 10 470 531 90 + 780 391 99 20 206 268 90 + 781 116 221 30 571 627 90 + 782 165 343 10 556 613 90 + 783 388 334 20 227 280 90 + 784 130 57 40 289 365 90 + 785 422 409 10 234 290 90 + 786 66 156 10 653 718 90 + 787 485 86 20 349 413 90 + 788 389 428 20 380 435 90 + 789 117 467 10 254 307 90 + 790 475 477 20 1028 1091 90 + 791 429 27 20 1272 1339 90 + 792 339 60 20 274 338 90 + 793 381 494 10 801 855 90 + 794 218 321 20 697 759 90 + 795 64 101 20 667 724 90 + 796 343 254 20 334 394 90 + 797 478 464 10 0 1422 90 + 798 423 286 20 430 477 90 + 799 198 9 20 763 819 90 + 800 225 196 10 128 174 90 + 801 374 190 20 292 344 90 + 802 462 14 20 0 1417 90 + 803 347 54 10 836 904 90 + 804 231 195 20 497 552 90 + 805 72 96 20 1220 1278 90 + 806 489 87 20 451 499 90 + 807 443 313 30 554 602 90 + 808 233 204 20 198 260 90 + 809 477 483 20 745 817 90 + 810 459 368 10 299 361 90 + 811 95 277 20 1057 1121 90 + 812 16 460 20 1112 1180 90 + 813 100 266 20 207 275 90 + 814 288 53 40 925 997 90 + 815 211 386 20 141 212 90 + 816 144 439 30 736 797 90 + 817 224 314 10 0 1665 90 + 818 79 291 10 519 568 90 + 819 95 235 10 155 227 90 + 820 7 123 30 329 399 90 + 821 91 217 10 692 738 90 + 822 105 27 10 0 1469 90 + 823 101 385 20 262 320 90 + 824 238 210 30 757 821 90 + 825 439 67 10 322 386 90 + 826 435 267 20 1188 1247 90 + 827 443 64 30 779 854 90 + 828 92 234 10 0 1576 90 + 829 450 265 10 0 1534 90 + 830 102 27 20 796 852 90 + 831 492 94 10 724 787 90 + 832 440 63 20 886 934 90 + 833 453 367 20 0 1500 90 + 834 15 69 10 0 1438 90 + 835 489 17 10 764 826 90 + 836 335 255 20 85 124 90 + 837 419 418 10 394 454 90 + 838 292 41 10 733 804 90 + 839 489 27 10 0 1408 90 + 840 96 270 20 308 367 90 + 841 461 369 10 579 633 90 + 842 105 22 30 339 385 90 + 843 479 121 10 0 1472 90 + 844 207 223 10 585 634 90 + 845 17 458 10 1297 1360 90 + 846 186 7 20 500 555 90 + 847 465 168 10 837 902 90 + 848 416 288 20 1251 1328 90 + 849 388 418 10 217 283 90 + 850 92 233 10 768 830 90 + 851 179 492 10 678 752 90 + 852 132 55 10 573 632 90 + 853 485 24 20 0 1408 90 + 854 388 331 20 160 230 90 + 855 217 323 20 424 473 90 + 856 281 164 20 91 140 90 + 857 169 340 10 737 806 90 + 858 491 20 20 0 1401 90 + 859 279 42 40 0 1524 90 + 860 439 243 20 0 1545 90 + 861 391 334 20 402 470 90 + 862 96 244 10 1332 1380 90 + 863 441 273 20 903 972 90 + 864 477 478 20 942 993 90 + 865 56 434 20 0 1467 90 + 866 12 463 20 0 1415 90 + 867 458 164 20 374 439 90 + 868 446 65 20 516 566 90 + 869 71 156 10 0 1532 90 + 870 65 153 30 570 614 90 + 871 8 118 20 1079 1138 90 + 872 102 29 30 0 1469 90 + 873 315 265 10 774 841 90 + 874 343 62 10 1300 1364 90 + 875 384 16 20 892 959 90 + 876 67 105 10 579 622 90 + 877 478 118 20 1058 1121 90 + 878 73 101 20 1313 1375 90 + 879 200 14 10 311 356 90 + 880 114 225 30 0 1596 90 + 881 460 293 30 1121 1176 90 + 882 51 447 10 438 501 90 + 883 418 295 20 1063 1140 90 + 884 282 139 20 188 227 90 + 885 477 122 10 886 924 90 + 886 91 266 10 0 1575 90 + 887 16 463 20 836 904 90 + 888 228 199 10 673 746 90 + 889 435 20 20 0 1439 90 + 890 467 195 10 285 344 90 + 891 469 132 10 856 923 90 + 892 465 136 30 964 1007 90 + 893 246 255 10 818 877 90 + 894 49 75 20 810 857 90 + 895 66 98 20 944 996 90 + 896 166 32 10 296 352 90 + 897 326 466 30 753 817 90 + 898 202 186 20 616 676 90 + 899 467 285 20 0 1515 90 + 900 290 136 20 0 1614 90 + 901 341 58 10 0 1522 90 + 902 121 219 20 132 203 90 + 903 107 35 30 986 1041 90 + 904 216 319 10 321 387 90 + 905 134 288 20 923 979 90 + 906 89 270 10 590 647 90 + 907 136 52 10 759 817 90 + 908 462 167 20 0 1507 90 + 909 340 54 10 0 1519 90 + 910 80 286 10 0 1561 90 + 911 38 301 20 0 1516 90 + 912 25 307 10 0 1502 90 + 913 470 139 10 668 731 90 + 914 270 400 10 151 213 90 + 915 204 187 30 803 857 90 + 916 460 171 30 937 994 90 + 917 399 106 20 925 989 90 + 918 197 267 10 582 626 90 + 919 77 350 10 997 1058 90 + 920 91 231 30 579 652 90 + 921 398 103 30 739 807 90 + 922 35 303 20 0 1513 90 + 923 231 204 20 0 1685 90 + 924 311 266 10 63 126 90 + 925 416 420 20 0 1497 90 + 926 231 203 20 291 352 90 + 927 4 116 10 618 678 90 + 928 417 217 30 0 1564 90 + 929 268 52 10 1003 1079 90 + 930 345 144 30 568 640 90 + 931 368 85 30 0 1532 90 + 932 441 65 10 0 1469 90 + 933 201 270 10 108 177 90 + 934 0 293 30 591 637 90 + 935 167 24 20 668 736 90 + 936 186 464 10 0 1511 90 + 937 7 292 10 246 306 90 + 938 80 290 10 420 484 90 + 939 405 455 40 883 948 90 + 940 439 312 30 257 324 90 + 941 300 108 10 150 211 90 + 942 478 121 40 788 840 90 + 943 92 232 10 0 1575 90 + 944 111 463 20 0 1480 90 + 945 132 294 20 454 521 90 + 946 134 285 20 1104 1168 90 + 947 316 284 20 510 570 90 + 948 56 428 20 415 482 90 + 949 232 47 10 262 327 90 + 950 466 291 10 656 705 90 + 951 341 257 20 0 1643 90 + 952 420 213 10 509 568 90 + 953 116 152 20 678 750 90 + 954 163 337 10 277 334 90 + 955 440 7 20 0 1426 90 + 956 208 222 30 667 734 90 + 957 485 95 10 281 351 90 + 958 97 385 30 537 598 90 + 959 462 367 20 481 545 90 + 960 455 365 20 235 306 90 + 961 492 95 30 0 1447 90 + 962 405 450 20 311 376 90 + 963 371 193 20 133 185 90 + 964 234 202 10 0 1684 90 + 965 404 103 20 0 1522 90 + 966 24 41 10 557 601 90 + 967 67 334 20 532 600 90 + 968 207 227 10 0 1686 90 + 969 277 403 10 395 464 90 + 970 15 457 20 462 534 90 + 971 217 319 10 0 1658 90 + 972 111 467 20 597 647 90 + 973 378 493 30 426 487 90 + 974 112 465 10 685 743 90 + 975 173 25 20 952 1007 90 + 976 421 292 20 245 287 90 + 977 74 146 30 0 1530 90 + 978 178 491 10 0 1483 90 + 979 204 185 20 0 1655 90 + 980 319 470 10 0 1504 90 + 981 163 331 40 118 179 90 + 982 470 125 20 253 316 90 + 983 315 121 10 590 647 90 + 984 166 34 20 0 1503 90 + 985 284 140 40 115 172 90 + 986 85 288 20 329 386 90 + 987 376 190 30 382 439 90 + 988 238 203 10 0 1686 90 + 989 399 104 10 834 896 90 + 990 472 481 20 477 527 90 + 991 46 74 20 612 682 90 + 992 401 255 30 685 738 90 + 993 475 480 30 837 911 90 + 994 485 27 10 1231 1291 90 + 995 476 174 30 874 924 90 + 996 330 242 30 627 671 90 + 997 332 249 30 82 144 90 + 998 375 80 10 550 598 90 + 999 94 235 20 227 266 90 + 1000 287 144 20 0 1622 90 diff --git a/ortools/routing/parsers/testdata/c1_10_2-90-42222.96.txt b/ortools/routing/parsers/testdata/c1_10_2-90-42222.96.txt new file mode 100644 index 0000000000..8bc6b6aa7a --- /dev/null +++ b/ortools/routing/parsers/testdata/c1_10_2-90-42222.96.txt @@ -0,0 +1,95 @@ +Instance Name: c1_10_2 +Authors: Zhu He, Longfei Wang, Weibo Lin, Yujie Chen, Haoyuan Hu (haoyuan.huhy@cainiao.com), Yinghui Xu & VRP Team (Ying Zhang, Guotao Wu, Kunpeng Han et al.), unpublished result of CAINIAO AI. +Date: 05-10-2018 +Reference: "New Algorithm for VRPTW", unpublished result of CAINIAO AI. +Solution +Route 1 : 1 987 466 279 31 276 263 207 646 193 3 +Route 2 : 854 783 861 166 515 307 687 617 496 70 +Route 3 : 28 775 973 188 527 245 793 636 147 747 547 +Route 4 : 35 825 932 868 154 370 827 832 270 171 146 +Route 5 : 36 714 945 20 46 703 493 610 23 524 968 +Route 6 : 38 633 262 63 618 632 366 192 12 929 988 +Route 7 : 54 483 531 334 100 414 430 326 550 802 853 447 +Route 8 : 66 545 557 381 271 215 630 264 750 834 95 +Route 9 : 76 631 467 333 639 229 730 88 659 110 42 +Route 10 : 79 664 49 489 490 16 669 731 375 701 436 387 +Route 11 : 106 158 81 385 537 124 816 412 160 +Route 12 : 108 182 470 93 203 716 706 875 693 762 601 232 165 +Route 13 : 115 962 486 743 440 512 397 939 123 494 549 +Route 14 : 116 563 986 938 818 27 189 174 522 886 862 880 441 +Route 15 : 122 777 564 320 301 763 360 236 80 642 310 +Route 16 : 130 725 612 904 855 13 794 971 628 438 498 561 663 +Route 17 : 164 323 242 419 622 942 885 609 877 290 753 +Route 18 : 167 84 867 779 908 595 468 847 916 194 41 +Route 19 : 175 144 551 94 913 539 891 892 507 133 692 373 +Route 20 : 183 745 218 371 643 143 844 956 661 +Route 21 : 184 139 955 14 645 754 700 889 195 +Route 22 : 190 842 50 596 830 872 903 459 822 675 984 +Route 23 : 208 425 149 332 851 134 409 358 978 671 936 739 +Route 24 : 212 859 324 421 369 261 838 697 814 327 +Route 25 : 238 597 287 772 506 626 471 260 376 817 +Route 26 : 244 896 200 846 634 624 201 445 517 454 92 764 +Route 27 : 278 511 308 424 90 395 77 728 65 519 186 +Route 28 : 285 736 34 922 61 744 911 680 153 +Route 29 : 306 479 437 719 177 607 769 135 724 379 525 791 +Route 30 : 309 890 602 721 253 651 11 829 523 250 435 +Route 31 : 328 879 501 683 344 426 799 594 503 399 98 82 156 +Route 32 : 336 508 254 152 112 157 29 757 101 392 453 860 283 221 +Route 33 : 351 682 475 852 428 907 429 749 235 127 382 460 +Route 34 : 363 45 68 575 295 180 302 187 19 580 833 +Route 35 : 364 492 219 170 240 216 349 178 237 176 +Route 36 : 380 44 4 17 18 105 811 943 723 297 695 778 +Route 37 : 386 792 901 909 259 319 145 803 128 691 668 874 173 +Route 38 : 388 760 151 137 998 163 26 665 340 756 504 +Route 39 : 394 813 840 463 586 906 541 138 905 225 946 249 +Route 40 : 402 766 343 930 921 989 917 677 931 +Route 41 : 406 820 502 222 927 509 465 196 674 871 662 +Route 42 : 415 322 627 461 47 773 389 603 977 593 +Route 43 : 451 605 578 457 748 325 673 735 637 848 647 99 +Route 44 : 473 109 40 282 298 119 821 491 383 150 129 +Route 45 : 482 625 990 584 60 809 993 864 790 280 43 797 +Route 46 : 487 255 899 289 572 950 423 85 554 233 881 650 458 +Route 47 : 532 33 209 709 991 372 894 672 641 +Route 48 : 535 303 226 345 897 202 210 118 +Route 49 : 536 257 121 966 635 247 113 452 448 367 347 83 500 +Route 50 : 562 148 291 57 131 559 172 569 698 462 678 513 +Route 51 : 570 350 882 400 752 269 97 919 666 9 89 356 689 +Route 52 : 571 681 948 91 96 378 275 865 75 713 185 431 +Route 53 : 577 533 329 393 967 474 688 315 472 518 411 +Route 54 : 581 933 52 335 368 654 918 530 444 699 59 140 +Route 55 : 6 268 980 574 206 427 67 339 231 495 420 590 +Route 56 : 611 940 534 738 117 768 657 863 330 248 826 162 +Route 57 : 616 313 481 74 876 795 114 338 895 416 284 805 878 234 +Route 58 : 599 755 704 798 10 649 556 273 717 566 +Route 59 : 638 72 573 337 613 947 588 439 751 +Route 60 : 648 949 197 767 214 198 64 589 243 +Route 61 : 652 823 258 317 958 505 142 516 341 606 +Route 62 : 655 976 629 807 314 141 239 220 55 883 +Route 63 : 660 294 321 353 983 499 348 548 405 272 +Route 64 : 667 808 926 191 712 898 979 915 732 544 488 +Route 65 : 705 316 600 870 786 274 390 352 869 +Route 66 : 711 403 970 729 413 866 887 408 690 812 614 845 +Route 67 : 722 718 432 727 288 835 858 361 839 608 994 384 +Route 68 : 780 529 300 740 37 292 696 205 746 514 204 582 965 +Route 69 : 784 708 497 48 935 484 653 975 434 765 964 +Route 70 : 785 267 837 104 132 925 526 223 24 217 568 640 +Route 71 : 789 553 103 331 972 974 422 944 401 579 538 78 +Route 72 : 815 658 656 771 761 168 592 464 281 391 +Route 73 : 819 999 246 742 781 953 560 418 159 374 417 +Route 74 : 836 293 542 928 952 446 396 733 15 73 741 469 694 +Route 75 : 849 476 788 528 354 555 342 558 685 552 346 7 443 +Route 76 : 623 734 228 107 776 992 598 951 +Route 77 : 856 758 774 478 410 5 477 398 286 +Route 78 : 902 543 679 604 8 920 227 850 828 433 567 161 71 +Route 79 : 914 362 621 969 213 251 455 252 86 485 +Route 80 : 923 800 211 359 442 804 715 311 893 266 +Route 81 : 924 155 224 312 702 199 737 21 583 87 365 521 +Route 82 : 937 181 407 102 934 720 126 265 2 53 62 912 910 +Route 83 : 941 32 520 357 686 644 25 136 900 1000 +Route 84 : 957 787 806 710 318 831 450 587 961 58 179 843 +Route 85 : 960 810 620 959 841 304 480 684 56 770 591 51 +Route 86 : 963 726 801 456 565 670 241 230 169 540 +Route 87 : 981 125 954 404 39 782 256 857 510 22 +Route 88 : 982 707 111 759 377 296 995 546 449 299 619 +Route 89 : 985 884 305 30 277 888 824 355 615 +Route 90 : 997 69 585 796 120 996 873 576 676 diff --git a/ortools/routing/parsers/tsplib_parser.cc b/ortools/routing/parsers/tsplib_parser.cc index cb5b6af5ee..6c67f04f02 100644 --- a/ortools/routing/parsers/tsplib_parser.cc +++ b/ortools/routing/parsers/tsplib_parser.cc @@ -36,7 +36,7 @@ #include "ortools/util/filelineiter.h" #include "re2/re2.h" -namespace operations_research { +namespace operations_research::routing { namespace { // ----- Distances ----- @@ -171,7 +171,7 @@ TspLibParser::TspLibParser() edge_column_(0), to_read_(0) {} -bool TspLibParser::LoadFile(const std::string& file_name) { +bool TspLibParser::LoadFile(absl::string_view file_name) { std::shared_ptr zip_archive( OpenZipArchiveIfItExists(file_name)); for (const std::string& line : @@ -182,7 +182,7 @@ bool TspLibParser::LoadFile(const std::string& file_name) { return true; } -int TspLibParser::SizeFromFile(const std::string& file_name) const { +int TspLibParser::SizeFromFile(absl::string_view file_name) const { std::shared_ptr zip_archive( OpenZipArchiveIfItExists(file_name)); int size = 0; @@ -747,7 +747,7 @@ TspLibTourParser::TspLibTourParser() : section_(UNDEFINED_SECTION), size_(0) {} // TODO(user): Return false when issues were encountered while parsing the // file. -bool TspLibTourParser::LoadFile(const std::string& file_name) { +bool TspLibTourParser::LoadFile(absl::string_view file_name) { section_ = UNDEFINED_SECTION; comments_.clear(); tour_.clear(); @@ -818,7 +818,7 @@ CVRPToursParser::CVRPToursParser() : cost_(0) {} // TODO(user): Return false when issues were encountered while parsing the // file. -bool CVRPToursParser::LoadFile(const std::string& file_name) { +bool CVRPToursParser::LoadFile(absl::string_view file_name) { tours_.clear(); cost_ = 0; std::shared_ptr zip_archive( @@ -852,4 +852,4 @@ void CVRPToursParser::ProcessNewLine(const std::string& line) { } } -} // namespace operations_research +} // namespace operations_research::routing diff --git a/ortools/routing/parsers/tsplib_parser.h b/ortools/routing/parsers/tsplib_parser.h index 774fa552cb..a2f80c4881 100644 --- a/ortools/routing/parsers/tsplib_parser.h +++ b/ortools/routing/parsers/tsplib_parser.h @@ -31,11 +31,12 @@ #include #include "absl/container/flat_hash_map.h" +#include "absl/strings/string_view.h" #include "absl/types/span.h" #include "ortools/base/types.h" #include "ortools/routing/parsers/simple_graph.h" -namespace operations_research { +namespace operations_research::routing { class TspLibParser final { public: @@ -44,9 +45,9 @@ class TspLibParser final { TspLibParser(); // Loads and parses a routing problem from a given file. - bool LoadFile(const std::string& file_name); + bool LoadFile(absl::string_view file_name); // Returns the number of nodes in the routing problem stored in a given file. - int SizeFromFile(const std::string& file_name) const; + int SizeFromFile(absl::string_view file_name) const; // Returns a function returning edge weights between nodes. EdgeWeights GetEdgeWeights() const { return distance_function_; } // Returns the index of the depot. @@ -197,7 +198,7 @@ class TspLibTourParser final { public: TspLibTourParser(); // Loads and parses a given tour file. - bool LoadFile(const std::string& file_name); + bool LoadFile(absl::string_view file_name); // Returns a vector corresponding to the sequence of nodes of the tour. const std::vector& tour() const { return tour_; } // Returns the size of the tour. @@ -236,7 +237,7 @@ class CVRPToursParser final { public: CVRPToursParser(); // Loads and parses a given tours file. - bool LoadFile(const std::string& file_name); + bool LoadFile(absl::string_view file_name); // Returns a vector corresponding to the sequence of nodes of tours. const std::vector>& tours() const { return tours_; } int64_t cost() const { return cost_; } @@ -247,6 +248,6 @@ class CVRPToursParser final { std::vector> tours_; int64_t cost_; }; -} // namespace operations_research +} // namespace operations_research::routing #endif // OR_TOOLS_ROUTING_PARSERS_TSPLIB_PARSER_H_ diff --git a/ortools/routing/parsers/tsplib_parser_test.cc b/ortools/routing/parsers/tsplib_parser_test.cc index 089ba721c2..64115a8eba 100644 --- a/ortools/routing/parsers/tsplib_parser_test.cc +++ b/ortools/routing/parsers/tsplib_parser_test.cc @@ -21,7 +21,6 @@ #include "absl/base/macros.h" #include "absl/container/btree_set.h" -#include "absl/flags/flag.h" #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "gtest/gtest.h" @@ -31,15 +30,9 @@ #include "ortools/base/path.h" #include "ortools/base/zipfile.h" -#if defined(_MSC_VER) -#define ROOT_DIR "../../../../../../../" -#else -#define ROOT_DIR -#endif // _MSC_VER +#define ROOT_DIR "_main/" -ABSL_FLAG(std::string, test_srcdir, "", "REQUIRED: src dir"); - -namespace operations_research { +namespace operations_research::routing { namespace { TEST(TspLibParserTest, GeneratedDataSets) { @@ -251,8 +244,8 @@ TEST(TspLibParserTest, ParseHCPAdjList) { TEST(TspLibParserTest, ParseKytojoki33Depot) { // This file inverts EDGE_WEIGHT_TYPE and EDGE_WEIGHT_FORMAT. std::string file_name = file::JoinPath( - absl::GetFlag(FLAGS_test_srcdir), - ROOT_DIR "ortools/routing/parsers/testdata/", "tsplib_Kytojoki_33.vrp"); + ::testing::SrcDir(), ROOT_DIR "ortools/routing/parsers/testdata/", + "tsplib_Kytojoki_33.vrp"); TspLibParser parser; EXPECT_TRUE(parser.LoadFile(file_name)); // The depot is a new node, given by its coordinates, instead of an existing @@ -301,8 +294,8 @@ TEST(TspLibTourParserTest, LoadAllDataSets) { ": Optimal solution of ulysses22 (7013)"}; int file_index = 0; std::vector matches; - if (file::Match(file::JoinPath("/tarfs", absl::GetFlag(FLAGS_test_srcdir), - kArchive, "*\\.opt\\.tour\\.gz"), + if (file::Match(file::JoinPath("/tarfs", ::testing::SrcDir(), kArchive, + "*\\.opt\\.tour\\.gz"), &matches, file::Defaults()) .ok()) { for (const std::string& match : matches) { @@ -336,9 +329,9 @@ TEST(CVRPToursParserTest, LoadAllDataSets) { /*opt-A-n55-k9*/ 1073}; int file_index = 0; std::vector matches; - if (file::Match(file::JoinPath("/zip", absl::GetFlag(FLAGS_test_srcdir), - kArchive, "opt-A-\\.*"), - &matches, file::Defaults()) + if (file::Match( + file::JoinPath("/zip", ::testing::SrcDir(), kArchive, "opt-A-\\.*"), + &matches, file::Defaults()) .ok()) { for (const std::string& match : matches) { CVRPToursParser parser; @@ -349,4 +342,4 @@ TEST(CVRPToursParserTest, LoadAllDataSets) { } } } // namespace -} // namespace operations_research +} // namespace operations_research::routing diff --git a/ortools/routing/parsers/tsptw_parser.cc b/ortools/routing/parsers/tsptw_parser.cc index 208a3bf64e..5f767b7500 100644 --- a/ortools/routing/parsers/tsptw_parser.cc +++ b/ortools/routing/parsers/tsptw_parser.cc @@ -29,7 +29,7 @@ #include "ortools/base/zipfile.h" #include "ortools/util/filelineiter.h" -namespace operations_research { +namespace operations_research::routing { namespace { @@ -66,7 +66,7 @@ TspTWParser::TspTWParser() distance_function_(nullptr), time_function_(nullptr) {} -bool TspTWParser::LoadFile(const std::string& file_name) { +bool TspTWParser::LoadFile(absl::string_view file_name) { std::shared_ptr zip_archive( OpenZipArchiveIfItExists(file_name)); coords_.clear(); @@ -81,7 +81,7 @@ bool TspTWParser::LoadFile(const std::string& file_name) { return ParseLopezIbanezBlum(file_name) || ParseDaSilvaUrrutia(file_name); } -bool TspTWParser::ParseLopezIbanezBlum(const std::string& file_name) { +bool TspTWParser::ParseLopezIbanezBlum(absl::string_view file_name) { int section = 0; int entry_count = 0; for (const std::string& line : @@ -154,7 +154,7 @@ bool TspTWParser::ParseLopezIbanezBlum(const std::string& file_name) { return entry_count == size_; } -bool TspTWParser::ParseDaSilvaUrrutia(const std::string& file_name) { +bool TspTWParser::ParseDaSilvaUrrutia(absl::string_view file_name) { for (const std::string& line : FileLines(file_name, FileLineIterator::REMOVE_INLINE_CR)) { // Skip header. @@ -211,4 +211,4 @@ bool TspTWParser::ParseDaSilvaUrrutia(const std::string& file_name) { return true; } -} // namespace operations_research +} // namespace operations_research::routing diff --git a/ortools/routing/parsers/tsptw_parser.h b/ortools/routing/parsers/tsptw_parser.h index b853151e18..697ef7a5ee 100644 --- a/ortools/routing/parsers/tsptw_parser.h +++ b/ortools/routing/parsers/tsptw_parser.h @@ -25,16 +25,17 @@ #include #include +#include "absl/strings/string_view.h" #include "ortools/base/types.h" #include "ortools/routing/parsers/simple_graph.h" -namespace operations_research { +namespace operations_research::routing { class TspTWParser final { public: TspTWParser(); // Loads and parses a routing problem from a given file. - bool LoadFile(const std::string& file_name); + bool LoadFile(absl::string_view file_name); // Returns a function returning the distance between nodes. On some instances // service times are already included in values returned by this function. // The actual distance of a route can be obtained by removing @@ -69,8 +70,8 @@ class TspTWParser final { TspTWParser(const TspTWParser&) = delete; void operator=(const TspTWParser&) = delete; #endif - bool ParseLopezIbanezBlum(const std::string& file_name); - bool ParseDaSilvaUrrutia(const std::string& file_name); + bool ParseLopezIbanezBlum(absl::string_view file_name); + bool ParseDaSilvaUrrutia(absl::string_view file_name); int64_t size_; int depot_; @@ -83,6 +84,6 @@ class TspTWParser final { std::vector distance_matrix_; }; -} // namespace operations_research +} // namespace operations_research::routing #endif // OR_TOOLS_ROUTING_PARSERS_TSPTW_PARSER_H_ diff --git a/ortools/routing/parsers/tsptw_parser_test.cc b/ortools/routing/parsers/tsptw_parser_test.cc index 1632e6c59a..b99e9fc28c 100644 --- a/ortools/routing/parsers/tsptw_parser_test.cc +++ b/ortools/routing/parsers/tsptw_parser_test.cc @@ -15,19 +15,12 @@ #include -#include "absl/flags/flag.h" #include "gtest/gtest.h" #include "ortools/base/path.h" -#if defined(_MSC_VER) -#define ROOT_DIR "../../../../../../../" -#else -#define ROOT_DIR -#endif // _MSC_VER +#define ROOT_DIR "_main/" -ABSL_FLAG(std::string, test_srcdir, "", "REQUIRED: src dir"); - -namespace operations_research { +namespace operations_research::routing { namespace { TEST(TspTWParserTest, LoadDataSet) { @@ -46,8 +39,7 @@ TEST(TspTWParserTest, LoadDataSet) { ROOT_DIR "ortools/routing/parsers/testdata/" "n20w20.002.txt"}) { TspTWParser parser; - EXPECT_TRUE(parser.LoadFile( - file::JoinPath(absl::GetFlag(FLAGS_test_srcdir), data))); + EXPECT_TRUE(parser.LoadFile(file::JoinPath(::testing::SrcDir(), data))); EXPECT_EQ(0, parser.depot()); const int size = sizes[count]; EXPECT_EQ(size, parser.size()); @@ -77,4 +69,4 @@ TEST(TspTWParserTest, LoadDataSet) { } } // namespace -} // namespace operations_research +} // namespace operations_research::routing