OR-Tools  9.6
solution_serializer_test.cc
Go to the documentation of this file.
1 // Copyright 2010-2022 Google LLC
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
15 
16 #include <cstdio>
17 #include <string>
18 #include <vector>
19 
20 #include "gtest/gtest.h"
22 
23 namespace operations_research {
24 namespace {
25 TEST(RoutingSolutionSerializerTest, RoutingSolutionEventComparison) {
26  RoutingSolution::Event t1 = {RoutingSolution::Event::Type::kStart, 0,
27  Arc{0, 0}};
28  RoutingSolution::Event t2 = {RoutingSolution::Event::Type::kStart, 0,
29  Arc{0, 0}}; // Same as t1.
30  RoutingSolution::Event t3 = {RoutingSolution::Event::Type::kEnd, 0,
31  Arc{0, 0}};
32  RoutingSolution::Event t4 = {RoutingSolution::Event::Type::kStart, 1,
33  Arc{0, 0}};
34  RoutingSolution::Event t5 = {RoutingSolution::Event::Type::kStart, 0,
35  Arc{1, 0}};
36  RoutingSolution::Event t6 = {RoutingSolution::Event::Type::kStart, 0,
37  Arc{0, 1}};
38  EXPECT_EQ(t1, t1);
39  EXPECT_EQ(t1, t2);
40  EXPECT_NE(t1, t3);
41  EXPECT_NE(t1, t4);
42  EXPECT_NE(t1, t5);
43  EXPECT_NE(t1, t6);
44 }
45 
46 TEST(RoutingSolutionSerializerTest, ParseEmptyString) {
48 }
49 
50 TEST(RoutingSolutionSerializerTest, ParseUnrecognizedString) {
51  EXPECT_EQ(RoutingOutputFormatFromString("ThisIsPureGarbage"),
53 }
54 
55 TEST(RoutingSolutionSerializerTest, ParseNoneString) {
57 }
58 
59 TEST(RoutingSolutionSerializerTest, ParseTsplibString) {
60  EXPECT_EQ(RoutingOutputFormatFromString("tsplib"),
62  EXPECT_EQ(RoutingOutputFormatFromString("TSPLIB"),
64 }
65 
66 TEST(RoutingSolutionSerializerTest, ParseCvrplibString) {
67  EXPECT_EQ(RoutingOutputFormatFromString("cvrplib"),
69  EXPECT_EQ(RoutingOutputFormatFromString("CVRPLIB"),
71 }
72 
73 TEST(RoutingSolutionSerializerTest, ParseCarplibString) {
74  EXPECT_EQ(RoutingOutputFormatFromString("carplib"),
76  EXPECT_EQ(RoutingOutputFormatFromString("CARPLIB"),
78 }
79 
80 TEST(RoutingSolutionSerializerTest, ParseNearplibString) {
81  EXPECT_EQ(RoutingOutputFormatFromString("nearplib"),
83  EXPECT_EQ(RoutingOutputFormatFromString("NEARPLIB"),
85 }
86 
87 TEST(RoutingSolutionSerializerTest, FromSplitRoutesWithOneRoute) {
88  // Specifically test RouteFromVector in the implementation.
89  const std::vector<std::vector<int64_t>> routes{{0, 1, 3, 0}};
90  const RoutingSolution result = RoutingSolution::FromSplitRoutes(routes);
91 
92  const RoutingSolution expected_output = RoutingSolution{
93  std::vector<RoutingSolution::Route>{RoutingSolution::Route{
94  RoutingSolution::Event{RoutingSolution::Event::Type::kStart, -1,
95  Arc{0, 0}},
96  RoutingSolution::Event{RoutingSolution::Event::Type::kTransit, -1,
97  Arc{0, 1}},
98  RoutingSolution::Event{RoutingSolution::Event::Type::kTransit, -1,
99  Arc{1, 3}},
100  RoutingSolution::Event{RoutingSolution::Event::Type::kTransit, -1,
101  Arc{3, 0}},
102  RoutingSolution::Event{RoutingSolution::Event::Type::kEnd, -1,
103  Arc{0, 0}},
104  }},
105  std::vector<int64_t>{-1},
106  std::vector<int64_t>{-1},
107  };
108  EXPECT_EQ(result, expected_output);
109 }
110 
111 TEST(RoutingSolutionSerializerTest, FromSplitRoutesWithTwoRoutes) {
112  // Specifically test RoutesFromVector in the implementation.
113  const std::vector<std::vector<int64_t>> routes{
114  {0, 1, 3, 0},
115  {0, 2, 0},
116  };
117  const RoutingSolution result = RoutingSolution::FromSplitRoutes(routes);
118 
119  const RoutingSolution expected_output = {RoutingSolution{
120  std::vector<RoutingSolution::Route>{
122  RoutingSolution::Event{RoutingSolution::Event::Type::kStart, -1,
123  Arc{0, 0}},
124  RoutingSolution::Event{RoutingSolution::Event::Type::kTransit, -1,
125  Arc{0, 1}},
126  RoutingSolution::Event{RoutingSolution::Event::Type::kTransit, -1,
127  Arc{1, 3}},
128  RoutingSolution::Event{RoutingSolution::Event::Type::kTransit, -1,
129  Arc{3, 0}},
130  RoutingSolution::Event{RoutingSolution::Event::Type::kEnd, -1,
131  Arc{0, 0}},
132  },
134  RoutingSolution::Event{RoutingSolution::Event::Type::kStart, -1,
135  Arc{0, 0}},
136  RoutingSolution::Event{RoutingSolution::Event::Type::kTransit, -1,
137  Arc{0, 2}},
138  RoutingSolution::Event{RoutingSolution::Event::Type::kTransit, -1,
139  Arc{2, 0}},
140  RoutingSolution::Event{RoutingSolution::Event::Type::kEnd, -1,
141  Arc{0, 0}},
142  },
143  },
144  std::vector<int64_t>{-1, -1},
145  std::vector<int64_t>{-1, -1},
146  }};
147 
148  EXPECT_EQ(result, expected_output);
149 }
150 
151 TEST(RoutingSolutionSerializerTest, SolutionToTsplib) {
152  const std::vector<int64_t> solution{0, 1, 2, 3, 0, -1, 0, 4, 5, 6, 0, -1};
153  const std::string expected_output = "0\n1\n2\n3\n0\n-1\n0\n4\n5\n6\n0\n-1\n";
155  RoutingSolution::SplitRoutes(solution, -1), 0)
156  .SerializeToString(RoutingOutputFormat::kTSPLIB),
157  expected_output);
158 }
159 
160 TEST(RoutingSolutionSerializerTest, SolutionToTsplibFile) {
161  const std::string file_name{std::tmpnam(nullptr)};
162  RegisteredMutableMemFile registered(file_name);
163 
164  const std::vector<std::vector<int64_t>> solution_vector{{0, 1, 2, 3, 0},
165  {0, 4, 5, 6, 0}};
166  const std::string expected_output =
167  "NAME : Test name\n"
168  "COMMENT : Length = -1; Total time = -1.000000 s\n"
169  "TYPE : TOUR\n"
170  "DIMENSION : 7\n"
171  "TOUR_SECTION\n"
172  "0\n1\n2\n3\n0\n-1\n0\n4\n5\n6\n0\n-1\n"
173  "EOF";
174 
175  RoutingSolution solution =
176  RoutingSolution::FromSplitRoutes(solution_vector, 0);
177  solution.SetName("Test name");
178  solution.WriteToSolutionFile(RoutingOutputFormat::kTSPLIB, file_name);
179  std::string written_solution;
180  CHECK_OK(file::GetContents(file_name, &written_solution, file::Defaults()));
181  EXPECT_EQ(written_solution, expected_output);
182 }
183 
184 TEST(RoutingSolutionSerializerTest, SolutionToCvrplib) {
185  // Depot: 1.
186  const std::vector<int64_t> solution{1, 2, 3, 1, -1, 1, 4, 5, 6, 1, -1};
187  const std::string expected_output = "Route #1: 1 2\nRoute #2: 3 4 5\n";
188 
190  RoutingSolution::SplitRoutes(solution, -1), 1)
191  .SerializeToString(RoutingOutputFormat::kCVRPLIB),
192  expected_output);
193 }
194 
195 TEST(RoutingSolutionSerializerTest, SolutionToCvrplibInvalidNoStart) {
196  const std::vector<RoutingSolution::Route> routes = {
198  RoutingSolution::Event{RoutingSolution::Event::Type::kTransit, -1,
199  Arc{0, 1}},
200  RoutingSolution::Event{RoutingSolution::Event::Type::kEnd, -1,
201  Arc{0, 0}},
202  },
203  };
204  const RoutingSolution solution{routes, {4}, {4}};
205  std::string solution_str;
206 
207  EXPECT_DEATH(
208  solution_str = solution.SerializeToString(RoutingOutputFormat::kCVRPLIB),
209  "");
210 }
211 
212 TEST(RoutingSolutionSerializerTest, SolutionToCvrplibInvalidNoEnd) {
213  const std::vector<RoutingSolution::Route> routes = {
215  RoutingSolution::Event{RoutingSolution::Event::Type::kStart, -1,
216  Arc{0, 0}},
217  RoutingSolution::Event{RoutingSolution::Event::Type::kTransit, -1,
218  Arc{0, 1}},
219  },
220  };
221  const RoutingSolution solution{routes, {4}, {4}};
222  std::string solution_str;
223 
224  EXPECT_DEATH(
225  solution_str = solution.SerializeToString(RoutingOutputFormat::kCVRPLIB),
226  "");
227 }
228 
229 TEST(RoutingSolutionSerializerTest, SolutionToCvrplibDepot0Dimacs) {
230  // Section 7 from
231  // http://dimacs.rutgers.edu/files/6916/3848/0327/CVRP_Competition_Rules.pdf
232  const std::vector<int64_t> solution{0, 1, 4, 0, -1, 0, 3, 2, 5, 0, -1};
233  const std::string expected_output = "Route #1: 1 4\nRoute #2: 3 2 5\n";
234 
236  RoutingSolution::SplitRoutes(solution, -1), 0)
237  .SerializeToString(RoutingOutputFormat::kCVRPLIB),
238  expected_output);
239 }
240 
241 TEST(RoutingSolutionSerializerTest, SolutionToCvrplibDepot1Dimacs) {
242  // Section 7 from
243  // http://dimacs.rutgers.edu/files/6916/3848/0327/CVRP_Competition_Rules.pdf
244  const std::vector<int64_t> solution{1, 2, 5, 1, -1, 1, 4, 3, 6, 1, -1};
245  const std::string expected_output = "Route #1: 1 4\nRoute #2: 3 2 5\n";
246 
248  RoutingSolution::SplitRoutes(solution, -1), 1)
249  .SerializeToString(RoutingOutputFormat::kCVRPLIB),
250  expected_output);
251 }
252 
253 TEST(RoutingSolutionSerializerTest, SolutionToCvrplibFile) {
254  const std::string file_name{std::tmpnam(nullptr)};
255  RegisteredMutableMemFile registered(file_name);
256 
257  const std::vector<std::vector<int64_t>> solution_vector{{0, 1, 2, 3, 0},
258  {0, 4, 5, 6, 0}};
259  const std::string expected_output =
260  "Route #1: 1 2 3\n"
261  "Route #2: 4 5 6\n"
262  "Cost 4857";
263 
264  RoutingSolution solution =
265  RoutingSolution::FromSplitRoutes(solution_vector, 0);
266  solution.SetTotalCost(4857);
267  solution.WriteToSolutionFile(RoutingOutputFormat::kCVRPLIB, file_name);
268  std::string written_solution;
269  CHECK_OK(file::GetContents(file_name, &written_solution, file::Defaults()));
270  EXPECT_EQ(written_solution, expected_output);
271 }
272 
273 RoutingSolution MakeTestArcRoutingInstance() {
274  using Event = RoutingSolution::Event;
275  using Type = Event::Type;
276  return {std::vector<RoutingSolution::Route>{
278  Event{Type::kStart, 0, Arc{0, 0}},
279  Event{Type::kServeArc, 12, Arc{4, 10}, "A1"},
280  Event{Type::kServeArc, 21, Arc{10, 8}, "A2"},
281  Event{Type::kServeArc, 8, Arc{8, 1}, "A3"},
282  Event{Type::kServeArc, 7, Arc{1, 3}, "A4"},
283  Event{Type::kServeArc, 2, Arc{3, 0}, "A5"},
284  Event{Type::kEnd, 0, Arc{0, 0}},
285  },
287  Event{Type::kStart, 0, Arc{0, 0}},
288  Event{Type::kServeArc, 5, Arc{0, 11}, "A6"},
289  Event{Type::kServeArc, 14, Arc{5, 6}, "A7"},
290  Event{Type::kServeArc, 19, Arc{7, 10}, "A8"},
291  Event{Type::kServeArc, 22, Arc{10, 9}, "A9"},
292  Event{Type::kServeArc, 4, Arc{9, 0}, "A10"},
293  Event{Type::kEnd, 0, Arc{0, 0}},
294  },
296  Event{Type::kStart, 0, Arc{0, 0}},
297  Event{Type::kServeArc, 13, Arc{11, 4}, "A11"},
298  Event{Type::kServeArc, 9, Arc{2, 3}, "A12"},
299  Event{Type::kServeArc, 6, Arc{1, 2}, "A13"},
300  Event{Type::kServeArc, 10, Arc{2, 4}, "A14"},
301  Event{Type::kServeArc, 11, Arc{4, 5}, "A15"},
302  Event{Type::kEnd, 0, Arc{0, 0}},
303  },
305  Event{Type::kStart, 0, Arc{0, 0}},
306  Event{Type::kServeArc, 15, Arc{11, 5}, "A16"},
307  Event{Type::kServeArc, 16, Arc{6, 7}, "A17"},
308  Event{Type::kServeArc, 18, Arc{7, 9}, "A18"},
309  Event{Type::kServeArc, 20, Arc{9, 8}, "A19"},
310  Event{Type::kServeArc, 1, Arc{1, 0}, "A20"},
311  Event{Type::kEnd, 0, Arc{0, 0}},
312  },
314  Event{Type::kStart, 0, Arc{0, 0}},
315  Event{Type::kServeArc, 17, Arc{11, 6}, "A21"},
316  Event{Type::kServeArc, 3, Arc{6, 0}, "A22"},
317  Event{Type::kEnd, 0, Arc{0, 0}},
318  },
319  },
320  std::vector<int64_t>{5, 5, 5, 5, 2},
321  std::vector<int64_t>{76, 60, 86, 53, 41},
322  7,
323  6,
324  30.84};
325 }
326 
327 RoutingSolution MakeTestEdgeNodeArcRoutingInstance() {
328  using Event = RoutingSolution::Event;
329  using Type = Event::Type;
330  return {std::vector<RoutingSolution::Route>{
332  Event{Type::kStart, 0, Arc{0, 0}},
333  Event{Type::kTransit, -1, Arc{0, 4}},
334  Event{Type::kServeEdge, 12, Arc{4, 10}, "E1"},
335  Event{Type::kServeArc, 21, Arc{10, 8}, "A2"},
336  Event{Type::kServeNode, 8, Arc{8, 8}},
337  Event{Type::kTransit, -1, Arc{8, 1}},
338  Event{Type::kServeEdge, 7, Arc{1, 3}, "E3"},
339  Event{Type::kServeArc, 2, Arc{3, 0}, "A4"},
340  Event{Type::kEnd, 0, Arc{0, 0}},
341  },
343  Event{Type::kStart, 0, Arc{0, 0}},
344  Event{Type::kServeEdge, 5, Arc{0, 11}, "E5"},
345  Event{Type::kTransit, -1, Arc{11, 5}},
346  Event{Type::kServeEdge, 14, Arc{5, 6}, "E6"},
347  Event{Type::kTransit, -1, Arc{6, 7}},
348  Event{Type::kServeEdge, 19, Arc{7, 10}, "E7"},
349  Event{Type::kServeEdge, 22, Arc{10, 9}, "E8"},
350  Event{Type::kServeEdge, 4, Arc{9, 0}, "E9"},
351  Event{Type::kEnd, 0, Arc{0, 0}},
352  },
354  Event{Type::kStart, 0, Arc{0, 0}},
355  Event{Type::kTransit, -1, Arc{0, 11}},
356  Event{Type::kServeArc, 13, Arc{11, 4}, "A10"},
357  Event{Type::kTransit, -1, Arc{4, 2}},
358  Event{Type::kServeEdge, 9, Arc{2, 3}, "E11"},
359  Event{Type::kTransit, -1, Arc{3, 1}},
360  Event{Type::kServeArc, 6, Arc{1, 2}, "A12"},
361  Event{Type::kServeNode, 10, Arc{2, 2}},
362  Event{Type::kTransit, -1, Arc{2, 4}},
363  Event{Type::kServeEdge, 11, Arc{4, 5}, "E13"},
364  Event{Type::kTransit, -1, Arc{5, 0}},
365  Event{Type::kEnd, 0, Arc{0, 0}},
366  },
368  Event{Type::kStart, 0, Arc{0, 0}},
369  Event{Type::kTransit, -1, Arc{0, 11}},
370  Event{Type::kServeNode, 15, Arc{11, 11}},
371  Event{Type::kServeEdge, 16, Arc{11, 7}, "E14"},
372  Event{Type::kServeEdge, 18, Arc{7, 9}, "E15"},
373  Event{Type::kServeEdge, 20, Arc{9, 8}, "E16"},
374  Event{Type::kTransit, -1, Arc{8, 1}},
375  Event{Type::kServeEdge, 1, Arc{1, 0}, "E17"},
376  Event{Type::kEnd, 0, Arc{0, 0}},
377  },
379  Event{Type::kStart, 0, Arc{0, 0}},
380  Event{Type::kTransit, -1, Arc{0, 11}},
381  Event{Type::kServeNode, 17, Arc{11, 11}},
382  Event{Type::kTransit, -1, Arc{11, 6}},
383  Event{Type::kServeNode, 3, Arc{6, 6}},
384  Event{Type::kTransit, -1, Arc{6, 0}},
385  Event{Type::kEnd, 0, Arc{0, 0}},
386  },
387  },
388  std::vector<int64_t>{5, 5, 5, 5, 2},
389  std::vector<int64_t>{76, 60, 86, 53, 41},
390  7,
391  6,
392  30.84};
393 }
394 
395 TEST(RoutingSolutionSerializerTest, CarpSolutionToCarplib) {
396  // http://dimacs.rutgers.edu/programs/challenge/vrp/carp/
397  const std::string expected_solution_output =
398  "0 1 1 5 76 7 (D 0,1,1) (S 12,5,11) (S 21,11,9) (S 8,9,2) (S 7,2,4) "
399  "(S 2,4,1) (D 0,1,1)\n"
400  "0 1 2 5 60 7 (D 0,1,1) (S 5,1,12) (S 14,6,7) (S 19,8,11) (S 22,11,10) "
401  "(S 4,10,1) (D 0,1,1)\n"
402  "0 1 3 5 86 7 (D 0,1,1) (S 13,12,5) (S 9,3,4) (S 6,2,3) (S 10,3,5) "
403  "(S 11,5,6) (D 0,1,1)\n"
404  "0 1 4 5 53 7 (D 0,1,1) (S 15,12,6) (S 16,7,8) (S 18,8,10) (S 20,10,9) "
405  "(S 1,2,1) (D 0,1,1)\n"
406  "0 1 5 2 41 4 (D 0,1,1) (S 17,12,7) (S 3,7,1) (D 0,1,1)";
407 
408  const RoutingSolution solution = MakeTestArcRoutingInstance();
409  EXPECT_EQ(solution.SerializeToString(RoutingOutputFormat::kCARPLIB),
410  expected_solution_output);
411 }
412 
413 TEST(RoutingSolutionSerializerTest, CarpSolutionToCarplibFile) {
414  const std::string file_name{std::tmpnam(nullptr)};
415  RegisteredMutableMemFile registered(file_name);
416 
417  RoutingSolution solution = MakeTestArcRoutingInstance();
418  const std::string expected_output =
419  "7\n"
420  "5\n"
421  "30.840000\n"
422  "0 1 1 5 76 7 (D 0,1,1) (S 12,5,11) (S 21,11,9) (S 8,9,2) (S 7,2,4) "
423  "(S 2,4,1) (D 0,1,1)\n"
424  "0 1 2 5 60 7 (D 0,1,1) (S 5,1,12) (S 14,6,7) (S 19,8,11) (S 22,11,10) "
425  "(S 4,10,1) (D 0,1,1)\n"
426  "0 1 3 5 86 7 (D 0,1,1) (S 13,12,5) (S 9,3,4) (S 6,2,3) (S 10,3,5) "
427  "(S 11,5,6) (D 0,1,1)\n"
428  "0 1 4 5 53 7 (D 0,1,1) (S 15,12,6) (S 16,7,8) (S 18,8,10) (S 20,10,9) "
429  "(S 1,2,1) (D 0,1,1)\n"
430  "0 1 5 2 41 4 (D 0,1,1) (S 17,12,7) (S 3,7,1) (D 0,1,1)";
431  solution.SetName("Test name");
432  solution.WriteToSolutionFile(RoutingOutputFormat::kCARPLIB, file_name);
433 
434  std::string written_solution;
435  CHECK_OK(file::GetContents(file_name, &written_solution, file::Defaults()));
436  EXPECT_EQ(written_solution, expected_output);
437 }
438 
439 TEST(RoutingSolutionSerializerTest, NearpSolutionToCarplib) {
440  const std::string expected_solution_output =
441  "0 1 1 5 76 7 (D 0,1,1) (S 12,5,11) (S 21,11,9) (S 8,9,9) (S 7,2,4) "
442  "(S 2,4,1) (D 0,1,1)\n"
443  "0 1 2 5 60 7 (D 0,1,1) (S 5,1,12) (S 14,6,7) (S 19,8,11) (S 22,11,10) "
444  "(S 4,10,1) (D 0,1,1)\n"
445  "0 1 3 5 86 7 (D 0,1,1) (S 13,12,5) (S 9,3,4) (S 6,2,3) (S 10,3,3) "
446  "(S 11,5,6) (D 0,1,1)\n"
447  "0 1 4 5 53 7 (D 0,1,1) (S 15,12,12) (S 16,12,8) (S 18,8,10) (S 20,10,9) "
448  "(S 1,2,1) (D 0,1,1)\n"
449  "0 1 5 2 41 4 (D 0,1,1) (S 17,12,12) (S 3,7,7) (D 0,1,1)";
450 
451  const RoutingSolution solution = MakeTestEdgeNodeArcRoutingInstance();
452  EXPECT_EQ(solution.SerializeToString(RoutingOutputFormat::kCARPLIB),
453  expected_solution_output);
454 }
455 
456 TEST(RoutingSolutionSerializerTest, NearpSolutionToCarplibFile) {
457  const std::string file_name{std::tmpnam(nullptr)};
458  RegisteredMutableMemFile registered(file_name);
459 
460  RoutingSolution solution = MakeTestEdgeNodeArcRoutingInstance();
461  const std::string expected_output =
462  "7\n"
463  "5\n"
464  "30.840000\n"
465  "0 1 1 5 76 7 (D 0,1,1) (S 12,5,11) (S 21,11,9) (S 8,9,9) (S 7,2,4) "
466  "(S 2,4,1) (D 0,1,1)\n"
467  "0 1 2 5 60 7 (D 0,1,1) (S 5,1,12) (S 14,6,7) (S 19,8,11) (S 22,11,10) "
468  "(S 4,10,1) (D 0,1,1)\n"
469  "0 1 3 5 86 7 (D 0,1,1) (S 13,12,5) (S 9,3,4) (S 6,2,3) (S 10,3,3) "
470  "(S 11,5,6) (D 0,1,1)\n"
471  "0 1 4 5 53 7 (D 0,1,1) (S 15,12,12) (S 16,12,8) (S 18,8,10) (S 20,10,9) "
472  "(S 1,2,1) (D 0,1,1)\n"
473  "0 1 5 2 41 4 (D 0,1,1) (S 17,12,12) (S 3,7,7) (D 0,1,1)";
474  solution.SetName("Test name");
475  solution.WriteToSolutionFile(RoutingOutputFormat::kCARPLIB, file_name);
476 
477  std::string written_solution;
478  CHECK_OK(file::GetContents(file_name, &written_solution, file::Defaults()));
479  EXPECT_EQ(written_solution, expected_output);
480 }
481 
482 TEST(RoutingSolutionSerializerTest, CarpSolutionToNearplib) {
483  const std::string expected_solution_output =
484  "Route #1 : 1 5-A1-11-A2-9-A3-2-A4-4-A5-1\n"
485  "Route #2 : 1-A6-12 6-A7-7 8-A8-11-A9-10-A10-1\n"
486  "Route #3 : 1 12-A11-5 3-A12-4 2-A13-3-A14-5-A15-6 1\n"
487  "Route #4 : 1 12-A16-6 7-A17-8-A18-10-A19-9 2-A20-1\n"
488  "Route #5 : 1 12-A21-7-A22-1";
489 
490  const RoutingSolution solution = MakeTestArcRoutingInstance();
491  EXPECT_EQ(solution.SerializeToString(RoutingOutputFormat::kNEARPLIB),
492  expected_solution_output);
493 }
494 
495 TEST(RoutingSolutionSerializerTest, CarpSolutionToNearplibFile) {
496  const std::string file_name{std::tmpnam(nullptr)};
497  RegisteredMutableMemFile registered(file_name);
498 
499  RoutingSolution solution = MakeTestArcRoutingInstance();
500  const std::string date =
501  absl::FormatTime("%B %d, %E4Y", absl::Now(), absl::LocalTimeZone());
502  const std::string expected_output =
503  "Instance name: Test name\n"
504  "Authors: DIMACS CARP\n"
505  "Date: " +
506  date +
507  "\n"
508  "Reference: OR-Tools\n"
509  "Solution\n"
510  "Route #1 : 1 5-A1-11-A2-9-A3-2-A4-4-A5-1\n"
511  "Route #2 : 1-A6-12 6-A7-7 8-A8-11-A9-10-A10-1\n"
512  "Route #3 : 1 12-A11-5 3-A12-4 2-A13-3-A14-5-A15-6 1\n"
513  "Route #4 : 1 12-A16-6 7-A17-8-A18-10-A19-9 2-A20-1\n"
514  "Route #5 : 1 12-A21-7-A22-1\n"
515  "Total cost: 7";
516  solution.SetName("Test name");
517  solution.SetAuthors("DIMACS CARP");
518  solution.WriteToSolutionFile(RoutingOutputFormat::kNEARPLIB, file_name);
519 
520  std::string written_solution;
521  CHECK_OK(file::GetContents(file_name, &written_solution, file::Defaults()));
522  EXPECT_EQ(written_solution, expected_output);
523 }
524 
525 TEST(RoutingSolutionSerializerTest, NearpSolutionToNearplib) {
526  const std::string expected_solution_output =
527  "Route #1 : 1 5-E1-11-A2-9 N9 2-E3-4-A4-1\n"
528  "Route #2 : 1-E5-12 6-E6-7 8-E7-11-E8-10-E9-1\n"
529  "Route #3 : 1 12-A10-5 3-E11-4 2-A12-3 N3 5-E13-6 1\n"
530  "Route #4 : 1 N12-E14-8-E15-10-E16-9 2-E17-1\n"
531  "Route #5 : 1 N12 N7 1";
532  // TODO(user): the following output would be ideal (because shorter). It
533  // would be achieved by implementing the relevant TODO in
534  // SerializeToNEARPLIBString.
535  // Route #1 : 1 5-E1-11-A2-N9 2-E3-4-A4-1
536  // Route #3 : 1 12-A10-5 3-E11-4 2-A12-N3 5-E13-6 1
537 
538  const RoutingSolution solution = MakeTestEdgeNodeArcRoutingInstance();
539  EXPECT_EQ(solution.SerializeToString(RoutingOutputFormat::kNEARPLIB),
540  expected_solution_output);
541 }
542 
543 TEST(RoutingSolutionSerializerTest, NearpSolutionToNearplibFile) {
544  const std::string file_name{std::tmpnam(nullptr)};
545  RegisteredMutableMemFile registered(file_name);
546 
547  RoutingSolution solution = MakeTestEdgeNodeArcRoutingInstance();
548  const std::string date =
549  absl::FormatTime("%B %d, %E4Y", absl::Now(), absl::LocalTimeZone());
550  const std::string expected_output =
551  "Instance name: Test name\n"
552  "Authors: Based on DIMACS CARP\n"
553  "Date: " +
554  date +
555  "\n"
556  "Reference: OR-Tools\n"
557  "Solution\n"
558  "Route #1 : 1 5-E1-11-A2-9 N9 2-E3-4-A4-1\n"
559  "Route #2 : 1-E5-12 6-E6-7 8-E7-11-E8-10-E9-1\n"
560  "Route #3 : 1 12-A10-5 3-E11-4 2-A12-3 N3 5-E13-6 1\n"
561  "Route #4 : 1 N12-E14-8-E15-10-E16-9 2-E17-1\n"
562  "Route #5 : 1 N12 N7 1\n"
563  "Total cost: 7";
564  solution.SetName("Test name");
565  solution.SetAuthors("Based on DIMACS CARP");
566  solution.WriteToSolutionFile(RoutingOutputFormat::kNEARPLIB, file_name);
567 
568  std::string written_solution;
569  CHECK_OK(file::GetContents(file_name, &written_solution, file::Defaults()));
570  EXPECT_EQ(written_solution, expected_output);
571 }
572 
573 TEST(RoutingSolutionSerializerTest, FormatStatisticAsTsplib) {
574  EXPECT_EQ(FormatStatistic("STAT", 4, RoutingOutputFormat::kTSPLIB),
575  "STAT = 4");
576 }
577 
578 TEST(RoutingSolutionSerializerTest, FormatStatisticAsCvrplib) {
579  EXPECT_EQ(FormatStatistic("STAT", 4, RoutingOutputFormat::kCVRPLIB),
580  "STAT 4");
581 }
582 
583 TEST(RoutingSolutionSerializerTest, FormatStatisticAsCarplib) {
584  EXPECT_EQ(FormatStatistic("STAT", 4, RoutingOutputFormat::kCARPLIB), "4");
585 }
586 
587 TEST(RoutingSolutionSerializerTest, FormatStatisticAsNearplib) {
588  EXPECT_EQ(FormatStatistic("STAT", 4, RoutingOutputFormat::kNEARPLIB),
589  "STAT : 4");
590 }
591 
592 TEST(RoutingSolutionSerializerTest, FormatStatisticAsTsplibLongPrecision) {
593  EXPECT_EQ(FormatStatistic("STAT", 591.556557, RoutingOutputFormat::kTSPLIB),
594  "STAT = 591.556557");
595 }
596 
597 TEST(RoutingSolutionSerializerTest, FormatStatisticAsCvrplibLongPrecision) {
598  EXPECT_EQ(FormatStatistic("STAT", 591.556557, RoutingOutputFormat::kCVRPLIB),
599  "STAT 591.556557");
600 }
601 
602 TEST(RoutingSolutionSerializerTest, FormatStatisticAsCarplibLongPrecision) {
603  EXPECT_EQ(FormatStatistic("STAT", 591.556557, RoutingOutputFormat::kCARPLIB),
604  "591.556557");
605 }
606 
607 TEST(RoutingSolutionSerializerTest, FormatStatisticAsNearplibLongPrecision) {
608  EXPECT_EQ(FormatStatistic("STAT", 591.556557, RoutingOutputFormat::kNEARPLIB),
609  "STAT : 591.556557");
610 }
611 } // namespace
612 } // namespace operations_research
static RoutingSolution FromSplitRoutes(const std::vector< std::vector< int64_t >> &routes, std::optional< int64_t > depot=std::nullopt)
static std::vector< std::vector< int64_t > > SplitRoutes(const std::vector< int64_t > &solution, int64_t separator)
absl::Status GetContents(const absl::string_view &filename, std::string *output, int flags)
Definition: base/file.cc:164
Options Defaults()
Definition: base/file.h:123
Collection of objects used to extend the Constraint Solver library.
RoutingOutputFormat RoutingOutputFormatFromString(std::string_view format)
TEST(LinearAssignmentTest, NullMatrix)
std::string FormatStatistic(const std::string &name, T value, RoutingOutputFormat format)