vrpRouting  0.3
optimizers/tabu.cpp
Go to the documentation of this file.
1 /*PGR-GNU*****************************************************************
2 
3 FILE: tabu.cpp
4 
5 Copyright (c) 2021 pgRouting developers
7 
8 Developer:
9 Copyright (c) 2021 Joseph Emile Honour Percival
10 
11 ------
12 
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
17 
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22 
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 
27  ********************************************************************PGR-GNU*/
28 
29 #include "optimizers/tabu.h"
30 
31 #include <algorithm>
32 #include <string>
33 #include <deque>
34 
35 #include "cpp_common/pgr_assert.h"
37 
38 #include "optimizers/move.h"
39 
43 namespace {
44 
48 set_unassignedOrders(const std::deque<vrprouting::problem::Vehicle_pickDeliver> &fleet) {
49  Identifiers<size_t> unassigned_orders;
50  for (const auto &v : fleet) {
51  if (v.is_phony()) unassigned_orders += v.orders_in_vehicle();
52  }
53  return unassigned_orders;
54 }
55 
62 bool
63 are_all_served(const Identifiers<size_t> &unassigned) {
64  return unassigned.empty();
65 }
66 } // namespace
67 
68 namespace vrprouting {
69 namespace optimizers {
70 namespace tabu {
71 
96  const problem::Solution &old_solution,
97  size_t max_cycles,
98  bool stop_on_all_served,
99  bool optimize) :
100  problem::Solution(old_solution),
101  best_solution(old_solution),
102  m_max_cycles(max_cycles),
103  m_stop_on_all_served(stop_on_all_served),
104  m_optimize(optimize) {
105  ENTERING(msg());
106 
107  /*
108  * this function does the actual work
109  */
110  tabu_search();
111 
112  /*
113  * delete empty phony trucks
114  */
116 
117  /*
118  * Save best fleet/order structure found
119  */
120  this->m_fleet = best_solution.fleet();
121 
122  msg().log << tau("Best solution found");
123  EXITING(msg());
124 }
125 
133 bool
135  ENTERING(msg());
136  /*
137  * nothing to do:
138  * - No orders pending on phony vehicle
139  */
140  if (are_all_served(m_unassignedOrders)) return false;
142 
143  bool moves_were_done(false);
144 
145  /*
146  * cycling to find phony vehicles
147  */
148  for (auto &phony_vehicle : m_fleet) {
149  /*
150  * skip
151  * - real vehicle
152  * - empty vehicle
153  */
154  if (phony_vehicle.is_real() || phony_vehicle.empty()) continue;
155  pgassert(phony_vehicle.is_phony() && !phony_vehicle.empty());
156 
157 
158  auto orders_in_phony_vehicle = phony_vehicle.orders_in_vehicle();
159  for (const auto o_id : orders_in_phony_vehicle) {
160  /*
161  * get the order to be inserted on a real vehicle
162  */
163  double best_score = 0;
164  auto order = orders()[o_id];
165 
166  auto best_vehicle_ref = &phony_vehicle;
167 
168  for (auto &real_vehicle : m_fleet) {
169  /*
170  * skip when:
171  * - destination vehicle is the current vehicle
172  * - destination vehicle is phony
173  * - When current order is not feasible on real vehicle
174  */
175  if (&phony_vehicle == &real_vehicle) continue;
176  if (real_vehicle.is_phony()) continue;
177  if (!real_vehicle.feasible_orders().has(o_id)) continue;
178  if (real_vehicle.has_order(order)) continue;
179 
180  pgassert(&phony_vehicle != &real_vehicle);
181  pgassert(real_vehicle.is_real());
182 
183  /*
184  * setup local working vehicles
185  */
186  auto real_vehicle_copy = real_vehicle;
187 
188  /* current travel_time */
189  auto curr_travel_time = phony_vehicle.total_travel_time() + real_vehicle_copy.total_travel_time();
190 
191  /*
192  * insert order on destination vehicle
193  */
194  pgassert(!real_vehicle_copy.has_order(order));
195  real_vehicle_copy.hillClimb(order);
196 
197  // either the to vehicle has the and is feasible OR it does not have the order
198  pgassert((real_vehicle_copy.has_order(order) && real_vehicle_copy.is_feasible())
199  || !real_vehicle_copy.has_order(order));
200 
201  /*
202  * Skip to next order if the order wasnt inserted
203  */
204  if (!real_vehicle_copy.has_order(order)) continue;
205  pgassert(real_vehicle_copy.has_order(order));
206 
207  auto new_travel_time = phony_vehicle.total_travel_time() + real_vehicle_copy.total_travel_time();
208  auto delta_travel_time = new_travel_time - curr_travel_time;
209 
210  auto delta_objective = delta_travel_time;
211  auto estimated_objective = objective() + static_cast<double>(delta_objective);
212 
213 
214  if (best_score == 0 || estimated_objective < best_score) {
215  best_score = estimated_objective;
216  best_vehicle_ref = &real_vehicle;
217  }
218  } // to_v
219 
220  if (best_score != 0) {
221  pgassert(best_vehicle_ref != &phony_vehicle);
222  phony_vehicle.erase(order);
223  best_vehicle_ref->hillClimb(order);
224  m_unassignedOrders -= order.idx();
225  best_solution = (*this);
226  moves_were_done = true;
227  }
228  } // orders
229  } // from phony
230  EXITING(msg());
231  if (moves_were_done) tabu_list.clear();
232  return moves_were_done;
233 }
234 
240 void
242  auto max_length = std::max(orders().size(), m_standard_limit);
243  tabu_list.set_max_length(max_length);
244 }
245 
246 
273 void
275  ENTERING(msg());
276 
277  sort_by_size(true);
278 
280 
281  move_2_real();
283  /*
284  * stop if no optimization is asked
285  */
286  if (!m_optimize) return;
287 
288  /*
289  * stop if all orders are served
290  */
292 
294  /*
295  * Do the cycles
296  */
297  /*
298  * initialize the iterator counter
299  */
300  size_t iter = 0;
301 
302  int no_moves = 0;
303 
304  int max_no_moves = 2;
305 
306  int max_no_swaps = 2;
307 
308  bool diversification = true;
309 
310  bool intensification = false;
311 
312  bool do_spi = true;
313 
314  int could_not_spi = 0;
315 
316  int stuck_counter = 0;
317 
318  int wander_counter = 0;
319 
320  int max_no_improvement = 1000;
321 
322  std::string neighborhood;
323 
324  int wander_length = 100;
325 
326  while (iter < m_max_cycles) {
327  double curr_best = best_solution.objective();
328 
329  if (stuck_counter == max_no_improvement) {
330  intensify();
331  if (best_solution.objective() == curr_best)
332  break;
333  }
334 
335  if (no_moves < max_no_moves && do_spi) {
336  neighborhood = "spi";
337  } else {
338  neighborhood = "sbr";
339  }
340 
341  bool moved;
342 
343  if (neighborhood == "spi") {
344  moved = single_pair_insertion(false, false);
346  if (moved) {
348  }
349  } else {
350  moved = swap_between_routes(false, false);
351  if (moved) {
353  }
354  }
355 
357 
358  if (!moved) {
359  no_moves += 1;
360  if (neighborhood == "spi") {
361  could_not_spi += 1;
362  }
363  if (neighborhood == "sbr") {
364  intensify();
365  }
366  } else {
367  no_moves = 0;
368  }
369 
370  if (no_moves >= max_no_swaps + max_no_moves) break;
371 
373 
374  /*
375  * check for aimless wandering ...
376  */
377  if (curr_best == best_solution.objective()) {
378  stuck_counter += 1;
379  wander_counter += 1;
380  if (stuck_counter % wander_length == 0) {
381  intensification = !intensification;
382  diversification = !diversification;
383 
384  if (intensification) {
385  intensify();
386  }
387  if (diversification) {
388  diversify();
389  }
390  }
391  } else {
392  // if it is not the same then it must be better!
393  stuck_counter = 0;
394  }
395  iter++;
396  }
397  EXITING(msg());
398 }
399 
400 
407 void
410 
411  bool do_spi = true;
412  bool do_sbr = true;
413 
414  int max_iter = 20;
415  int i = 0;
416  while (do_spi && i < max_iter) {
417  do_spi = single_pair_insertion(true, false);
418  if (do_spi) if (!are_all_served(m_unassignedOrders)) move_2_real();
419  i++;
420  }
421  i = 0;
422  while (do_sbr && i < max_iter) {
423  do_sbr = swap_between_routes(true, false);
424  if (do_spi) if (!are_all_served(m_unassignedOrders)) move_2_real();
425  i++;
426  }
427 }
428 
429 
436 bool
438  /*
439  * set the number of maximum swaps between routes for diversification
440  */
441  size_t max_swaps = std::min(m_fleet.size(), orders().size() / 10);
442  size_t s = 0;
443  bool swaps_were_done = true;
444  while (swaps_were_done && s < max_swaps) {
445  swaps_were_done = single_pair_insertion(false, true);
446  if (!swaps_were_done) {
447  swaps_were_done = swap_between_routes(false, true);
448  }
449  if (!swaps_were_done) {
450  swaps_were_done = swap_between_routes(false, false);
451  }
452  if (swaps_were_done) if (!are_all_served(m_unassignedOrders)) move_2_real();
453  s++;
454  }
455  return swaps_were_done;
456 }
457 
458 
459 
467 bool
468 Optimize::single_pair_insertion(bool intensify, bool diversify) {
469  sort_by_size(true);
470  auto best_to_v = &m_fleet[0];
471  auto best_from_v = &m_fleet[0];
472  double best_score = intensify ? objective() : 0;
473  double best_to_score;
474  double best_from_score;
475  bool moved = false;
476  auto best_order = orders()[0];
477  bool has_phony = false;
478 
479  std::string best_candidate;
480 
481  for (auto &from_vehicle : m_fleet) {
482  if (from_vehicle.is_phony() || from_vehicle.empty()) continue;
483 
484  auto first_order_set = from_vehicle.orders_in_vehicle();
485  for (const auto o_id : first_order_set) {
486  auto order = orders()[o_id];
487  for (auto &to_v : m_fleet) {
488  if (&from_vehicle == &to_v) continue;
489  if (to_v.is_phony()) {
490  has_phony = true;
491  }
492  if (to_v.is_phony()) continue;
493  if (!has_phony && to_v.empty()) continue;
494 
495  if (!to_v.feasible_orders().has(o_id)) continue;
496 
497  std::ostringstream ss;
498 
499  ss << to_v.path_str() << ":" << o_id;
500 
501  std::string candidate = ss.str();
502 
503  if (tabu_list.has_infeasible(candidate)) continue;
504 
505  if (diversify && tabu_list.has_seen(candidate)) continue;
506 
507  /*
508  * setup local working vehicles
509  */
510  auto to_v_copy = to_v;
511  auto from_v_copy = from_vehicle;
512 
513  /* current travel_time */
514  auto curr_travel_time = from_v_copy.total_travel_time() + to_v_copy.total_travel_time();
515 
516  /*
517  * insert order on destination vehicle
518  */
519  pgassert(!to_v_copy.has_order(order));
520  to_v_copy.hillClimb(order);
521 
522  // either the to vehicle has the order and is feasible OR it does not have the order
523  pgassert((to_v_copy.has_order(order) && to_v_copy.is_feasible()) || !to_v_copy.has_order(order));
524 
525  /*
526  * Skip to next order if the order wasn't inserted
527  */
528  if (!to_v_copy.has_order(order)) {
529  tabu_list.add_infeasible(candidate);
530  continue;
531  }
532 
533  from_v_copy.erase(order);
534  if (from_v_copy.has_order(order) || !from_v_copy.is_feasible()) continue;
535 
536  auto new_travel_time = from_v_copy.total_travel_time() + to_v_copy.total_travel_time();
537  auto delta_travel_time = new_travel_time - curr_travel_time;
538 
539  auto delta_objective = delta_travel_time;
540  auto estimated_objective = objective() + static_cast<double>(delta_objective);
541 
542  /*
543  * evaluate the move
544  */
545  if (estimated_objective >= best_score && !from_v_copy.empty() && best_score != 0) continue;
546 
547  if (tabu_list.has_move(
548  from_v_copy, to_v_copy, order, to_v_copy.objective(),
549  from_v_copy.objective())
550  && estimated_objective >= best_solution.objective()
551  && !from_v_copy.empty()) continue;
552 
553  if (estimated_objective < best_score || from_v_copy.empty() || best_score == 0) {
554  moved = true;
555  best_score = estimated_objective;
556  best_to_score = to_v.objective();
557  best_from_score = from_vehicle.objective();
558  best_to_v = &to_v;
559  best_from_v = &from_vehicle;
560  best_order = order;
561  best_candidate = candidate;
562  }
563  } // to vehicles
564  } // orders
565  } // from vehicles
566 
567  if (moved) {
568  tabu_list.add(Move((*best_from_v), (*best_to_v), best_order, best_to_score, best_from_score));
569  best_to_v->hillClimb(best_order);
570  best_from_v->erase(best_order);
571  tabu_list.add_seen(best_candidate);
572  if (best_from_v->is_phony()) m_unassignedOrders -= best_order.idx();
573  save_if_best();
574  }
575  return moved;
576 }
577 
578 
586 bool
587 Optimize::swap_between_routes(bool intensify, bool diversify) {
588  sort_by_size(false);
589  auto best_to_v = &m_fleet[0];
590  auto best_from_v = &m_fleet[0];
591  double best_score = intensify ? objective() : 0;
592  double best_to_score;
593  double best_from_score;
594  bool swapped = false;
595  auto best_from_order = orders()[0];
596  auto best_to_order = orders()[0];
597 
598  std::string best_candidate1;
599  std::string best_candidate2;
600 
601  for (size_t i = 0; i < m_fleet.size(); ++i) {
602  problem::Vehicle_pickDeliver &from_vehicle = m_fleet[i];
603  if (from_vehicle.is_phony() || from_vehicle.empty()) continue;
604 
605  auto first_order_set = from_vehicle.orders_in_vehicle();
606  for (const auto o_id1 : first_order_set) {
607  auto order1 = orders()[o_id1];
608  for (size_t j = i + 1; j < m_fleet.size(); ++j) {
610  if (&from_vehicle == &to_v) continue;
611  if (to_v.is_phony() || to_v.empty()) continue;
612  if (!to_v.feasible_orders().has(o_id1)) continue;
613 
614 
615  /*
616  * cycle through to orders for swap
617  */
618  auto second_order_set = to_v.orders_in_vehicle();
619  for (const auto o_id2 : second_order_set) {
620  auto order2 = orders()[o_id2];
621  if (!from_vehicle.feasible_orders().has(o_id2)) continue;
622 
623  auto curr_from_objective = from_vehicle.objective();
624  auto curr_to_objective = to_v.objective();
625 
626  /*
627  * setup local working vehicles
628  */
629  auto from_v_copy = from_vehicle;
630  auto to_v_copy = to_v;
631 
632 
633  pgassert(from_v_copy.has_order(order1));
634  pgassert(to_v_copy.has_order(order2));
635 
636 
637  /*
638  * do one truck at a time
639  */
640  to_v_copy.erase(order2);
641  if (to_v_copy.orders_in_vehicle().has(o_id2) || !to_v_copy.is_feasible()) continue;
642 
643  std::ostringstream ss1;
644  ss1 << to_v_copy.path_str() << ":" << o_id1;
645 
646  std::string candidate1 = ss1.str();
647 
648  if (tabu_list.has_infeasible(candidate1)) continue;
649 
650  from_v_copy.erase(order1);
651  if (from_v_copy.orders_in_vehicle().has(o_id1) || !from_v_copy.is_feasible()) continue;
652 
653  std::ostringstream ss2;
654  ss2 << from_v_copy.path_str() << ":" << o_id2;
655 
656  std::string candidate2 = ss2.str();
657 
658  if (diversify && tabu_list.has_seen(candidate1) && tabu_list.has_seen(candidate2)) continue;
659 
660  if (tabu_list.has_infeasible(candidate2)) continue;
661 
662  to_v_copy.hillClimb(order1);
663  if (!to_v_copy.has_order(order1) || !to_v_copy.is_feasible()) {
664  tabu_list.add_infeasible(candidate1);
665  continue;
666  }
667 
668 
669  from_v_copy.hillClimb(order2);
670  if (!from_v_copy.has_order(order2) || !from_v_copy.is_feasible()) {
671  tabu_list.add_infeasible(candidate2);
672  continue;
673  }
674 
675 
676  /*
677  * Evaluate the swap
678  */
679  auto new_from_objective = from_v_copy.objective();
680  auto new_to_objective = to_v_copy.objective();
681 
682  auto estimated_delta =
683  +(new_to_objective + new_from_objective)
684  - (curr_from_objective + curr_to_objective);
685 
686  auto estimated_objective = objective() + estimated_delta;
687  /*
688  * dont swap if there is no improvement in either vehicle
689  */
690  if (estimated_objective >= best_score && best_score != 0) continue;
691 
692  if (tabu_list.has_swap(
693  from_v_copy, to_v_copy, order1, order2, from_v_copy.objective(),
694  to_v_copy.objective())
695  && estimated_objective >= best_solution.objective()) continue;
696 
697 
698  if (estimated_objective < best_score || best_score == 0) {
699  swapped = true;
700  best_from_score = from_vehicle.objective();
701  best_to_score = to_v.objective();
702  best_score = estimated_objective;
703  best_to_v = &to_v;
704  best_from_v = &from_vehicle;
705  best_from_order = order1;
706  best_to_order = order2;
707  best_candidate1 = candidate1;
708  best_candidate2 = candidate2;
709  }
710  }
711  } // to vehicles
712  } // orders
713  } // from vehicles
714  if (swapped) {
715  tabu_list.add(
716  Move((*best_from_v), (*best_to_v), best_from_order, best_to_order, best_to_score, best_from_score));
717  best_from_v->erase(best_from_order);
718  best_to_v->erase(best_to_order);
719  best_from_v->hillClimb(best_to_order);
720  best_to_v->hillClimb(best_from_order);
721  tabu_list.add_seen(best_candidate1);
722  tabu_list.add_seen(best_candidate2);
723  if (best_from_v->is_phony()) {
724  m_unassignedOrders -= best_from_order.idx();
725  m_unassignedOrders += best_to_order.idx();
726  }
727  if (best_to_v->is_phony()) {
728  m_unassignedOrders -= best_to_order.idx();
729  m_unassignedOrders += best_from_order.idx();
730  }
731  save_if_best();
732  }
733  return swapped;
734 }
735 
736 #if 1
737 
741 void
743  /*
744  * sort by number of orders on the vehicles
745  */
746  if (asc) {
747  std::sort(m_fleet.begin(), m_fleet.end(), []
749  -> bool {
750  if (lhs.orders_in_vehicle().size() == rhs.orders_in_vehicle().size()) {
751  return lhs.id() < rhs.id();
752  } else {
753  return lhs.orders_in_vehicle().size() < rhs.orders_in_vehicle().size();
754  }
755  });
756  } else {
757  std::sort(m_fleet.begin(), m_fleet.end(), []
759  -> bool {
760  if (lhs.orders_in_vehicle().size() == rhs.orders_in_vehicle().size()) {
761  return lhs.id() > rhs.id();
762  } else {
763  return lhs.orders_in_vehicle().size() > rhs.orders_in_vehicle().size();
764  }
765  });
766  }
767 
768 
769  /*
770  * Leave the phony vehicles at the beginning
771  */
772  std::stable_partition(m_fleet.begin(), m_fleet.end(), []
774  -> bool {
775  return v.id() < 0;
776  });
777 }
778 #endif
779 
787 void
788 Optimize::delete_empty_truck() {
789  /*
790  * remove from the fleet vehicles that are phony and empty
791  */
792  m_fleet.erase(std::remove_if(
793  m_fleet.begin(),
794  m_fleet.end(),
795  [](const problem::Vehicle_pickDeliver &v){
796  return v.orders_in_vehicle().empty() && v.is_phony();}),
797  m_fleet.end());
798 }
799 
800 
804 void
805 Optimize::save_if_best() {
806  if (objective() < best_solution.objective()) {
807  best_solution = (*this);
808  msg().log << "\t*** best objective " << best_solution.cost_str();
809  }
810 }
811 
812 } // namespace tabu
813 } // namespace optimizers
814 } // namespace vrprouting
vrprouting::problem::Solution
Definition: solution.h:50
vrprouting::problem::Solution::orders
const Orders & orders() const
Definition: solution.h:120
vrprouting::optimizers::tabu::Optimize::save_if_best
void save_if_best()
save a new found solution only if it is best
Definition: optimizers/tabu.cpp:805
vrprouting::optimizers::tabu::TabuList::has_seen
bool has_seen(const std::string &candidate)
Checks to see if a move candidate has already been done before (in the seen list)
Definition: tabu_list.cpp:158
move.h
EXITING
#define EXITING(x)
Definition: pgr_messages.h:105
vrprouting::Pgr_messages::log
std::ostringstream log
Stores the hint information.
Definition: pgr_messages.h:91
vrprouting::problem::Vehicle_pickDeliver::feasible_orders
Identifiers< size_t > & feasible_orders()
returns the set of feasible orders for modification
Definition: vehicle_pickDeliver.h:100
vrprouting::optimizers::tabu::Optimize::best_solution
problem::Solution best_solution
The best solution so far.
Definition: optimizers/tabu.h:57
pgr_messages.h
vrprouting::problem::Solution::objective
double objective() const
Get the value of the objective function.
Definition: solution.h:110
vrprouting::problem::Solution::m_fleet
std::deque< Vehicle_pickDeliver > m_fleet
The current solution.
Definition: solution.h:125
vrprouting::optimizers::tabu::Optimize::swap_between_routes
bool swap_between_routes(bool intensify, bool diversify)
Swapping pairs Between Routes: initiate directed or undirected swaps of orders between vehicles.
Definition: optimizers/tabu.cpp:587
vrprouting::optimizers::tabu::TabuList::has_move
bool has_move(const problem::Vehicle_pickDeliver &, const problem::Vehicle_pickDeliver &, const problem::Order &from_order, double obj1, double obj2) const
Checks to see if a "move" move is "tabu" (in the tabu list)
Definition: tabu_list.cpp:73
vrprouting::optimizers::tabu::Optimize::tabu_list
TabuList tabu_list
Tabu lists of the problem.
Definition: optimizers/tabu.h:61
anonymous_namespace{tabu.cpp}::set_unassignedOrders
Identifiers< size_t > set_unassignedOrders(const std::deque< vrprouting::problem::Vehicle_pickDeliver > &fleet)
set of unassigned orders
Definition: optimizers/tabu.cpp:48
tabu.h
ENTERING
#define ENTERING(x)
Definition: pgr_messages.h:104
vrprouting::optimizers::tabu::Optimize::single_pair_insertion
bool single_pair_insertion(bool intensify, bool diversify)
Single Pair Insertion: move order from one vehicle to another that reduces objective value.
Definition: optimizers/tabu.cpp:468
anonymous_namespace{tabu.cpp}::are_all_served
bool are_all_served(const Identifiers< size_t > &unassigned)
Are all orders served?
Definition: optimizers/tabu.cpp:63
vrprouting::optimizers::tabu::Optimize::intensify
void intensify()
Intensify the search.
Definition: optimizers/tabu.cpp:408
vrprouting::problem::Vehicle::is_phony
bool is_phony() const
Definition: vehicle.cpp:116
vrprouting::optimizers::tabu::Move
The Move class defines moves that are evaluated and set as tabu.
Definition: move.h:46
pgassert
#define pgassert(expr)
Uses the standard assert syntax.
Definition: pgr_assert.h:95
vrprouting::optimizers::tabu::Optimize::move_2_real
bool move_2_real()
moves orders from phony vehicles to a real vehicle
Definition: optimizers/tabu.cpp:134
vrprouting::optimizers::tabu::Optimize::sort_by_size
void sort_by_size(bool asc)
Definition: optimizers/tabu.cpp:742
vrprouting::optimizers::tabu::Optimize::m_unassignedOrders
Identifiers< size_t > m_unassignedOrders
Set of unassigned orders.
Definition: optimizers/tabu.h:105
vrprouting::problem::Vehicle_pickDeliver::objective
double objective() const
Get the value of the objective function.
Definition: vehicle_pickDeliver.cpp:321
vrprouting::optimizers::tabu::Optimize::delete_empty_truck
void delete_empty_truck()
deletes phony vehicles that are empty
Definition: optimizers/tabu.cpp:788
vrprouting::optimizers::tabu::TabuList::clear
void clear()
removes all moves from the tabu list
Definition: tabu_list.cpp:50
vrprouting::optimizers::tabu::TabuList::add_infeasible
void add_infeasible(const std::string &candidate)
Adds a move candidate to the infeasible list.
Definition: tabu_list.cpp:154
vrprouting::optimizers::tabu::Optimize::diversify
bool diversify()
Diversify the search.
Definition: optimizers/tabu.cpp:437
vrprouting::optimizers::tabu::Optimize::m_stop_on_all_served
bool m_stop_on_all_served
Flag to stop when all orders are in real vehicles.
Definition: optimizers/tabu.h:90
vrprouting::problem::Vehicle_pickDeliver
Definition: vehicle_pickDeliver.h:46
Identifiers::empty
bool empty() const
Definition: identifiers.hpp:78
vrprouting::problem::Solution::fleet
const std::deque< Vehicle_pickDeliver > & fleet() const
Get the current fleet solution.
Definition: solution.h:107
pgr_assert.h
An assert functionality that uses C++ throw().
vrprouting::problem::Solution::msg
Pgr_messages & msg()
Definition: solution.h:119
vrprouting::optimizers::tabu::TabuList::has_swap
bool has_swap(const problem::Vehicle_pickDeliver &, const problem::Vehicle_pickDeliver &, const problem::Order &, const problem::Order &, double obj1, double obj2) const
Checks to see if a "swap" move is "tabu" (in the tabu list)
Definition: tabu_list.cpp:91
vrprouting::problem::Solution::tau
std::string tau(const std::string &title="Tau") const
writing the solution in compact form into a string
Definition: solution.cpp:116
vrprouting::optimizers::tabu::Optimize::m_standard_limit
size_t m_standard_limit
Limit for a cycle.
Definition: optimizers/tabu.h:96
vrprouting::optimizers::tabu::Optimize::m_optimize
bool m_optimize
Flag to just build a solution and not optimize it.
Definition: optimizers/tabu.h:93
vrprouting::optimizers::tabu::TabuList::set_max_length
void set_max_length(size_t length)
sets the maximum length (tabu_length) of the tabu list
Definition: tabu_list.cpp:131
vrprouting::optimizers::tabu::Optimize::Optimize
Optimize(const problem::Solution &solution, size_t times, bool stop_on_all_served, bool)
Optimization operation.
Definition: optimizers/tabu.cpp:95
vrprouting::optimizers::tabu::Optimize::set_tabu_list_length
void set_tabu_list_length()
set tabu length
Definition: optimizers/tabu.cpp:241
vrprouting::optimizers::tabu::TabuList::add_seen
void add_seen(const std::string &candidate)
Adds a move candidate to the seen list.
Definition: tabu_list.cpp:162
Identifiers::has
bool has(const T other) const
true ids() has element
Definition: identifiers.hpp:100
vrprouting::optimizers::tabu::TabuList::add
void add(const Move &m)
Make a move "tabu" by adding it to the tabu list.
Definition: tabu_list.cpp:42
vrprouting::optimizers::tabu::Optimize::m_max_cycles
size_t m_max_cycles
Maximum number of cycles on the optimization process.
Definition: optimizers/tabu.h:87
Identifiers< size_t >
vrprouting::problem::Vehicle_pickDeliver::empty
bool empty() const
Definition: vehicle.cpp:112
vrprouting::problem::Vehicle_pickDeliver::orders_in_vehicle
Identifiers< size_t > orders_in_vehicle() const
returns the number of orders in the vehicle
Definition: vehicle_pickDeliver.h:105
vrprouting::optimizers::tabu::TabuList::has_infeasible
bool has_infeasible(const std::string &candidate)
Checks to see if a move candidate is infeasible (in the infeasible list)
Definition: tabu_list.cpp:150
vrprouting::optimizers::tabu::Optimize::tabu_search
void tabu_search()
Main optimization controller.
Definition: optimizers/tabu.cpp:274
vrprouting
Definition: base_matrix.cpp:46