00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "base/callback.h"
00028 #include "base/commandlineflags.h"
00029 #include "base/commandlineflags.h"
00030 #include "base/integral_types.h"
00031 #include "base/scoped_ptr.h"
00032 #include "base/join.h"
00033 #include "constraint_solver/routing.h"
00034 #include "base/random.h"
00035
00036 using operations_research::Assignment;
00037 using operations_research::RoutingModel;
00038 using operations_research::ACMRandom;
00039 using operations_research::StrCat;
00040 using operations_research::scoped_array;
00041
00042
00043 DEFINE_int32(tsp_size, 10, "Size of Traveling Salesman Problem instance.");
00044 DEFINE_bool(tsp_use_random_matrix, true, "Use random cost matrix.");
00045 DEFINE_int32(tsp_random_forbidden_connections, 0,
00046 "Number of random forbidden connections.");
00047 DEFINE_bool(tsp_use_deterministic_random_seed, false,
00048 "Use deterministic random seeds.");
00049
00050
00051 int32 GetSeed() {
00052 if (FLAGS_tsp_use_deterministic_random_seed) {
00053 return ACMRandom::DeterministicSeed();
00054 } else {
00055 return ACMRandom::HostnamePidTimeSeed();
00056 }
00057 }
00058
00059
00060
00061
00062 int64 MyDistance(RoutingModel::NodeIndex from, RoutingModel::NodeIndex to) {
00063
00064 return (from + to).value();
00065 }
00066
00067
00068 class RandomMatrix {
00069 public:
00070 explicit RandomMatrix(int size) : size_(size) {}
00071 void Initialize() {
00072 matrix_.reset(new int64[size_ * size_]);
00073 const int64 kDistanceMax = 100;
00074 ACMRandom randomizer(GetSeed());
00075 for (RoutingModel::NodeIndex from = RoutingModel::kFirstNode; from < size_;
00076 ++from) {
00077 for (RoutingModel::NodeIndex to = RoutingModel::kFirstNode; to < size_;
00078 ++to) {
00079 if (to != from) {
00080 matrix_[MatrixIndex(from, to)] = randomizer.Uniform(kDistanceMax);
00081 } else {
00082 matrix_[MatrixIndex(from, to)] = 0LL;
00083 }
00084 }
00085 }
00086 }
00087 int64 Distance(RoutingModel::NodeIndex from,
00088 RoutingModel::NodeIndex to) const {
00089 return matrix_[MatrixIndex(from, to)];
00090 }
00091
00092 private:
00093 int64 MatrixIndex(RoutingModel::NodeIndex from,
00094 RoutingModel::NodeIndex to) const {
00095 return (from * size_ + to).value();
00096 }
00097 scoped_array<int64> matrix_;
00098 const int size_;
00099 };
00100
00101 int main(int argc, char **argv) {
00102 google::ParseCommandLineFlags(&argc, &argv, true);
00103 if (FLAGS_tsp_size > 0) {
00104
00105
00106
00107
00108 RoutingModel routing(FLAGS_tsp_size, 1);
00109
00110 routing.SetCommandLineOption("routing_first_solution", "PathCheapestArc");
00111
00112 routing.SetCommandLineOption("routing_no_lns", "true");
00113
00114
00115
00116
00117
00118 RandomMatrix matrix(FLAGS_tsp_size);
00119 if (FLAGS_tsp_use_random_matrix) {
00120 matrix.Initialize();
00121 routing.SetCost(NewPermanentCallback(&matrix, &RandomMatrix::Distance));
00122 } else {
00123 routing.SetCost(NewPermanentCallback(MyDistance));
00124 }
00125
00126 ACMRandom randomizer(GetSeed());
00127 int64 forbidden_connections = 0;
00128 while (forbidden_connections < FLAGS_tsp_random_forbidden_connections) {
00129 const int64 from = randomizer.Uniform(FLAGS_tsp_size - 1);
00130 const int64 to = randomizer.Uniform(FLAGS_tsp_size - 1) + 1;
00131 if (routing.NextVar(from)->Contains(to)) {
00132 LG << "Forbidding connection " << from << " -> " << to;
00133 routing.NextVar(from)->RemoveValue(to);
00134 ++forbidden_connections;
00135 }
00136 }
00137
00138 const Assignment* solution = routing.Solve();
00139 if (solution != NULL) {
00140
00141 LG << "Cost " << solution->ObjectiveValue();
00142
00143
00144 const int route_number = 0;
00145 string route;
00146 for (int64 node = routing.Start(route_number);
00147 !routing.IsEnd(node);
00148 node = solution->Value(routing.NextVar(node))) {
00149 route = StrCat(route, StrCat(node, " -> "));
00150 }
00151 route = StrCat(route, "0");
00152 LG << route;
00153 } else {
00154 LG << "No solution found.";
00155 }
00156 } else {
00157 LG << "Specify an instance size greater than 0.";
00158 }
00159 return 0;
00160 }