00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "constraint_solver/routing.h"
00015
00016 #include <stddef.h>
00017 #include <string.h>
00018 #include <algorithm>
00019 #include "base/hash.h"
00020
00021 #include "base/callback.h"
00022 #include "base/commandlineflags.h"
00023 #include "base/integral_types.h"
00024 #include "base/logging.h"
00025 #include "base/scoped_ptr.h"
00026 #include "base/bitmap.h"
00027 #include "base/concise_iterator.h"
00028 #include "base/map-util.h"
00029 #include "base/stl_util.h"
00030 #include "base/hash.h"
00031 #include "constraint_solver/constraint_solveri.h"
00032 #include "graph/linear_assignment.h"
00033
00034 namespace operations_research {
00035 class LocalSearchPhaseParameters;
00036 }
00037
00038
00039 DEFINE_bool(routing_no_lns, false,
00040 "Routing: forbids use of Large Neighborhood Search.");
00041 DEFINE_bool(routing_no_relocate, false,
00042 "Routing: forbids use of Relocate neighborhood.");
00043 DEFINE_bool(routing_no_exchange, false,
00044 "Routing: forbids use of Exchange neighborhood.");
00045 DEFINE_bool(routing_no_cross, false,
00046 "Routing: forbids use of Cross neighborhood.");
00047 DEFINE_bool(routing_no_2opt, false,
00048 "Routing: forbids use of 2Opt neighborhood.");
00049 DEFINE_bool(routing_no_oropt, false,
00050 "Routing: forbids use of OrOpt neighborhood.");
00051 DEFINE_bool(routing_no_make_active, false,
00052 "Routing: forbids use of MakeActive/SwapActive/MakeInactive "
00053 "neighborhoods.");
00054 DEFINE_bool(routing_no_lkh, false,
00055 "Routing: forbids use of LKH neighborhood.");
00056 DEFINE_bool(routing_no_tsp, true,
00057 "Routing: forbids use of TSPOpt neighborhood.");
00058 DEFINE_bool(routing_no_tsplns, true,
00059 "Routing: forbids use of TSPLNS neighborhood.");
00060 DEFINE_bool(routing_use_extended_swap_active, false,
00061 "Routing: use extended version of SwapActive neighborhood.");
00062
00063
00064 DEFINE_int64(routing_solution_limit, kint64max,
00065 "Routing: number of solutions limit.");
00066 DEFINE_int64(routing_time_limit, kint64max,
00067 "Routing: time limit in ms.");
00068 DEFINE_int64(routing_lns_time_limit, 100,
00069 "Routing: time limit in ms for LNS sub-decisionbuilder.");
00070
00071
00072 DEFINE_bool(routing_guided_local_search, false, "Routing: use GLS.");
00073 DEFINE_double(routing_guided_local_search_lamda_coefficient, 0.1,
00074 "Lamda coefficient in GLS.");
00075 DEFINE_bool(routing_simulated_annealing, false,
00076 "Routing: use simulated annealing.");
00077 DEFINE_bool(routing_tabu_search, false, "Routing: use tabu search.");
00078
00079
00080 DEFINE_bool(routing_dfs, false,
00081 "Routing: use a complete deoth-first search.");
00082 DEFINE_string(routing_first_solution, "",
00083 "Routing: first solution heuristic;possible values are "
00084 "Default, GlobalCheapestArc, LocalCheapestArc, PathCheapestArc.");
00085 DEFINE_bool(routing_use_first_solution_dive, false,
00086 "Dive (left-branch) for first solution.");
00087 DEFINE_int64(routing_optimization_step, 1, "Optimization step.");
00088
00089
00090
00091 DEFINE_bool(routing_use_objective_filter, true,
00092 "Use objective filter to speed up local search.");
00093 DEFINE_bool(routing_use_path_cumul_filter, true,
00094 "Use PathCumul constraint filter to speed up local search.");
00095 DEFINE_bool(routing_use_pickup_and_delivery_filter, true,
00096 "Use filter which filters precedence and same route constraints.");
00097
00098
00099 DEFINE_bool(routing_cache_callbacks, false, "Cache callback calls.");
00100 DEFINE_int64(routing_max_cache_size, 1000,
00101 "Maximum cache size when callback caching is on.");
00102 DEFINE_bool(routing_trace, false, "Routing: trace search.");
00103 DEFINE_bool(routing_search_trace, false,
00104 "Routing: use SearchTrace for monitoring search.");
00105 DEFINE_bool(routing_use_homogeneous_costs, true,
00106 "Routing: use homogeneous cost model when possible.");
00107 DEFINE_bool(routing_check_compact_assignment, true,
00108 "Routing::CompactAssignment calls Solver::CheckAssignment on the "
00109 "compact assignment.");
00110
00111 #if defined(_MSC_VER)
00112 namespace stdext {
00113 template<> size_t hash_value<operations_research::RoutingModel::NodeIndex>(
00114 const operations_research::RoutingModel::NodeIndex& a) {
00115 return a.value();
00116 }
00117 }
00118 #endif // _MSC_VER
00119
00120 namespace operations_research {
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 class MakePairActiveOperator : public PathOperator {
00146 public:
00147 MakePairActiveOperator(const IntVar* const* vars,
00148 const IntVar* const* secondary_vars,
00149 const RoutingModel::NodePairs& pairs,
00150 int size)
00151 : PathOperator(vars, secondary_vars, size, 2),
00152 inactive_pair_(0),
00153 pairs_(pairs) {}
00154 virtual ~MakePairActiveOperator() {}
00155 virtual bool MakeNextNeighbor(Assignment* delta, Assignment* deltadelta);
00156 virtual bool MakeNeighbor();
00157
00158 protected:
00159 virtual bool OnSamePathAsPreviousBase(int64 base_index) {
00160
00161
00162 return true;
00163 }
00164 virtual int64 GetBaseNodeRestartPosition(int base_index) {
00165
00166 if (base_index == 0
00167 || StartNode(base_index) != StartNode(base_index - 1)) {
00168 return StartNode(base_index);
00169 } else {
00170 return BaseNode(base_index - 1);
00171 }
00172 }
00173
00174 private:
00175 virtual void OnNodeInitialization();
00176
00177 int inactive_pair_;
00178 RoutingModel::NodePairs pairs_;
00179 };
00180
00181 void MakePairActiveOperator::OnNodeInitialization() {
00182 for (int i = 0; i < pairs_.size(); ++i) {
00183 if (IsInactive(pairs_[i].first) && IsInactive(pairs_[i].second)) {
00184 inactive_pair_ = i;
00185 return;
00186 }
00187 }
00188 inactive_pair_ = pairs_.size();
00189 }
00190
00191 bool MakePairActiveOperator::MakeNextNeighbor(Assignment* delta,
00192 Assignment* deltadelta) {
00193 while (inactive_pair_ < pairs_.size()) {
00194 if (!IsInactive(pairs_[inactive_pair_].first)
00195 || !IsInactive(pairs_[inactive_pair_].second)
00196 || !PathOperator::MakeNextNeighbor(delta, deltadelta)) {
00197 ResetPosition();
00198 ++inactive_pair_;
00199 } else {
00200 return true;
00201 }
00202 }
00203 return false;
00204 }
00205
00206 bool MakePairActiveOperator::MakeNeighbor() {
00207 DCHECK_EQ(StartNode(0), StartNode(1));
00208
00209
00210
00211
00212
00213 return MakeActive(pairs_[inactive_pair_].second, BaseNode(1))
00214 && MakeActive(pairs_[inactive_pair_].first, BaseNode(0));
00215 }
00216
00217 LocalSearchOperator* MakePairActive(Solver* const solver,
00218 const IntVar* const* vars,
00219 const IntVar* const* secondary_vars,
00220 const RoutingModel::NodePairs& pairs,
00221 int size) {
00222 return solver->RevAlloc(new MakePairActiveOperator(vars,
00223 secondary_vars,
00224 pairs,
00225 size));
00226 }
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237 class PairRelocateOperator : public PathOperator {
00238 public:
00239 PairRelocateOperator(const IntVar* const* vars,
00240 const IntVar* const* secondary_vars,
00241 const RoutingModel::NodePairs& pairs,
00242 int size)
00243 : PathOperator(vars, secondary_vars, size, 3), is_first_(size, false) {
00244 int64 index_max = 0;
00245 for (int i = 0; i < size; ++i) {
00246 index_max = std::max(index_max, vars[i]->Max());
00247 }
00248 prevs_.resize(index_max + 1, -1);
00249 int max_pair_index = -1;
00250 for (int i = 0; i < pairs.size(); ++i) {
00251 max_pair_index = std::max(max_pair_index, pairs[i].first);
00252 max_pair_index = std::max(max_pair_index, pairs[i].second);
00253 }
00254 pairs_.resize(max_pair_index + 1, -1);
00255 for (int i = 0; i < pairs.size(); ++i) {
00256 pairs_[pairs[i].first] = pairs[i].second;
00257 pairs_[pairs[i].second] = pairs[i].first;
00258 is_first_[pairs[i].first] = true;
00259 }
00260 }
00261 virtual ~PairRelocateOperator() {}
00262 virtual bool MakeNeighbor();
00263
00264 protected:
00265 virtual bool OnSamePathAsPreviousBase(int64 base_index) {
00266
00267
00268
00269 return base_index == 2;
00270 }
00271 virtual int64 GetBaseNodeRestartPosition(int base_index) {
00272
00273
00274
00275 const bool moving_first = is_first_[BaseNode(0)];
00276 if (!moving_first
00277 && base_index == 2
00278 && StartNode(base_index) == StartNode(base_index - 1)) {
00279 return BaseNode(base_index - 1);
00280 } else {
00281 return StartNode(base_index);
00282 }
00283 }
00284
00285 private:
00286 virtual void OnNodeInitialization();
00287 virtual bool RestartAtPathStartOnSynchronize() {
00288 return true;
00289 }
00290
00291 std::vector<int> pairs_;
00292 std::vector<int> prevs_;
00293 std::vector<bool> is_first_;
00294 };
00295
00296 bool PairRelocateOperator::MakeNeighbor() {
00297 DCHECK_EQ(StartNode(1), StartNode(2));
00298 const int64 prev = prevs_[BaseNode(0)];
00299 if (prev < 0) {
00300 return false;
00301 }
00302 const int sibling = BaseNode(0) < pairs_.size() ? pairs_[BaseNode(0)] : -1;
00303 if (sibling < 0) {
00304 return false;
00305 }
00306 const int64 prev_sibling = prevs_[sibling];
00307 if (prev_sibling < 0) {
00308 return false;
00309 }
00310 return MoveChain(prev_sibling, sibling, BaseNode(1))
00311 && MoveChain(prev, BaseNode(0), BaseNode(2));
00312 }
00313
00314 void PairRelocateOperator::OnNodeInitialization() {
00315 for (int i = 0; i < Size(); ++i) {
00316 prevs_[Next(i)] = i;
00317 }
00318 }
00319
00320 LocalSearchOperator* MakePairRelocate(Solver* const solver,
00321 const IntVar* const* vars,
00322 const IntVar* const* secondary_vars,
00323 const RoutingModel::NodePairs& pairs,
00324 int size) {
00325 return solver->RevAlloc(new PairRelocateOperator(vars,
00326 secondary_vars,
00327 pairs,
00328 size));
00329 }
00330
00331
00332
00333 class RoutingCache {
00334 public:
00335 RoutingCache(RoutingModel::NodeEvaluator2* callback, int size)
00336 : cached_(size), cache_(size), callback_(callback) {
00337 for (RoutingModel::NodeIndex i(0); i < RoutingModel::NodeIndex(size); ++i) {
00338 cached_[i].resize(size, false);
00339 cache_[i].resize(size, 0);
00340 }
00341 callback->CheckIsRepeatable();
00342 }
00343 int64 Run(RoutingModel::NodeIndex i, RoutingModel::NodeIndex j) {
00344
00345
00346
00347
00348
00349 if (cached_[i][j]) {
00350 return cache_[i][j];
00351 } else {
00352 const int64 cached_value = callback_->Run(i, j);
00353 cached_[i][j] = true;
00354 cache_[i][j] = cached_value;
00355 return cached_value;
00356 }
00357 }
00358
00359 private:
00360 ITIVector<RoutingModel::NodeIndex,
00361 ITIVector<RoutingModel::NodeIndex, bool> > cached_;
00362 ITIVector<RoutingModel::NodeIndex,
00363 ITIVector<RoutingModel::NodeIndex, int64> > cache_;
00364 scoped_ptr<RoutingModel::NodeEvaluator2> callback_;
00365 };
00366
00367 namespace {
00368
00369
00370
00371
00372 class BasePathFilter : public IntVarLocalSearchFilter {
00373 public:
00374 BasePathFilter(const IntVar* const* nexts,
00375 int nexts_size,
00376 int next_domain_size,
00377 const string& name);
00378 virtual ~BasePathFilter() {}
00379 virtual bool Accept(const Assignment* delta, const Assignment* deltadelta);
00380 virtual void OnSynchronize();
00381
00382 protected:
00383 static const int64 kUnassigned;
00384
00385 int64 GetNext(const Assignment::IntContainer& container, int64 node) const;
00386
00387 private:
00388 virtual bool AcceptPath(const Assignment::IntContainer& container,
00389 int64 path_start) = 0;
00390
00391 std::vector<int64> node_path_starts_;
00392 const string name_;
00393 };
00394
00395 const int64 BasePathFilter::kUnassigned = -1;
00396
00397 BasePathFilter::BasePathFilter(const IntVar* const* nexts,
00398 int nexts_size,
00399 int next_domain_size,
00400 const string& name)
00401 : IntVarLocalSearchFilter(nexts, nexts_size),
00402 node_path_starts_(next_domain_size),
00403 name_(name) {}
00404
00405 bool BasePathFilter::Accept(const Assignment* delta,
00406 const Assignment* deltadelta) {
00407 const Assignment::IntContainer& container = delta->IntVarContainer();
00408 const int delta_size = container.Size();
00409
00410
00411
00412 std::vector<int64> touched_paths;
00413 for (int i = 0; i < delta_size; ++i) {
00414 const IntVarElement& new_element = container.Element(i);
00415 const IntVar* const var = new_element.Var();
00416 int64 index = kUnassigned;
00417 if (FindIndex(var, &index)) {
00418 const int64 start = node_path_starts_[index];
00419 if (start != kUnassigned
00420 && find(touched_paths.begin(), touched_paths.end(), start)
00421 == touched_paths.end()) {
00422 touched_paths.push_back(start);
00423 }
00424 }
00425 }
00426
00427 const int touched_paths_size = touched_paths.size();
00428 for (int i = 0; i < touched_paths_size; ++i) {
00429 if (!AcceptPath(container, touched_paths[i])) {
00430 return false;
00431 }
00432 }
00433 return true;
00434 }
00435
00436 void BasePathFilter::OnSynchronize() {
00437 const int nexts_size = Size();
00438
00439 std::vector<int64> path_starts;
00440
00441 Bitmap has_prevs(nexts_size, false);
00442 for (int i = 0; i < nexts_size; ++i) {
00443 const int next = Value(i);
00444 if (next < nexts_size) {
00445 has_prevs.Set(next, true);
00446 }
00447 }
00448 for (int i = 0; i < nexts_size; ++i) {
00449 if (!has_prevs.Get(i)) {
00450 path_starts.push_back(i);
00451 }
00452 }
00453
00454 node_path_starts_.assign(node_path_starts_.size(), kUnassigned);
00455
00456 for (int i = 0; i < path_starts.size(); ++i) {
00457 const int64 start = path_starts[i];
00458 int node = start;
00459 node_path_starts_[node] = start;
00460 int next = Value(node);
00461 while (next < nexts_size) {
00462 node = next;
00463 node_path_starts_[node] = start;
00464 next = Value(node);
00465 }
00466 node_path_starts_[next] = start;
00467 }
00468 }
00469
00470 int64 BasePathFilter::GetNext(const Assignment::IntContainer& container,
00471 int64 node) const {
00472 const IntVar* const next_var = Var(node);
00473 int64 next = Value(node);
00474 if (container.Contains(next_var)) {
00475 const IntVarElement& element = container.Element(next_var);
00476 if (element.Bound()) {
00477 next = element.Value();
00478 } else {
00479 return kUnassigned;
00480 }
00481 }
00482 return next;
00483 }
00484
00485
00486
00487 class PathCumulFilter : public BasePathFilter {
00488 public:
00489
00490 PathCumulFilter(const IntVar* const* nexts,
00491 int nexts_size,
00492 const IntVar* const* cumuls,
00493 int cumuls_size,
00494 Solver::IndexEvaluator2* evaluator,
00495 const string& name);
00496 virtual ~PathCumulFilter() {}
00497
00498 private:
00499 virtual bool AcceptPath(const Assignment::IntContainer& container,
00500 int64 path_start);
00501
00502 scoped_array<IntVar*> cumuls_;
00503 const int cumuls_size_;
00504 Solver::IndexEvaluator2* const evaluator_;
00505 };
00506
00507 PathCumulFilter::PathCumulFilter(const IntVar* const* nexts,
00508 int nexts_size,
00509 const IntVar* const* cumuls,
00510 int cumuls_size,
00511 Solver::IndexEvaluator2* evaluator,
00512 const string& name)
00513 : BasePathFilter(nexts, nexts_size, cumuls_size, name),
00514 cumuls_size_(cumuls_size),
00515 evaluator_(evaluator) {
00516 cumuls_.reset(new IntVar*[cumuls_size_]);
00517 memcpy(cumuls_.get(), cumuls, cumuls_size_ * sizeof(*cumuls));
00518 }
00519
00520 bool PathCumulFilter::AcceptPath(const Assignment::IntContainer& container,
00521 int64 path_start) {
00522 int64 node = path_start;
00523 int64 cumul = cumuls_[node]->Min();
00524 while (node < Size()) {
00525 const int64 next = GetNext(container, node);
00526 if (next == kUnassigned) {
00527
00528 return true;
00529 }
00530 cumul += evaluator_->Run(node, next);
00531 if (cumul > cumuls_[next]->Max()) {
00532 return false;
00533 }
00534 cumul = std::max(cumuls_[next]->Min(), cumul);
00535 node = next;
00536 }
00537 return true;
00538 }
00539
00540
00541 class NodePrecedenceFilter : public BasePathFilter {
00542 public:
00543 NodePrecedenceFilter(const IntVar* const* nexts,
00544 int nexts_size,
00545 int next_domain_size,
00546 const RoutingModel::NodePairs& pairs,
00547 const string& name);
00548 virtual ~NodePrecedenceFilter() {}
00549 bool AcceptPath(const Assignment::IntContainer& container, int64 path_start);
00550
00551 private:
00552 std::vector<int> pair_firsts_;
00553 std::vector<int> pair_seconds_;
00554 };
00555
00556 NodePrecedenceFilter::NodePrecedenceFilter(const IntVar* const* nexts,
00557 int nexts_size,
00558 int next_domain_size,
00559 const RoutingModel::NodePairs& pairs,
00560 const string& name)
00561 : BasePathFilter(nexts, nexts_size, next_domain_size, name),
00562 pair_firsts_(next_domain_size, kUnassigned),
00563 pair_seconds_(next_domain_size, kUnassigned) {
00564 for (int i = 0; i < pairs.size(); ++i) {
00565 pair_firsts_[pairs[i].first] = pairs[i].second;
00566 pair_seconds_[pairs[i].second] = pairs[i].first;
00567 }
00568 }
00569
00570 bool NodePrecedenceFilter::AcceptPath(const Assignment::IntContainer& container,
00571 int64 path_start) {
00572 std::vector<bool> visited(Size(), false);
00573 int64 node = path_start;
00574 int64 path_length = 1;
00575 while (node < Size()) {
00576 if (path_length > Size()) {
00577 return false;
00578 }
00579 if (pair_firsts_[node] != kUnassigned
00580 && visited[pair_firsts_[node]]) {
00581 return false;
00582 }
00583 if (pair_seconds_[node] != kUnassigned
00584 && !visited[pair_seconds_[node]]) {
00585 return false;
00586 }
00587 visited[node] = true;
00588 const int64 next = GetNext(container, node);
00589 if (next == kUnassigned) {
00590
00591 return true;
00592 }
00593 node = next;
00594 ++path_length;
00595 }
00596 return true;
00597 }
00598
00599
00600
00601 int64 CostFunction(int64** eval, int64 i, int64 j) {
00602 return eval[i][j];
00603 }
00604
00605 class MatrixEvaluator : public BaseObject {
00606 public:
00607 MatrixEvaluator(const int64* const* values,
00608 int nodes,
00609 RoutingModel* model)
00610 : values_(new int64*[nodes]), nodes_(nodes), model_(model) {
00611 CHECK(values) << "null pointer";
00612 for (int i = 0; i < nodes_; ++i) {
00613 values_[i] = new int64[nodes_];
00614 memcpy(values_[i], values[i], nodes_ * sizeof(*values[i]));
00615 }
00616 }
00617 virtual ~MatrixEvaluator() {
00618 for (int i = 0; i < nodes_; ++i) {
00619 delete [] values_[i];
00620 }
00621 delete [] values_;
00622 }
00623 int64 Value(RoutingModel::NodeIndex i, RoutingModel::NodeIndex j) const {
00624 return values_[i.value()][j.value()];
00625 }
00626
00627 private:
00628 int64** const values_;
00629 const int nodes_;
00630 RoutingModel* const model_;
00631 };
00632
00633 class VectorEvaluator : public BaseObject {
00634 public:
00635 VectorEvaluator(const int64* values, int64 nodes, RoutingModel* model)
00636 : values_(new int64[nodes]), nodes_(nodes), model_(model) {
00637 CHECK(values) << "null pointer";
00638 memcpy(values_.get(), values, nodes * sizeof(*values));
00639 }
00640 virtual ~VectorEvaluator() {}
00641 int64 Value(RoutingModel::NodeIndex i, RoutingModel::NodeIndex j) const;
00642 private:
00643 scoped_array<int64> values_;
00644 const int64 nodes_;
00645 RoutingModel* const model_;
00646 };
00647
00648 int64 VectorEvaluator::Value(RoutingModel::NodeIndex i,
00649 RoutingModel::NodeIndex j) const {
00650 return values_[i.value()];
00651 }
00652
00653 class ConstantEvaluator : public BaseObject {
00654 public:
00655 explicit ConstantEvaluator(int64 value) : value_(value) {}
00656 virtual ~ConstantEvaluator() {}
00657 int64 Value(RoutingModel::NodeIndex i, RoutingModel::NodeIndex j) const {
00658 return value_;
00659 }
00660 private:
00661 const int64 value_;
00662 };
00663
00664
00665
00666 Solver::DecisionModification LeftDive(Solver* const s) {
00667 return Solver::KEEP_LEFT;
00668 }
00669
00670 }
00671
00672
00673
00674 static const int kUnassigned = -1;
00675 static const int64 kNoPenalty = -1;
00676
00677 const RoutingModel::NodeIndex RoutingModel::kFirstNode(0);
00678 const RoutingModel::NodeIndex RoutingModel::kInvalidNodeIndex(-1);
00679
00680 RoutingModel::RoutingModel(int nodes, int vehicles)
00681 : solver_(NULL),
00682 no_cycle_constraint_(NULL),
00683 costs_(vehicles),
00684 homogeneous_costs_(FLAGS_routing_use_homogeneous_costs),
00685 cost_(0),
00686 fixed_costs_(vehicles),
00687 nodes_(nodes),
00688 vehicles_(vehicles),
00689 starts_(vehicles),
00690 ends_(vehicles),
00691 start_end_count_(1),
00692 is_depot_set_(false),
00693 closed_(false),
00694 status_(ROUTING_NOT_SOLVED),
00695 first_solution_strategy_(ROUTING_DEFAULT_STRATEGY),
00696 first_solution_evaluator_(NULL),
00697 metaheuristic_(ROUTING_GREEDY_DESCENT),
00698 collect_assignments_(NULL),
00699 solve_db_(NULL),
00700 improve_db_(NULL),
00701 restore_assignment_(NULL),
00702 assignment_(NULL),
00703 preassignment_(NULL),
00704 time_limit_ms_(FLAGS_routing_time_limit),
00705 lns_time_limit_ms_(FLAGS_routing_lns_time_limit),
00706 limit_(NULL),
00707 ls_limit_(NULL),
00708 lns_limit_(NULL) {
00709 SolverParameters parameters;
00710 solver_.reset(new Solver("Routing", parameters));
00711 Initialize();
00712 }
00713
00714 RoutingModel::RoutingModel(
00715 int nodes,
00716 int vehicles,
00717 const std::vector<std::pair<NodeIndex, NodeIndex> >& start_end)
00718 : solver_(NULL),
00719 no_cycle_constraint_(NULL),
00720 costs_(vehicles),
00721 homogeneous_costs_(FLAGS_routing_use_homogeneous_costs),
00722 fixed_costs_(vehicles),
00723 nodes_(nodes),
00724 vehicles_(vehicles),
00725 starts_(vehicles),
00726 ends_(vehicles),
00727 is_depot_set_(false),
00728 closed_(false),
00729 status_(ROUTING_NOT_SOLVED),
00730 first_solution_strategy_(ROUTING_DEFAULT_STRATEGY),
00731 first_solution_evaluator_(NULL),
00732 metaheuristic_(ROUTING_GREEDY_DESCENT),
00733 collect_assignments_(NULL),
00734 solve_db_(NULL),
00735 improve_db_(NULL),
00736 restore_assignment_(NULL),
00737 assignment_(NULL),
00738 preassignment_(NULL),
00739 time_limit_ms_(FLAGS_routing_time_limit),
00740 lns_time_limit_ms_(FLAGS_routing_lns_time_limit),
00741 limit_(NULL),
00742 ls_limit_(NULL),
00743 lns_limit_(NULL) {
00744 SolverParameters parameters;
00745 solver_.reset(new Solver("Routing", parameters));
00746 CHECK_EQ(vehicles, start_end.size());
00747 hash_set<NodeIndex> depot_set;
00748 for (int i = 0; i < start_end.size(); ++i) {
00749 depot_set.insert(start_end[i].first);
00750 depot_set.insert(start_end[i].second);
00751 }
00752 start_end_count_ = depot_set.size();
00753 Initialize();
00754 SetStartEnd(start_end);
00755 }
00756
00757 RoutingModel::RoutingModel(int nodes,
00758 int vehicles,
00759 const std::vector<NodeIndex>& starts,
00760 const std::vector<NodeIndex>& ends)
00761 : solver_(NULL),
00762 no_cycle_constraint_(NULL),
00763 costs_(vehicles),
00764 homogeneous_costs_(FLAGS_routing_use_homogeneous_costs),
00765 fixed_costs_(vehicles),
00766 nodes_(nodes),
00767 vehicles_(vehicles),
00768 starts_(vehicles),
00769 ends_(vehicles),
00770 is_depot_set_(false),
00771 closed_(false),
00772 status_(ROUTING_NOT_SOLVED),
00773 first_solution_strategy_(ROUTING_DEFAULT_STRATEGY),
00774 first_solution_evaluator_(NULL),
00775 metaheuristic_(ROUTING_GREEDY_DESCENT),
00776 collect_assignments_(NULL),
00777 solve_db_(NULL),
00778 improve_db_(NULL),
00779 restore_assignment_(NULL),
00780 assignment_(NULL),
00781 preassignment_(NULL),
00782 time_limit_ms_(FLAGS_routing_time_limit),
00783 lns_time_limit_ms_(FLAGS_routing_lns_time_limit),
00784 limit_(NULL),
00785 ls_limit_(NULL),
00786 lns_limit_(NULL) {
00787 SolverParameters parameters;
00788 solver_.reset(new Solver("Routing", parameters));
00789 CHECK_EQ(vehicles, starts.size());
00790 CHECK_EQ(vehicles, ends.size());
00791 hash_set<NodeIndex> depot_set;
00792 std::vector<std::pair<NodeIndex, NodeIndex> > start_end(starts.size());
00793 for (int i = 0; i < starts.size(); ++i) {
00794 depot_set.insert(starts[i]);
00795 depot_set.insert(ends[i]);
00796 start_end[i] = std::make_pair(starts[i], ends[i]);
00797 }
00798 start_end_count_ = depot_set.size();
00799 Initialize();
00800 SetStartEnd(start_end);
00801 }
00802
00803 void RoutingModel::Initialize() {
00804 const int size = Size();
00805
00806 nexts_.reset(solver_->MakeIntVarArray(size,
00807 0,
00808 size + vehicles_ - 1,
00809 "Nexts"));
00810 solver_->AddConstraint(solver_->MakeAllDifferent(nexts_.get(), size, false));
00811
00812
00813 vehicle_vars_.reset(solver_->MakeIntVarArray(size + vehicles_,
00814 -1,
00815 vehicles_ - 1,
00816 "Vehicles"));
00817
00818 active_.reset(solver_->MakeBoolVarArray(size, "Active"));
00819
00820 cost_cache_.clear();
00821 cost_cache_.resize(size);
00822 for (int i = 0; i < size; ++i) {
00823 CostCacheElement& cache = cost_cache_[i];
00824 cache.node = kUnassigned;
00825 cache.vehicle = kUnassigned;
00826 cache.cost = 0;
00827 }
00828 preassignment_ = solver_->MakeAssignment();
00829 }
00830
00831 RoutingModel::~RoutingModel() {
00832 STLDeleteElements(&routing_caches_);
00833 STLDeleteElements(&owned_node_callbacks_);
00834 STLDeleteElements(&owned_index_callbacks_);
00835 }
00836
00837 void RoutingModel::AddNoCycleConstraintInternal() {
00838 CheckDepot();
00839 if (no_cycle_constraint_ == NULL) {
00840 no_cycle_constraint_ = solver_->MakeNoCycle(nexts_.get(),
00841 active_.get(),
00842 Size());
00843 solver_->AddConstraint(no_cycle_constraint_);
00844 }
00845 }
00846
00847 void RoutingModel::AddDimension(NodeEvaluator2* evaluator,
00848 int64 slack_max,
00849 int64 capacity,
00850 const string& name) {
00851 CheckDepot();
00852 IntVar** cumuls = GetOrMakeCumuls(capacity, name);
00853 const int size = Size();
00854 IntVar** transits = GetOrMakeTransits(NewCachedCallback(evaluator),
00855 slack_max, capacity, name);
00856 solver_->AddConstraint(solver_->MakePathCumul(nexts_.get(),
00857 active_.get(),
00858 cumuls,
00859 transits,
00860 size,
00861 size + vehicles_));
00862
00863 for (int i = 0; i < vehicles_; ++i) {
00864 solver_->AddConstraint(solver_->MakeEquality(cumuls[Start(i)], Zero()));
00865 }
00866 }
00867
00868 void RoutingModel::AddConstantDimension(int64 value,
00869 int64 capacity,
00870 const string& name) {
00871 ConstantEvaluator* evaluator =
00872 solver_->RevAlloc(new ConstantEvaluator(value));
00873 AddDimension(NewPermanentCallback(evaluator, &ConstantEvaluator::Value),
00874 0, capacity, name);
00875 }
00876
00877 void RoutingModel::AddVectorDimension(const int64* values,
00878 int64 capacity,
00879 const string& name) {
00880 VectorEvaluator* evaluator =
00881 solver_->RevAlloc(new VectorEvaluator(values, nodes_, this));
00882 AddDimension(NewPermanentCallback(evaluator, &VectorEvaluator::Value),
00883 0, capacity, name);
00884 }
00885
00886 void RoutingModel::AddMatrixDimension(const int64* const* values,
00887 int64 capacity,
00888 const string& name) {
00889 MatrixEvaluator* evaluator =
00890 solver_->RevAlloc(new MatrixEvaluator(values, nodes_, this));
00891 AddDimension(NewPermanentCallback(evaluator, &MatrixEvaluator::Value),
00892 0, capacity, name);
00893 }
00894
00895 void RoutingModel::AddAllActive() {
00896 for (int i = 0; i < Size(); ++i) {
00897 if (active_[i]->Max() != 0) {
00898 active_[i]->SetValue(1);
00899 }
00900 }
00901 }
00902
00903 void RoutingModel::SetCost(NodeEvaluator2* evaluator) {
00904 evaluator->CheckIsRepeatable();
00905 NodeEvaluator2* cached_evaluator = NewCachedCallback(evaluator);
00906 homogeneous_costs_ = FLAGS_routing_use_homogeneous_costs;
00907 for (int i = 0; i < vehicles_; ++i) {
00908 SetVehicleCostInternal(i, cached_evaluator);
00909 }
00910 }
00911
00912 int64 RoutingModel::GetRouteFixedCost() const {
00913 return GetVehicleFixedCost(0);
00914 }
00915
00916 void RoutingModel::SetVehicleCost(int vehicle, NodeEvaluator2* evaluator) {
00917 evaluator->CheckIsRepeatable();
00918 homogeneous_costs_ = false;
00919 SetVehicleCostInternal(vehicle, NewCachedCallback(evaluator));
00920 }
00921
00922 void RoutingModel::SetVehicleCostInternal(int vehicle,
00923 NodeEvaluator2* evaluator) {
00924 CHECK_LT(vehicle, vehicles_);
00925 costs_[vehicle] = evaluator;
00926 }
00927
00928 void RoutingModel::SetRouteFixedCost(int64 cost) {
00929 for (int i = 0; i < vehicles_; ++i) {
00930 SetVehicleFixedCost(i, cost);
00931 }
00932 }
00933
00934 int64 RoutingModel::GetVehicleFixedCost(int vehicle) const {
00935 CHECK_LT(vehicle, vehicles_);
00936 return fixed_costs_[vehicle];
00937 }
00938
00939 void RoutingModel::SetVehicleFixedCost(int vehicle, int64 cost) {
00940 CHECK_LT(vehicle, vehicles_);
00941 fixed_costs_[vehicle] = cost;
00942 }
00943
00944 void RoutingModel::AddDisjunction(const std::vector<NodeIndex>& nodes) {
00945 AddDisjunctionInternal(nodes, kNoPenalty);
00946 }
00947
00948 void RoutingModel::AddDisjunction(const std::vector<NodeIndex>& nodes,
00949 int64 penalty) {
00950 CHECK_GE(penalty, 0) << "Penalty must be positive";
00951 AddDisjunctionInternal(nodes, penalty);
00952 }
00953
00954 void RoutingModel::AddDisjunctionInternal(const std::vector<NodeIndex>& nodes,
00955 int64 penalty) {
00956 const int size = disjunctions_.size();
00957 disjunctions_.resize(size + 1);
00958 std::vector<int>& disjunction_nodes = disjunctions_[size].nodes;
00959 disjunction_nodes.resize(nodes.size());
00960 for (int i = 0; i < nodes.size(); ++i) {
00961 CHECK_NE(kUnassigned, node_to_index_[nodes[i]]);
00962 disjunction_nodes[i] = node_to_index_[nodes[i]];
00963 }
00964 disjunctions_[size].penalty = penalty;
00965 for (int i = 0; i < nodes.size(); ++i) {
00966
00967 node_to_disjunction_[node_to_index_[nodes[i]]] = size;
00968 }
00969 }
00970
00971 IntVar* RoutingModel::CreateDisjunction(int disjunction) {
00972 const std::vector<int>& nodes = disjunctions_[disjunction].nodes;
00973 const int nodes_size = nodes.size();
00974 std::vector<IntVar*> disjunction_vars(nodes_size + 1);
00975 for (int i = 0; i < nodes_size; ++i) {
00976 const int node = nodes[i];
00977 CHECK_LT(node, Size());
00978 disjunction_vars[i] = ActiveVar(node);
00979 }
00980 IntVar* no_active_var = solver_->MakeBoolVar();
00981 disjunction_vars[nodes_size] = no_active_var;
00982 solver_->AddConstraint(solver_->MakeSumEquality(disjunction_vars, 1));
00983 const int64 penalty = disjunctions_[disjunction].penalty;
00984 if (penalty < 0) {
00985 no_active_var->SetMax(0);
00986 return NULL;
00987 } else {
00988 return solver_->MakeProd(no_active_var, penalty)->Var();
00989 }
00990 }
00991
00992 void RoutingModel::AddLocalSearchOperator(LocalSearchOperator* ls_operator) {
00993 extra_operators_.push_back(ls_operator);
00994 }
00995
00996 void RoutingModel::SetDepot(NodeIndex depot) {
00997 std::vector<std::pair<NodeIndex, NodeIndex> > start_end(
00998 vehicles_, std::make_pair(depot, depot));
00999 SetStartEnd(start_end);
01000 }
01001
01002 void RoutingModel::SetStartEnd(
01003 const std::vector<std::pair<NodeIndex, NodeIndex> >& start_end) {
01004 if (is_depot_set_) {
01005 LOG(WARNING) << "A depot has already been specified, ignoring new ones";
01006 return;
01007 }
01008 CHECK_EQ(start_end.size(), vehicles_);
01009 const int size = Size();
01010 hash_set<NodeIndex> starts;
01011 hash_set<NodeIndex> ends;
01012 for (int i = 0; i < vehicles_; ++i) {
01013 const NodeIndex start = start_end[i].first;
01014 const NodeIndex end = start_end[i].second;
01015 CHECK_GE(start, 0);
01016 CHECK_GE(end, 0);
01017 CHECK_LE(start, nodes_);
01018 CHECK_LE(end, nodes_);
01019 starts.insert(start);
01020 ends.insert(end);
01021 }
01022 index_to_node_.resize(size + vehicles_);
01023 node_to_index_.resize(nodes_, kUnassigned);
01024 int index = 0;
01025 for (NodeIndex i = kFirstNode; i < nodes_; ++i) {
01026 if (starts.count(i) != 0 || ends.count(i) == 0) {
01027 index_to_node_[index] = i;
01028 node_to_index_[i] = index;
01029 ++index;
01030 }
01031 }
01032 hash_set<NodeIndex> node_set;
01033 index_to_vehicle_.resize(size + vehicles_, kUnassigned);
01034 for (int i = 0; i < vehicles_; ++i) {
01035 const NodeIndex start = start_end[i].first;
01036 if (node_set.count(start) == 0) {
01037 node_set.insert(start);
01038 const int start_index = node_to_index_[start];
01039 starts_[i] = start_index;
01040 CHECK_NE(kUnassigned, start_index);
01041 index_to_vehicle_[start_index] = i;
01042 } else {
01043 starts_[i] = index;
01044 index_to_node_[index] = start;
01045 index_to_vehicle_[index] = i;
01046 ++index;
01047 }
01048 }
01049 for (int i = 0; i < vehicles_; ++i) {
01050 NodeIndex end = start_end[i].second;
01051 index_to_node_[index] = end;
01052 ends_[i] = index;
01053 CHECK_LE(size, index);
01054 index_to_vehicle_[index] = i;
01055 ++index;
01056 }
01057 for (int i = 0; i < size; ++i) {
01058 for (int j = 0; j < vehicles_; ++j) {
01059
01060 solver_->AddConstraint(solver_->MakeNonEquality(nexts_[i], starts_[j]));
01061 }
01062
01063 solver_->AddConstraint(solver_->MakeIsDifferentCstCt(nexts_[i],
01064 i,
01065 active_[i]));
01066 }
01067 is_depot_set_ = true;
01068
01069
01070 VLOG(1) << "Number of nodes: " << nodes_;
01071 VLOG(1) << "Number of vehicles: " << vehicles_;
01072 for (int index = 0; index < index_to_node_.size(); ++index) {
01073 VLOG(2) << "Variable index " << index
01074 << " -> Node index " << index_to_node_[index];
01075 }
01076 for (NodeIndex node = kFirstNode; node < node_to_index_.size(); ++node) {
01077 VLOG(2) << "Node index " << node
01078 << " -> Variable index " << node_to_index_[node];
01079 }
01080 }
01081
01082 void RoutingModel::CloseModel() {
01083 if (closed_) {
01084 LOG(WARNING) << "Model already closed";
01085 return;
01086 }
01087 closed_ = true;
01088
01089 CheckDepot();
01090
01091 AddNoCycleConstraintInternal();
01092
01093 const int size = Size();
01094
01095
01096 for (int i = 0; i < vehicles_; ++i) {
01097 solver_->AddConstraint(solver_->MakeEquality(
01098 vehicle_vars_[starts_[i]], solver_->MakeIntConst(i)));
01099 solver_->AddConstraint(solver_->MakeEquality(
01100 vehicle_vars_[ends_[i]], solver_->MakeIntConst(i)));
01101 }
01102 std::vector<IntVar*> zero_transit(size, solver_->MakeIntConst(Zero()));
01103 solver_->AddConstraint(solver_->MakePathCumul(nexts_.get(),
01104 active_.get(),
01105 vehicle_vars_.get(),
01106 zero_transit.data(),
01107 size,
01108 size + vehicles_));
01109
01110
01111
01112 for (int i = 0; i < size; ++i) {
01113 solver_->AddConstraint(solver_->MakeIsDifferentCstCt(vehicle_vars_[i], -1,
01114 active_[i]));
01115 }
01116
01117
01118 if (disjunctions_.size() == 0) {
01119 AddAllActive();
01120 }
01121
01122
01123 for (int i = 0; i < vehicles_; ++i) {
01124 for (int j = 0; j < vehicles_; ++j) {
01125 if (i != j) {
01126 nexts_[starts_[i]]->RemoveValue(ends_[j]);
01127 }
01128 }
01129 }
01130
01131 std::vector<IntVar*> cost_elements;
01132
01133
01134
01135 for (int i = 0; i < size; ++i) {
01136 IntExpr* expr = NULL;
01137 if (homogeneous_costs_) {
01138 expr = solver_->MakeElement(
01139 NewPermanentCallback(this,
01140 &RoutingModel::GetHomogeneousCost,
01141 static_cast<int64>(i)),
01142 nexts_[i]);
01143 } else {
01144 expr = solver_->MakeElement(
01145 NewPermanentCallback(this,
01146 &RoutingModel::GetCost,
01147 static_cast<int64>(i)),
01148 nexts_[i],
01149 vehicle_vars_[i]);
01150 }
01151 IntVar* var = solver_->MakeProd(expr, active_[i])->Var();
01152 cost_elements.push_back(var);
01153 }
01154
01155 for (int i = 0; i < disjunctions_.size(); ++i) {
01156 IntVar* penalty_var = CreateDisjunction(i);
01157 if (penalty_var != NULL) {
01158 cost_elements.push_back(penalty_var);
01159 }
01160 }
01161 cost_ = solver_->MakeSum(cost_elements)->Var();
01162 cost_->set_name("Cost");
01163
01164 SetupSearch();
01165 }
01166
01167
01168
01169
01170
01171
01172 class FastOnePathBuilder : public DecisionBuilder {
01173 public:
01174
01175 FastOnePathBuilder(RoutingModel* const model,
01176 ResultCallback2<int64, int64, int64>* evaluator)
01177 : model_(model), evaluator_(evaluator) {
01178 evaluator_->CheckIsRepeatable();
01179 }
01180 virtual ~FastOnePathBuilder() {}
01181 virtual Decision* Next(Solver* const solver) {
01182 int64 index = -1;
01183 if (!FindPathStart(&index)) {
01184 return NULL;
01185 }
01186 IntVar** nexts = model_->Nexts();
01187
01188
01189 Assignment* assignment = solver->MakeAssignment();
01190 int64 next = FindCheapestValue(index, *assignment);
01191 while (next >= 0) {
01192 assignment->Add(nexts[index]);
01193 assignment->SetValue(nexts[index], next);
01194 index = next;
01195 std::vector<int> alternates;
01196 model_->GetDisjunctionIndicesFromIndex(index, &alternates);
01197 for (int alternate_index = 0;
01198 alternate_index < alternates.size();
01199 ++alternate_index) {
01200 const int alternate = alternates[alternate_index];
01201 if (index != alternate) {
01202 assignment->Add(nexts[alternate]);
01203 assignment->SetValue(nexts[alternate], alternate);
01204 }
01205 }
01206 next = FindCheapestValue(index, *assignment);
01207 }
01208
01209
01210
01211 for (int index = 0; index < model_->Size(); ++index) {
01212 IntVar* const next = nexts[index];
01213 if (!assignment->Contains(next)) {
01214 assignment->Add(next);
01215 if (next->Contains(index)) {
01216 assignment->SetValue(next, index);
01217 }
01218 }
01219 }
01220 assignment->Restore();
01221 return NULL;
01222 }
01223
01224 private:
01225 bool FindPathStart(int64* index) const {
01226 IntVar** nexts = model_->Nexts();
01227 const int size = model_->Size();
01228
01229 for (int i = size - 1; i >= 0; --i) {
01230 if (nexts[i]->Bound()) {
01231 const int next = nexts[i]->Value();
01232 if (next < size && !nexts[next]->Bound()) {
01233 *index = next;
01234 return true;
01235 }
01236 }
01237 }
01238
01239 for (int i = size - 1; i >= 0; --i) {
01240 if (!nexts[i]->Bound()) {
01241 bool has_possible_prev = false;
01242 for (int j = 0; j < size; ++j) {
01243 if (nexts[j]->Contains(i)) {
01244 has_possible_prev = true;
01245 break;
01246 }
01247 }
01248 if (!has_possible_prev) {
01249 *index = i;
01250 return true;
01251 }
01252 }
01253 }
01254
01255 for (int i = 0; i < size; ++i) {
01256 if (!nexts[i]->Bound()) {
01257 *index = i;
01258 return true;
01259 }
01260 }
01261 return false;
01262 }
01263
01264 int64 FindCheapestValue(int index, const Assignment& assignment) const {
01265 IntVar** nexts = model_->Nexts();
01266 const int size = model_->Size();
01267 int64 best_evaluation = kint64max;
01268 int64 best_value = -1;
01269 if (index < size) {
01270 IntVar* const next = nexts[index];
01271 scoped_ptr<IntVarIterator> it(next->MakeDomainIterator(false));
01272 for (it->Init(); it->Ok(); it->Next()) {
01273 const int value = it->Value();
01274 if (value != index
01275 && (value >= size || !assignment.Contains(nexts[value]))) {
01276 const int64 evaluation = evaluator_->Run(index, value);
01277 if (evaluation <= best_evaluation) {
01278 best_evaluation = evaluation;
01279 best_value = value;
01280 }
01281 }
01282 }
01283 }
01284 return best_value;
01285 }
01286
01287 RoutingModel* const model_;
01288 scoped_ptr<ResultCallback2<int64, int64, int64> > evaluator_;
01289 };
01290
01291
01292
01293
01294 class AllUnperformed : public DecisionBuilder {
01295 public:
01296
01297 explicit AllUnperformed(RoutingModel* const model) : model_(model) {}
01298 virtual ~AllUnperformed() {}
01299 virtual Decision* Next(Solver* const solver) {
01300 for (int i = 0; i < model_->Size(); ++i) {
01301 if (!model_->IsStart(i)) {
01302 model_->ActiveVar(i)->SetValue(0);
01303 }
01304 }
01305 return NULL;
01306 }
01307
01308 private:
01309 RoutingModel* const model_;
01310 };
01311
01312
01313 RoutingModel::RoutingStrategy
01314 RoutingModel::GetSelectedFirstSolutionStrategy() const {
01315 if (FLAGS_routing_first_solution.compare("GlobalCheapestArc") == 0) {
01316 return ROUTING_GLOBAL_CHEAPEST_ARC;
01317 } else if (FLAGS_routing_first_solution.compare("LocalCheapestArc") == 0) {
01318 return ROUTING_LOCAL_CHEAPEST_ARC;
01319 } else if (FLAGS_routing_first_solution.compare("PathCheapestArc") == 0) {
01320 return ROUTING_PATH_CHEAPEST_ARC;
01321 } else if (FLAGS_routing_first_solution.compare("AllUnperformed") == 0) {
01322 return ROUTING_ALL_UNPERFORMED;
01323 } else if (FLAGS_routing_first_solution.compare("BestInsertion") == 0) {
01324 return ROUTING_BEST_INSERTION;
01325 }
01326 return first_solution_strategy_;
01327 }
01328
01329 RoutingModel::RoutingMetaheuristic
01330 RoutingModel::GetSelectedMetaheuristic() const {
01331 if (FLAGS_routing_tabu_search) {
01332 return ROUTING_TABU_SEARCH;
01333 } else if (FLAGS_routing_simulated_annealing) {
01334 return ROUTING_SIMULATED_ANNEALING;
01335 } else if (FLAGS_routing_guided_local_search) {
01336 return ROUTING_GUIDED_LOCAL_SEARCH;
01337 }
01338 return metaheuristic_;
01339 }
01340
01341 void RoutingModel::AddSearchMonitor(SearchMonitor* const monitor) {
01342 monitors_.push_back(monitor);
01343 }
01344
01345 const Assignment* RoutingModel::Solve(const Assignment* assignment) {
01346 QuietCloseModel();
01347 const int64 start_time_ms = solver_->wall_time();
01348 if (NULL == assignment) {
01349 solver_->Solve(solve_db_, monitors_);
01350 } else {
01351 assignment_->Copy(assignment);
01352 solver_->Solve(improve_db_, monitors_);
01353 }
01354 const int64 elapsed_time_ms = solver_->wall_time() - start_time_ms;
01355 if (collect_assignments_->solution_count() == 1) {
01356 status_ = ROUTING_SUCCESS;
01357 return collect_assignments_->solution(0);
01358 } else {
01359 if (elapsed_time_ms >= time_limit_ms_) {
01360 status_ = ROUTING_FAIL_TIMEOUT;
01361 } else {
01362 status_ = ROUTING_FAIL;
01363 }
01364 return NULL;
01365 }
01366 }
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378 int64 RoutingModel::ComputeLowerBound() {
01379 if (!closed_) {
01380 LOG(WARNING) << "Non-closed model not supported.";
01381 return 0;
01382 }
01383 if (!homogeneous_costs_) {
01384 LOG(WARNING) << "Non-homogeneous vehicle costs not supported";
01385 return 0;
01386 }
01387 if (disjunctions_.size() > 0) {
01388 LOG(WARNING)
01389 << "Node disjunction constraints or optional nodes not supported.";
01390 return 0;
01391 }
01392 const int num_nodes = Size() + vehicles_;
01393 ForwardStarGraph graph(2 * num_nodes, num_nodes * num_nodes);
01394 LinearSumAssignment<ForwardStarGraph> linear_sum_assignment(graph, num_nodes);
01395
01396
01397
01398 for (int tail = 0; tail < Size(); ++tail) {
01399 scoped_ptr<IntVarIterator> iterator(
01400 nexts_[tail]->MakeDomainIterator(false));
01401 for (iterator->Init(); iterator->Ok(); iterator->Next()) {
01402 const int head = iterator->Value();
01403
01404
01405
01406 if (head == tail) {
01407 continue;
01408 }
01409
01410
01411 const ArcIndex arc = graph.AddArc(tail, num_nodes + head);
01412 const CostValue cost = GetHomogeneousCost(tail, head);
01413 linear_sum_assignment.SetArcCost(arc, cost);
01414 }
01415 }
01416
01417
01418
01419 for (int tail = Size(); tail < num_nodes; ++tail) {
01420 const ArcIndex arc = graph.AddArc(tail, num_nodes + starts_[tail - Size()]);
01421 linear_sum_assignment.SetArcCost(arc, 0);
01422 }
01423 if (linear_sum_assignment.ComputeAssignment()) {
01424 return linear_sum_assignment.GetCost();
01425 }
01426 return 0;
01427 }
01428
01429 bool RoutingModel::RouteCanBeUsedByVehicle(const Assignment& assignment,
01430 int start_index,
01431 int vehicle) const {
01432 int current_index = IsStart(start_index) ?
01433 Next(assignment, start_index) : start_index;
01434 while (!IsEnd(current_index)) {
01435 const IntVar* const vehicle_var = VehicleVar(current_index);
01436 if (!vehicle_var->Contains(vehicle)) {
01437 return false;
01438 }
01439 const int next_index = Next(assignment, current_index);
01440 CHECK_NE(next_index, current_index) << "Inactive node inside a route";
01441 current_index = next_index;
01442 }
01443 return true;
01444 }
01445
01446 bool RoutingModel::ReplaceUnusedVehicle(
01447 int unused_vehicle,
01448 int active_vehicle,
01449 Assignment* const compact_assignment) const {
01450 CHECK_NOTNULL(compact_assignment);
01451 CHECK(!IsVehicleUsed(*compact_assignment, unused_vehicle));
01452 CHECK(IsVehicleUsed(*compact_assignment, active_vehicle));
01453
01454 const int unused_vehicle_start = Start(unused_vehicle);
01455 IntVar* const unused_vehicle_start_var = NextVar(unused_vehicle_start);
01456 const int unused_vehicle_end = End(unused_vehicle);
01457 const int active_vehicle_start = Start(active_vehicle);
01458 const int active_vehicle_end = End(active_vehicle);
01459 IntVar* const active_vehicle_start_var = NextVar(active_vehicle_start);
01460 const int active_vehicle_next =
01461 compact_assignment->Value(active_vehicle_start_var);
01462 compact_assignment->SetValue(unused_vehicle_start_var, active_vehicle_next);
01463 compact_assignment->SetValue(active_vehicle_start_var, End(active_vehicle));
01464
01465
01466 int current_index = active_vehicle_next;
01467 while (!IsEnd(current_index)) {
01468 IntVar* const vehicle_var = VehicleVar(current_index);
01469 compact_assignment->SetValue(vehicle_var, unused_vehicle);
01470 const int next_index = Next(*compact_assignment, current_index);
01471 if (IsEnd(next_index)) {
01472 IntVar* const last_next_var = NextVar(current_index);
01473 compact_assignment->SetValue(last_next_var, End(unused_vehicle));
01474 }
01475 current_index = next_index;
01476 }
01477
01478
01479 for (VarMap::const_iterator dimension = transits_.begin();
01480 dimension != transits_.end(); ++dimension) {
01481 IntVar** const transit_variables = dimension->second;
01482 IntVar* const unused_vehicle_transit_var =
01483 transit_variables[unused_vehicle_start];
01484 IntVar* const active_vehicle_transit_var =
01485 transit_variables[active_vehicle_start];
01486 const bool contains_unused_vehicle_transit_var =
01487 compact_assignment->Contains(unused_vehicle_transit_var);
01488 const bool contains_active_vehicle_transit_var =
01489 compact_assignment->Contains(active_vehicle_transit_var);
01490 if (contains_unused_vehicle_transit_var !=
01491 contains_active_vehicle_transit_var) {
01492 LG << "The assignment contains transit variable for dimension '"
01493 << dimension->first << "' for some vehicles, but not for all";
01494 return false;
01495 }
01496 if (contains_unused_vehicle_transit_var) {
01497 const int64 old_unused_vehicle_transit =
01498 compact_assignment->Value(unused_vehicle_transit_var);
01499 const int64 old_active_vehicle_transit =
01500 compact_assignment->Value(active_vehicle_transit_var);
01501 compact_assignment->SetValue(unused_vehicle_transit_var,
01502 old_active_vehicle_transit);
01503 compact_assignment->SetValue(active_vehicle_transit_var,
01504 old_unused_vehicle_transit);
01505 }
01506
01507
01508 IntVar** const cumul_variables =
01509 FindWithDefault(cumuls_, dimension->first, NULL);
01510 CHECK_NOTNULL(cumul_variables);
01511 IntVar* const unused_vehicle_cumul_var =
01512 cumul_variables[unused_vehicle_end];
01513 IntVar* const active_vehicle_cumul_var =
01514 cumul_variables[active_vehicle_end];
01515 const int64 old_unused_vehicle_cumul =
01516 compact_assignment->Value(unused_vehicle_cumul_var);
01517 const int64 old_active_vehicle_cumul =
01518 compact_assignment->Value(active_vehicle_cumul_var);
01519 compact_assignment->SetValue(unused_vehicle_cumul_var,
01520 old_active_vehicle_cumul);
01521 compact_assignment->SetValue(active_vehicle_cumul_var,
01522 old_unused_vehicle_cumul);
01523 }
01524 return true;
01525 }
01526
01527 Assignment* RoutingModel::CompactAssignment(
01528 const Assignment& assignment) const {
01529 CHECK_EQ(assignment.solver(), solver_.get());
01530 if (!homogeneous_costs_) {
01531 LG << "The costs are not homogeneous, routes cannot be rearranged";
01532 return NULL;
01533 }
01534
01535 Assignment* compact_assignment = new Assignment(&assignment);
01536 for (int vehicle = 0; vehicle < vehicles_ - 1; ++vehicle) {
01537 if (IsVehicleUsed(*compact_assignment, vehicle)) {
01538 continue;
01539 }
01540 const int vehicle_start = Start(vehicle);
01541 const int vehicle_end = End(vehicle);
01542
01543 int swap_vehicle = vehicles_ - 1;
01544 bool has_more_vehicles_with_route = false;
01545 for (; swap_vehicle > vehicle; --swap_vehicle) {
01546
01547
01548 if (!IsVehicleUsed(*compact_assignment, swap_vehicle)
01549 || !IsVehicleUsed(*compact_assignment, swap_vehicle)) {
01550 continue;
01551 }
01552 has_more_vehicles_with_route = true;
01553 const int swap_vehicle_start = Start(swap_vehicle);
01554 const int swap_vehicle_end = End(swap_vehicle);
01555 if (IndexToNode(vehicle_start) != IndexToNode(swap_vehicle_start)
01556 || IndexToNode(vehicle_end) != IndexToNode(swap_vehicle_end)) {
01557 continue;
01558 }
01559
01560
01561 if (RouteCanBeUsedByVehicle(*compact_assignment, swap_vehicle_start,
01562 vehicle)) {
01563 break;
01564 }
01565 }
01566
01567 if (swap_vehicle == vehicle) {
01568 if (has_more_vehicles_with_route) {
01569
01570
01571 LG << "No vehicle that can be swapped with " << vehicle << " was found";
01572 delete compact_assignment;
01573 return NULL;
01574 } else {
01575 break;
01576 }
01577 } else {
01578 if (!ReplaceUnusedVehicle(vehicle, swap_vehicle, compact_assignment)) {
01579 delete compact_assignment;
01580 return NULL;
01581 }
01582 }
01583 }
01584 if (FLAGS_routing_check_compact_assignment) {
01585 if (!solver_->CheckAssignment(compact_assignment)) {
01586 LG << "The compacted assignment is not a valid solution";
01587 delete compact_assignment;
01588 return NULL;
01589 }
01590 }
01591 return compact_assignment;
01592 }
01593
01594 int RoutingModel::FindNextActive(int index, const std::vector<int>& nodes) const {
01595 ++index;
01596 CHECK_LE(0, index);
01597 const int size = nodes.size();
01598 while (index < size && ActiveVar(nodes[index])->Max() == 0) {
01599 ++index;
01600 }
01601 return index;
01602 }
01603
01604 IntVar* RoutingModel::ApplyLocks(const std::vector<int>& locks) {
01605
01606
01607 CHECK_EQ(vehicles_, 1);
01608 preassignment_->Clear();
01609 IntVar* next_var = NULL;
01610 int lock_index = FindNextActive(-1, locks);
01611 const int size = locks.size();
01612 if (lock_index < size) {
01613 next_var = NextVar(locks[lock_index]);
01614 preassignment_->Add(next_var);
01615 for (lock_index = FindNextActive(lock_index, locks);
01616 lock_index < size;
01617 lock_index = FindNextActive(lock_index, locks)) {
01618 preassignment_->SetValue(next_var, locks[lock_index]);
01619 next_var = NextVar(locks[lock_index]);
01620 preassignment_->Add(next_var);
01621 }
01622 }
01623 return next_var;
01624 }
01625
01626 bool RoutingModel::ApplyLocksToAllVehicles(
01627 const std::vector<std::vector<NodeIndex> >& locks, bool close_routes) {
01628 preassignment_->Clear();
01629 return RoutesToAssignment(locks, true, close_routes, preassignment_);
01630 }
01631
01632 void RoutingModel::UpdateTimeLimit(int64 limit_ms) {
01633 time_limit_ms_ = limit_ms;
01634 if (limit_ != NULL) {
01635 solver_->UpdateLimits(time_limit_ms_,
01636 kint64max,
01637 kint64max,
01638 FLAGS_routing_solution_limit,
01639 limit_);
01640 }
01641 if (ls_limit_ != NULL) {
01642 solver_->UpdateLimits(time_limit_ms_,
01643 kint64max,
01644 kint64max,
01645 1,
01646 ls_limit_);
01647 }
01648 }
01649
01650 void RoutingModel::UpdateLNSTimeLimit(int64 limit_ms) {
01651 lns_time_limit_ms_ = limit_ms;
01652 if (lns_limit_ != NULL) {
01653 solver_->UpdateLimits(lns_time_limit_ms_,
01654 kint64max,
01655 kint64max,
01656 kint64max,
01657 lns_limit_);
01658 }
01659 }
01660
01661 void RoutingModel::SetCommandLineOption(const string& name,
01662 const string& value) {
01663 google::SetCommandLineOption(name.c_str(), value.c_str());
01664 }
01665
01666 bool RoutingModel::WriteAssignment(const string& file_name) const {
01667 if (collect_assignments_->solution_count() == 1 && assignment_ != NULL) {
01668 assignment_->Copy(collect_assignments_->solution(0));
01669 return assignment_->Save(file_name);
01670 } else {
01671 return false;
01672 }
01673 }
01674
01675 Assignment* RoutingModel::ReadAssignment(const string& file_name) {
01676 QuietCloseModel();
01677 CHECK(assignment_ != NULL);
01678 if (assignment_->Load(file_name)) {
01679 return DoRestoreAssignment();
01680 }
01681 return NULL;
01682 }
01683
01684 Assignment* RoutingModel::RestoreAssignment(const Assignment& solution) {
01685 QuietCloseModel();
01686 CHECK(assignment_ != NULL);
01687 assignment_->Copy(&solution);
01688 return DoRestoreAssignment();
01689 }
01690
01691 Assignment* RoutingModel::DoRestoreAssignment() {
01692 solver_->Solve(restore_assignment_, monitors_);
01693 if (collect_assignments_->solution_count() == 1) {
01694 status_ = ROUTING_SUCCESS;
01695 return collect_assignments_->solution(0);
01696 } else {
01697 status_ = ROUTING_FAIL;
01698 return NULL;
01699 }
01700 return NULL;
01701 }
01702
01703 bool RoutingModel::RoutesToAssignment(const std::vector<std::vector<NodeIndex> >& routes,
01704 bool ignore_inactive_nodes,
01705 bool close_routes,
01706 Assignment* const assignment) const {
01707 CHECK_NOTNULL(assignment);
01708 if (!closed_) {
01709 LOG(ERROR) << "The model is not closed yet";
01710 return false;
01711 }
01712 const int num_routes = routes.size();
01713 if (num_routes > vehicles_) {
01714 LOG(ERROR) << "The number of vehicles in the assignment (" << routes.size()
01715 << ") is greater than the number of vehicles in the model ("
01716 << vehicles_ << ")";
01717 return false;
01718 }
01719
01720 hash_set<int> visited_indices;
01721
01722 for (int vehicle = 0; vehicle < num_routes; ++vehicle) {
01723 const std::vector<NodeIndex>& route = routes[vehicle];
01724 int from_index = Start(vehicle);
01725 std::pair<hash_set<int>::iterator, bool> insert_result =
01726 visited_indices.insert(from_index);
01727 if (!insert_result.second) {
01728 LOG(ERROR) << "Index " << from_index << " (start node for vehicle "
01729 << vehicle << ") was already used";
01730 return false;
01731 }
01732
01733 for (int i = 0; i < route.size(); ++i) {
01734 const NodeIndex to_node = route[i];
01735 if (to_node < 0 || to_node >= nodes()) {
01736 LOG(ERROR) << "Invalid node index: " << to_node;
01737 return false;
01738 }
01739 const int to_index = NodeToIndex(to_node);
01740 if (to_index < 0 || to_index >= Size()) {
01741 LOG(ERROR) << "Invalid index: " << to_index << " from node "
01742 << to_node;
01743 return false;
01744 }
01745
01746 IntVar* const active_var = ActiveVar(to_index);
01747 if (active_var->Max() == 0) {
01748 if (ignore_inactive_nodes) {
01749 continue;
01750 } else {
01751 LOG(ERROR) << "Index " << to_index << " (node " << to_node
01752 << ") is not active";
01753 return false;
01754 }
01755 }
01756
01757 insert_result = visited_indices.insert(to_index);
01758 if (!insert_result.second) {
01759 LOG(ERROR) << "Index " << to_index << " (node " << to_node
01760 << ") is used multiple times";
01761 return false;
01762 }
01763
01764 const IntVar* const vehicle_var = VehicleVar(to_index);
01765 if (!vehicle_var->Contains(vehicle)) {
01766 LOG(ERROR) << "Vehicle " << vehicle << " is not allowed at index "
01767 << to_index << " (node " << to_node << ")";
01768 return false;
01769 }
01770
01771 IntVar* const from_var = NextVar(from_index);
01772 if (!assignment->Contains(from_var)) {
01773 assignment->Add(from_var);
01774 }
01775 assignment->SetValue(from_var, to_index);
01776
01777 from_index = to_index;
01778 }
01779
01780 if (close_routes) {
01781 IntVar* const last_var = NextVar(from_index);
01782 if (!assignment->Contains(last_var)) {
01783 assignment->Add(last_var);
01784 }
01785 assignment->SetValue(last_var, End(vehicle));
01786 }
01787 }
01788
01789
01790 for (int vehicle = num_routes; vehicle < vehicles_; ++vehicle) {
01791 const int start_index = Start(vehicle);
01792
01793
01794 std::pair<hash_set<int>::iterator, bool> insert_result =
01795 visited_indices.insert(start_index);
01796 if (!insert_result.second) {
01797 LOG(ERROR) << "Index " << start_index << " is used multiple times";
01798 return false;
01799 }
01800 if (close_routes) {
01801 IntVar* const start_var = NextVar(start_index);
01802 if (!assignment->Contains(start_var)) {
01803 assignment->Add(start_var);
01804 }
01805 assignment->SetValue(start_var, End(vehicle));
01806 }
01807 }
01808
01809
01810 if (close_routes) {
01811 for (int index = 0; index < Size(); ++index) {
01812 if (!ContainsKey(visited_indices, index)) {
01813 IntVar* const next_var = NextVar(index);
01814 if (!assignment->Contains(next_var)) {
01815 assignment->Add(next_var);
01816 }
01817 assignment->SetValue(next_var, index);
01818 }
01819 }
01820 }
01821
01822 return true;
01823 }
01824
01825 Assignment* RoutingModel::ReadAssignmentFromRoutes(
01826 const std::vector<std::vector<NodeIndex> >& routes,
01827 bool ignore_inactive_nodes) {
01828 QuietCloseModel();
01829 if (!RoutesToAssignment(routes, ignore_inactive_nodes, true, assignment_)) {
01830 return NULL;
01831 }
01832
01833
01834
01835 return DoRestoreAssignment();
01836 }
01837
01838 void RoutingModel::AssignmentToRoutes(
01839 const Assignment& assignment,
01840 std::vector<std::vector<NodeIndex> >* const routes) const {
01841 CHECK(closed_);
01842 CHECK_NOTNULL(routes);
01843
01844 const int model_size = Size();
01845 routes->resize(vehicles_);
01846 for (int vehicle = 0; vehicle < vehicles_; ++vehicle) {
01847 std::vector<NodeIndex>* const vehicle_route = &routes->at(vehicle);
01848 vehicle_route->clear();
01849
01850 int num_visited_nodes = 0;
01851 const int first_index = Start(vehicle);
01852 const IntVar* const first_var = NextVar(first_index);
01853 CHECK(assignment.Contains(first_var));
01854 CHECK(assignment.Bound(first_var));
01855 int current_index = assignment.Value(first_var);
01856 while (!IsEnd(current_index)) {
01857 vehicle_route->push_back(IndexToNode(current_index));
01858
01859 const IntVar* const next_var = NextVar(current_index);
01860 CHECK(assignment.Contains(next_var));
01861 CHECK(assignment.Bound(next_var));
01862 current_index = assignment.Value(next_var);
01863
01864 ++num_visited_nodes;
01865 CHECK_LE(num_visited_nodes, model_size)
01866 << "The assignment contains a cycle";
01867 }
01868 }
01869 }
01870
01871 RoutingModel::NodeIndex RoutingModel::IndexToNode(int64 index) const {
01872 DCHECK_LT(index, index_to_node_.size());
01873 return index_to_node_[index];
01874 }
01875
01876 int64 RoutingModel::NodeToIndex(NodeIndex node) const {
01877 DCHECK_LT(node, node_to_index_.size());
01878 DCHECK_NE(node_to_index_[node], kUnassigned);
01879 return node_to_index_[node];
01880 }
01881
01882 void RoutingModel::GetDisjunctionIndicesFromIndex(int64 index,
01883 std::vector<int>* indices) const {
01884 CHECK_NOTNULL(indices);
01885 int disjunction = -1;
01886 if (FindCopy(node_to_disjunction_, index, &disjunction)) {
01887 *indices = disjunctions_[disjunction].nodes;
01888 } else {
01889 indices->clear();
01890 }
01891 }
01892
01893 int64 RoutingModel::GetArcCost(int64 i, int64 j, int64 vehicle) {
01894 if (vehicle < 0) {
01895
01896
01897
01898
01899
01900
01901
01902 return 0;
01903 }
01904 CostCacheElement& cache = cost_cache_[i];
01905 if (cache.node == j && cache.vehicle == vehicle) {
01906 return cache.cost;
01907 }
01908 const NodeIndex node_i = IndexToNode(i);
01909 const NodeIndex node_j = IndexToNode(j);
01910 int64 cost = 0;
01911 if (!IsStart(i)) {
01912 cost = costs_[vehicle]->Run(node_i, node_j);
01913 } else if (!IsEnd(j)) {
01914
01915
01916 cost = costs_[vehicle]->Run(node_i, node_j)
01917 + fixed_costs_[index_to_vehicle_[i]];
01918 } else {
01919
01920
01921 cost = 0;
01922 }
01923 cache.node = j;
01924 cache.vehicle = vehicle;
01925 cache.cost = cost;
01926 return cost;
01927 }
01928
01929 int64 RoutingModel::GetPenaltyCost(int64 i) const {
01930 int index = kUnassigned;
01931 if (FindCopy(node_to_disjunction_, i, &index)) {
01932 const Disjunction& disjunction = disjunctions_[index];
01933 int64 penalty = disjunction.penalty;
01934 if (penalty > 0 && disjunction.nodes.size() == 1) {
01935 return penalty;
01936 } else {
01937 return 0;
01938 }
01939 } else {
01940 return 0;
01941 }
01942 }
01943
01944 bool RoutingModel::IsStart(int64 index) const {
01945 return !IsEnd(index) && index_to_vehicle_[index] != kUnassigned;
01946 }
01947
01948 bool RoutingModel::IsVehicleUsed(const Assignment& assignment,
01949 int vehicle) const {
01950 CHECK_GE(vehicle, 0);
01951 CHECK_LT(vehicle, vehicles_);
01952 CHECK_EQ(solver_.get(), assignment.solver());
01953 IntVar* const start_var = NextVar(Start(vehicle));
01954 CHECK(assignment.Contains(start_var));
01955 return !IsEnd(assignment.Value(start_var));
01956 }
01957
01958 int RoutingModel::Next(const Assignment& assignment,
01959 int index) const {
01960 CHECK_EQ(solver_.get(), assignment.solver());
01961 IntVar* const next_var = NextVar(index);
01962 CHECK(assignment.Contains(next_var));
01963 CHECK(assignment.Bound(next_var));
01964 return assignment.Value(next_var);
01965 }
01966
01967 int64 RoutingModel::GetCost(int64 i, int64 j, int64 vehicle) {
01968 if (i != j) {
01969 return GetArcCost(i, j, vehicle);
01970 } else {
01971 return 0;
01972 }
01973 }
01974
01975 int64 RoutingModel::GetFilterCost(int64 i, int64 j, int64 vehicle) {
01976 if (i != j) {
01977 return GetArcCost(i, j, vehicle);
01978 } else {
01979 return GetPenaltyCost(i);
01980 }
01981 }
01982
01983
01984 int64 RoutingModel::GetFirstSolutionCost(int64 i, int64 j) {
01985 if (j < nodes_) {
01986
01987 return GetCost(i, j, 0);
01988 } else {
01989 return kint64max;
01990 }
01991 }
01992
01993 void RoutingModel::CheckDepot() {
01994 if (!is_depot_set_) {
01995 LOG(WARNING) << "A depot must be specified, setting one at node 0";
01996 SetDepot(NodeIndex(0));
01997 }
01998 }
01999
02000 Assignment* RoutingModel::GetOrCreateAssignment() {
02001 if (assignment_ == NULL) {
02002 const int size = Size();
02003 assignment_ = solver_->MakeAssignment();
02004 assignment_->Add(nexts_.get(), size);
02005 if (!homogeneous_costs_) {
02006 assignment_->Add(vehicle_vars_.get(), size + vehicles_);
02007 }
02008 assignment_->AddObjective(cost_);
02009 }
02010 return assignment_;
02011 }
02012
02013 SearchLimit* RoutingModel::GetOrCreateLimit() {
02014 if (limit_ == NULL) {
02015 limit_ = solver_->MakeLimit(time_limit_ms_,
02016 kint64max,
02017 kint64max,
02018 FLAGS_routing_solution_limit,
02019 true);
02020 }
02021 return limit_;
02022 }
02023
02024 SearchLimit* RoutingModel::GetOrCreateLocalSearchLimit() {
02025 if (ls_limit_ == NULL) {
02026 ls_limit_ = solver_->MakeLimit(time_limit_ms_,
02027 kint64max,
02028 kint64max,
02029 1,
02030 true);
02031 }
02032 return ls_limit_;
02033 }
02034
02035 SearchLimit* RoutingModel::GetOrCreateLargeNeighborhoodSearchLimit() {
02036 if (lns_limit_ == NULL) {
02037 lns_limit_ = solver_->MakeLimit(lns_time_limit_ms_,
02038 kint64max,
02039 kint64max,
02040 kint64max);
02041 }
02042 return lns_limit_;
02043 }
02044
02045 LocalSearchOperator* RoutingModel::CreateInsertionOperator() {
02046 const int size = Size();
02047 if (pickup_delivery_pairs_.size() > 0) {
02048 const IntVar* const* vehicle_vars =
02049 homogeneous_costs_ ? NULL : vehicle_vars_.get();
02050 return MakePairActive(solver_.get(),
02051 nexts_.get(),
02052 vehicle_vars,
02053 pickup_delivery_pairs_,
02054 size);
02055 } else {
02056 if (homogeneous_costs_) {
02057 return solver_->MakeOperator(nexts_.get(),
02058 size,
02059 Solver::MAKEACTIVE);
02060 } else {
02061 return solver_->MakeOperator(nexts_.get(),
02062 vehicle_vars_.get(),
02063 size,
02064 Solver::MAKEACTIVE);
02065 }
02066 }
02067 }
02068
02069 #define CP_ROUTING_PUSH_BACK_OPERATOR(operator_type) \
02070 if (homogeneous_costs_) { \
02071 operators.push_back(solver_->MakeOperator(nexts_.get(), \
02072 size, \
02073 operator_type)); \
02074 } else { \
02075 operators.push_back(solver_->MakeOperator(nexts_.get(), \
02076 vehicle_vars_.get(), \
02077 size, \
02078 operator_type)); \
02079 }
02080
02081 #define CP_ROUTING_PUSH_BACK_CALLBACK_OPERATOR(operator_type) \
02082 if (homogeneous_costs_) { \
02083 operators.push_back(solver_->MakeOperator(nexts_.get(), \
02084 size, \
02085 BuildCostCallback(), \
02086 operator_type)); \
02087 } else { \
02088 operators.push_back(solver_->MakeOperator(nexts_.get(), \
02089 vehicle_vars_.get(), \
02090 size, \
02091 BuildCostCallback(), \
02092 operator_type)); \
02093 }
02094
02095 LocalSearchOperator* RoutingModel::CreateNeighborhoodOperators() {
02096 const int size = Size();
02097 std::vector<LocalSearchOperator*> operators = extra_operators_;
02098 if (pickup_delivery_pairs_.size() > 0) {
02099 const IntVar* const* vehicle_vars =
02100 homogeneous_costs_ ? NULL : vehicle_vars_.get();
02101 operators.push_back(MakePairRelocate(solver_.get(),
02102 nexts_.get(),
02103 vehicle_vars,
02104 pickup_delivery_pairs_,
02105 size));
02106 }
02107 if (vehicles_ > 1) {
02108 if (!FLAGS_routing_no_relocate) {
02109 CP_ROUTING_PUSH_BACK_OPERATOR(Solver::RELOCATE);
02110 }
02111 if (!FLAGS_routing_no_exchange) {
02112 CP_ROUTING_PUSH_BACK_OPERATOR(Solver::EXCHANGE);
02113 }
02114 if (!FLAGS_routing_no_cross) {
02115 CP_ROUTING_PUSH_BACK_OPERATOR(Solver::CROSS);
02116 }
02117 }
02118 if (!FLAGS_routing_no_lkh
02119 && !FLAGS_routing_tabu_search
02120 && !FLAGS_routing_simulated_annealing) {
02121 CP_ROUTING_PUSH_BACK_CALLBACK_OPERATOR(Solver::LK);
02122 }
02123 if (!FLAGS_routing_no_2opt) {
02124 CP_ROUTING_PUSH_BACK_OPERATOR(Solver::TWOOPT);
02125 }
02126 if (!FLAGS_routing_no_oropt) {
02127 CP_ROUTING_PUSH_BACK_OPERATOR(Solver::OROPT);
02128 }
02129 if (!FLAGS_routing_no_make_active && disjunctions_.size() != 0) {
02130 CP_ROUTING_PUSH_BACK_OPERATOR(Solver::MAKEINACTIVE);
02131
02132
02133
02134
02135 operators.push_back(CreateInsertionOperator());
02136 if (!FLAGS_routing_use_extended_swap_active) {
02137 CP_ROUTING_PUSH_BACK_OPERATOR(Solver::SWAPACTIVE);
02138 } else {
02139 CP_ROUTING_PUSH_BACK_OPERATOR(Solver::EXTENDEDSWAPACTIVE);
02140 }
02141 }
02142
02143 if (!FLAGS_routing_no_tsp
02144 && !FLAGS_routing_tabu_search
02145 && !FLAGS_routing_simulated_annealing) {
02146 CP_ROUTING_PUSH_BACK_CALLBACK_OPERATOR(Solver::TSPOPT);
02147 }
02148 if (!FLAGS_routing_no_tsplns
02149 && !FLAGS_routing_tabu_search
02150 && !FLAGS_routing_simulated_annealing) {
02151 CP_ROUTING_PUSH_BACK_CALLBACK_OPERATOR(Solver::TSPLNS);
02152 }
02153 if (!FLAGS_routing_no_lns) {
02154 CP_ROUTING_PUSH_BACK_OPERATOR(Solver::PATHLNS);
02155 if (disjunctions_.size() != 0) {
02156 CP_ROUTING_PUSH_BACK_OPERATOR(Solver::UNACTIVELNS);
02157 }
02158 }
02159 return solver_->ConcatenateOperators(operators);
02160 }
02161
02162 #undef CP_ROUTING_PUSH_BACK_CALLBACK_OPERATOR
02163 #undef CP_ROUTING_PUSH_BACK_OPERATOR
02164
02165 const std::vector<LocalSearchFilter*>&
02166 RoutingModel::GetOrCreateLocalSearchFilters() {
02167 if (filters_.empty()) {
02168 const int size = Size();
02169 if (FLAGS_routing_use_objective_filter) {
02170 if (homogeneous_costs_) {
02171 LocalSearchFilter* filter =
02172 solver_->MakeLocalSearchObjectiveFilter(
02173 nexts_.get(),
02174 size,
02175 NewPermanentCallback(this,
02176 &RoutingModel::GetHomogeneousFilterCost),
02177 cost_,
02178 Solver::EQ,
02179 Solver::SUM);
02180 filters_.push_back(filter);
02181 } else {
02182 LocalSearchFilter* filter =
02183 solver_->MakeLocalSearchObjectiveFilter(
02184 nexts_.get(),
02185 vehicle_vars_.get(),
02186 size,
02187 NewPermanentCallback(this, &RoutingModel::GetFilterCost),
02188 cost_,
02189 Solver::EQ,
02190 Solver::SUM);
02191 filters_.push_back(filter);
02192 }
02193 }
02194 if (FLAGS_routing_use_pickup_and_delivery_filter
02195 && pickup_delivery_pairs_.size() > 0) {
02196 filters_.push_back(solver_->RevAlloc(new NodePrecedenceFilter(
02197 nexts_.get(),
02198 Size(),
02199 Size() + vehicles_,
02200 pickup_delivery_pairs_,
02201 "")));
02202 }
02203 if (FLAGS_routing_use_path_cumul_filter) {
02204 for (ConstIter<VarMap> iter(cumuls_); !iter.at_end(); ++iter) {
02205 const string& name = iter->first;
02206 filters_.push_back(solver_->RevAlloc(
02207 new PathCumulFilter(nexts_.get(),
02208 Size(),
02209 iter->second,
02210 Size() + vehicles_,
02211 transit_evaluators_[name],
02212 name)));
02213 }
02214 }
02215 }
02216 return filters_;
02217 }
02218
02219 DecisionBuilder* RoutingModel::CreateSolutionFinalizer() {
02220 return solver_->MakePhase(nexts_.get(), Size(),
02221 Solver::CHOOSE_FIRST_UNBOUND,
02222 Solver::ASSIGN_MIN_VALUE);
02223 }
02224
02225 DecisionBuilder* RoutingModel::CreateFirstSolutionDecisionBuilder() {
02226 const int size = Size();
02227 DecisionBuilder* finalize_solution = CreateSolutionFinalizer();
02228 DecisionBuilder* first_solution = finalize_solution;
02229 switch (GetSelectedFirstSolutionStrategy()) {
02230 case ROUTING_GLOBAL_CHEAPEST_ARC:
02231 LG << "Using ROUTING_GLOBAL_CHEAPEST_ARC";
02232 first_solution =
02233 solver_->MakePhase(nexts_.get(), size,
02234 NewPermanentCallback(
02235 this,
02236 &RoutingModel::GetFirstSolutionCost),
02237 Solver::CHOOSE_STATIC_GLOBAL_BEST);
02238 break;
02239 case ROUTING_LOCAL_CHEAPEST_ARC:
02240 LG << "Using ROUTING_LOCAL_CHEAPEST_ARC";
02241 first_solution =
02242 solver_->MakePhase(nexts_.get(), size,
02243 Solver::CHOOSE_FIRST_UNBOUND,
02244 NewPermanentCallback(
02245 this,
02246 &RoutingModel::GetFirstSolutionCost));
02247 break;
02248 case ROUTING_PATH_CHEAPEST_ARC:
02249 LG << "Using ROUTING_PATH_CHEAPEST_ARC";
02250 first_solution =
02251 solver_->MakePhase(nexts_.get(), size,
02252 Solver::CHOOSE_PATH,
02253 NewPermanentCallback(
02254 this,
02255 &RoutingModel::GetFirstSolutionCost));
02256 if (vehicles() == 1) {
02257 DecisionBuilder* fast_one_path_builder =
02258 solver_->RevAlloc(new FastOnePathBuilder(
02259 this,
02260 NewPermanentCallback(
02261 this,
02262 &RoutingModel::GetFirstSolutionCost)));
02263 first_solution = solver_->Try(fast_one_path_builder, first_solution);
02264 }
02265 break;
02266 case ROUTING_EVALUATOR_STRATEGY:
02267 LG << "Using ROUTING_EVALUATOR_STRATEGY";
02268 CHECK(first_solution_evaluator_ != NULL);
02269 first_solution =
02270 solver_->MakePhase(nexts_.get(), size,
02271 Solver::CHOOSE_PATH,
02272 NewPermanentCallback(
02273 first_solution_evaluator_.get(),
02274 &Solver::IndexEvaluator2::Run));
02275 break;
02276 case ROUTING_DEFAULT_STRATEGY:
02277 LG << "Using DEFAULT";
02278 break;
02279 case ROUTING_ALL_UNPERFORMED:
02280 first_solution =
02281 solver_->RevAlloc(new AllUnperformed(this));
02282 break;
02283 case ROUTING_BEST_INSERTION: {
02284 LG << "Using ROUTING_BEST_INSERTION";
02285 SearchLimit* const ls_limit = solver_->MakeLimit(time_limit_ms_,
02286 kint64max,
02287 kint64max,
02288 kint64max,
02289 true);
02290 DecisionBuilder* const finalize =
02291 solver_->MakeSolveOnce(finalize_solution,
02292 GetOrCreateLargeNeighborhoodSearchLimit());
02293 LocalSearchPhaseParameters* const insertion_parameters =
02294 solver_->MakeLocalSearchPhaseParameters(
02295 CreateInsertionOperator(),
02296 finalize,
02297 ls_limit,
02298 GetOrCreateLocalSearchFilters());
02299 std::vector<SearchMonitor*> monitors;
02300 monitors.push_back(GetOrCreateLimit());
02301 first_solution = solver_->MakeNestedOptimize(
02302 solver_->MakeLocalSearchPhase(
02303 nexts_.get(),
02304 size,
02305 solver_->RevAlloc(new AllUnperformed(this)),
02306 insertion_parameters),
02307 GetOrCreateAssignment(),
02308 false,
02309 FLAGS_routing_optimization_step,
02310 monitors);
02311 first_solution = solver_->Compose(first_solution, finalize);
02312 break;
02313 }
02314 default:
02315 LOG(WARNING) << "Unknown argument for routing_first_solution, "
02316 "using default";
02317 }
02318 if (FLAGS_routing_use_first_solution_dive) {
02319 DecisionBuilder* apply =
02320 solver_->MakeApplyBranchSelector(NewPermanentCallback(&LeftDive));
02321 first_solution = solver_->Compose(apply, first_solution);
02322 }
02323 return first_solution;
02324 }
02325
02326 LocalSearchPhaseParameters* RoutingModel::CreateLocalSearchParameters() {
02327 return solver_->MakeLocalSearchPhaseParameters(
02328 CreateNeighborhoodOperators(),
02329 solver_->MakeSolveOnce(CreateSolutionFinalizer(),
02330 GetOrCreateLargeNeighborhoodSearchLimit()),
02331 GetOrCreateLocalSearchLimit(),
02332 GetOrCreateLocalSearchFilters());
02333 }
02334
02335 DecisionBuilder* RoutingModel::CreateLocalSearchDecisionBuilder() {
02336 const int size = Size();
02337 DecisionBuilder* first_solution = CreateFirstSolutionDecisionBuilder();
02338 LocalSearchPhaseParameters* parameters = CreateLocalSearchParameters();
02339 if (homogeneous_costs_) {
02340 return solver_->MakeLocalSearchPhase(nexts_.get(),
02341 size,
02342 first_solution,
02343 parameters);
02344 } else {
02345 const int all_size = size + size + vehicles_;
02346 scoped_array<IntVar*> all_vars(new IntVar*[all_size]);
02347 for (int i = 0; i < size; ++i) {
02348 all_vars[i] = nexts_[i];
02349 }
02350 for (int i = size; i < all_size; ++i) {
02351 all_vars[i] = vehicle_vars_[i - size];
02352 }
02353 return solver_->MakeLocalSearchPhase(all_vars.get(),
02354 all_size,
02355 first_solution,
02356 parameters);
02357 }
02358 }
02359
02360 void RoutingModel::SetupDecisionBuilders() {
02361 if (FLAGS_routing_dfs) {
02362 solve_db_ = CreateFirstSolutionDecisionBuilder();
02363 } else {
02364 solve_db_ = CreateLocalSearchDecisionBuilder();
02365 }
02366 CHECK_NOTNULL(preassignment_);
02367 DecisionBuilder* restore_preassignment =
02368 solver_->MakeRestoreAssignment(preassignment_);
02369 solve_db_ = solver_->Compose(restore_preassignment, solve_db_);
02370 improve_db_ =
02371 solver_->Compose(restore_preassignment,
02372 solver_->MakeLocalSearchPhase(
02373 GetOrCreateAssignment(),
02374 CreateLocalSearchParameters()));
02375 restore_assignment_ =
02376 solver_->Compose(solver_->MakeRestoreAssignment(GetOrCreateAssignment()),
02377 CreateSolutionFinalizer());
02378 }
02379
02380 void RoutingModel::SetupMetaheuristics() {
02381 const int size = Size();
02382 SearchMonitor* optimize;
02383 switch (GetSelectedMetaheuristic()) {
02384 case ROUTING_GUIDED_LOCAL_SEARCH:
02385 LG << "Using Guided Local Search";
02386 if (homogeneous_costs_) {
02387 optimize = solver_->MakeGuidedLocalSearch(
02388 false,
02389 cost_,
02390 NewPermanentCallback(this, &RoutingModel::GetHomogeneousCost),
02391 FLAGS_routing_optimization_step,
02392 nexts_.get(), size,
02393 FLAGS_routing_guided_local_search_lamda_coefficient);
02394 } else {
02395 optimize = solver_->MakeGuidedLocalSearch(
02396 false,
02397 cost_,
02398 BuildCostCallback(),
02399 FLAGS_routing_optimization_step,
02400 nexts_.get(), vehicle_vars_.get(), size,
02401 FLAGS_routing_guided_local_search_lamda_coefficient);
02402 }
02403 break;
02404 case ROUTING_SIMULATED_ANNEALING:
02405 LG << "Using Simulated Annealing";
02406 optimize =
02407 solver_->MakeSimulatedAnnealing(false, cost_,
02408 FLAGS_routing_optimization_step,
02409 100);
02410 break;
02411 case ROUTING_TABU_SEARCH:
02412 LG << "Using Tabu Search";
02413 optimize = solver_->MakeTabuSearch(false, cost_,
02414 FLAGS_routing_optimization_step,
02415 nexts_.get(), size,
02416 10, 10, .8);
02417 break;
02418 default:
02419 LG << "Using greedy descent";
02420 optimize = solver_->MakeMinimize(cost_, FLAGS_routing_optimization_step);
02421 }
02422 monitors_.push_back(optimize);
02423 }
02424
02425 void RoutingModel::SetupAssignmentCollector() {
02426 const int size = Size();
02427 Assignment* full_assignment = solver_->MakeAssignment();
02428 for (ConstIter<VarMap> it(cumuls_); !it.at_end(); ++it) {
02429 full_assignment->Add(it->second, size + vehicles_);
02430 }
02431 for (int i = 0; i < extra_vars_.size(); ++i) {
02432 full_assignment->Add(extra_vars_[i]);
02433 }
02434 full_assignment->Add(nexts_.get(), size);
02435 full_assignment->Add(active_.get(), size);
02436 full_assignment->Add(vehicle_vars_.get(), size + vehicles_);
02437 full_assignment->AddObjective(cost_);
02438
02439 collect_assignments_ =
02440 solver_->MakeBestValueSolutionCollector(full_assignment, false);
02441 monitors_.push_back(collect_assignments_);
02442 }
02443
02444 void RoutingModel::SetupTrace() {
02445 if (FLAGS_routing_trace) {
02446 const int kLogPeriod = 10000;
02447 SearchMonitor* trace = solver_->MakeSearchLog(kLogPeriod, cost_);
02448 monitors_.push_back(trace);
02449 }
02450 if (FLAGS_routing_search_trace) {
02451 SearchMonitor* trace = solver_->MakeSearchTrace("Routing ");
02452 monitors_.push_back(trace);
02453 }
02454 }
02455
02456 void RoutingModel::SetupSearchMonitors() {
02457 monitors_.push_back(GetOrCreateLimit());
02458 SetupMetaheuristics();
02459 SetupAssignmentCollector();
02460 SetupTrace();
02461 }
02462
02463 void RoutingModel::SetupSearch() {
02464 SetupDecisionBuilders();
02465 SetupSearchMonitors();
02466 }
02467
02468
02469 IntVar* RoutingModel::CumulVar(int64 index, const string& name) const {
02470 IntVar** named_cumuls = FindPtrOrNull(cumuls_, name);
02471 if (named_cumuls != NULL) {
02472 return named_cumuls[index];
02473 } else {
02474 return NULL;
02475 }
02476 }
02477
02478 IntVar* RoutingModel::TransitVar(int64 index, const string& name) const {
02479 IntVar** named_transits = FindPtrOrNull(transits_, name);
02480 if (named_transits != NULL) {
02481 return named_transits[index];
02482 } else {
02483 return NULL;
02484 }
02485 }
02486
02487 void RoutingModel::AddToAssignment(IntVar* const var) {
02488 extra_vars_.push_back(var);
02489 }
02490
02491 RoutingModel::NodeEvaluator2* RoutingModel::NewCachedCallback(
02492 NodeEvaluator2* callback) {
02493 const int size = node_to_index_.size();
02494 if (FLAGS_routing_cache_callbacks && size <= FLAGS_routing_max_cache_size) {
02495 routing_caches_.push_back(new RoutingCache(callback, size));
02496 NodeEvaluator2* const cached_evaluator =
02497 NewPermanentCallback(routing_caches_.back(), &RoutingCache::Run);
02498 owned_node_callbacks_.insert(cached_evaluator);
02499 return cached_evaluator;
02500 } else {
02501 owned_node_callbacks_.insert(callback);
02502 return callback;
02503 }
02504 }
02505
02506 Solver::IndexEvaluator3* RoutingModel::BuildCostCallback() {
02507 return NewPermanentCallback(this, &RoutingModel::GetCost);
02508 }
02509
02510 IntVar** RoutingModel::GetOrMakeCumuls(int64 capacity, const string& name) {
02511 IntVar** named_cumuls = FindPtrOrNull(cumuls_, name);
02512 if (named_cumuls == NULL) {
02513 std::vector<IntVar*> cumuls;
02514 const int size = Size() + vehicles_;
02515 solver_->MakeIntVarArray(size, 0LL, capacity, name, &cumuls);
02516 IntVar** cumul_array = solver_->RevAllocArray(new IntVar*[size]);
02517 memcpy(cumul_array, cumuls.data(), cumuls.size() * sizeof(*cumuls.data()));
02518 cumuls_[name] = cumul_array;
02519 return cumul_array;
02520 }
02521 return named_cumuls;
02522 }
02523
02524 int64 RoutingModel::WrappedEvaluator(NodeEvaluator2* evaluator,
02525 int64 from,
02526 int64 to) {
02527 return evaluator->Run(IndexToNode(from), IndexToNode(to));
02528 }
02529
02530 IntVar** RoutingModel::GetOrMakeTransits(NodeEvaluator2* evaluator,
02531 int64 slack_max,
02532 int64 capacity,
02533 const string& name) {
02534 evaluator->CheckIsRepeatable();
02535 IntVar** named_transits = FindPtrOrNull(transits_, name);
02536 if (named_transits == NULL) {
02537 std::vector<IntVar*> transits;
02538 const int size = Size();
02539 IntVar** transit_array = solver_->RevAllocArray(new IntVar*[size]);
02540 for (int i = 0; i < size; ++i) {
02541 IntVar* fixed_transit =
02542 solver_->MakeElement(NewPermanentCallback(
02543 this,
02544 &RoutingModel::WrappedEvaluator,
02545 evaluator,
02546 static_cast<int64>(i)),
02547 nexts_[i])->Var();
02548 if (slack_max == 0) {
02549 transit_array[i] = fixed_transit;
02550 } else {
02551 IntVar* slack_var = solver_->MakeIntVar(0, slack_max, "slack");
02552 transit_array[i] = solver_->MakeSum(slack_var, fixed_transit)->Var();
02553 }
02554 transit_array[i]->SetMin(-capacity);
02555 transit_array[i]->SetMax(capacity);
02556 }
02557 transits_[name] = transit_array;
02558 transit_evaluators_[name] =
02559 NewPermanentCallback(this,
02560 &RoutingModel::WrappedEvaluator,
02561 evaluator);
02562 owned_index_callbacks_.insert(transit_evaluators_[name]);
02563 owned_node_callbacks_.insert(evaluator);
02564 return transit_array;
02565 }
02566 return named_transits;
02567 }
02568 }